首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

MFC對話框驗證革命:正則表達式與CRegexForm表單驗證框架實戰

     編輯:關於C語言

一、傳統DDX/DDV的痛點

MFC提供DDX_Text資料交換與DDV_MaxChars/DDV_MinMaxInt基礎驗證,但:

  • 無法驗證郵遞區號、電話、信用卡等複雜格式
  • 每個錯誤彈出獨立訊息框,多錯誤體驗極差
  • 驗證邏輯硬編碼在DoDataExchange,函數膨脹難維護
  • 缺乏使用者引導 (工具提示、即時字元過濾、錯誤回饋視窗)

二、正則表達式驗證的引入

自訂DDV_Regex


void DDV_Regex(CDataExchange* pDX, CString& val, LPCTSTR pszRegex) {
    if (pDX->m_bSaveAndValidate) {
        CMRegex regex(pszRegex);
        if (!regex.Match(val).Success()) {
            pDX->Fail();  // 拋出例外,終止DDX
        }
    }
}

// 使用範例:郵遞區號 (##### 或 #####-####)
DDX_Text(pDX, IDC_ZIP, m_zip);
DDV_Regex(pDX, m_zip, _T("^\\d{5}(-\\d{4})?$"));

雖解決格式驗證,但仍遺留DDX/DDV架構缺陷。

三、CRegexForm:規則引導、表格驅動的完整解決方案

核心特性

  • 單一錯誤訊息框:彙總所有無效欄位
  • 即時字元過濾:非法字元直接拒絕並蜂鳴
  • 智慧工具提示:Tab移動時顯示輸入格式範例
  • 錯誤回饋視窗:對話框內固定區域顯示當前欄位錯誤
  • 資源字串驅動:驗證規則外部化,支援在地化

欄位對應表定義 (巨集)


BEGIN_REGEX_FORM(MyRegexForm)
    RGXFIELD(IDC_ZIP,      RGXF_REQUIRED, 0)                    // 必填
    RGXFIELD(IDC_SSN,      0, 0)                                  // 選填
    RGXFIELD(IDC_PHONE,    0, 0)
    RGXFIELD(IDC_TOKEN,    0, 0)
    RGXFIELD(IDC_PRIME,    RGXF_CALLBACK, 0)                     // 回調驗證
    RGXFIELD(IDC_FAVCOL,   0, CMRegex::IgnoreCase)               // 不分大小寫
END_REGEX_FORM()

資源字串格式 (五段式,換行分隔)


// IDC_ZIP 對應資源字串
"Zip Code\n^\\d{5}(-\\d{4})?$\n[\\d-]\n##### or #####-####\n"
// 解析:
// 1. 欄位名稱: "Zip Code"
// 2. 驗證Regex: "^\\d{5}(-\\d{4})?$"  (資源中需雙重轉義 \\\\d)
// 3. 合法字元Regex: "[\\d-]"  (即時過濾用,空白表示不限制)
// 4. 工具提示: "##### or #####-####"
// 5. 錯誤訊息: (空白則自動產生 "Should be ##### or #####-####")

四、CRegexForm核心實作架構

關鍵類別成員


class CRegexForm {
    struct FIELD_INFO {
        int nCtrlID;        // 控制項ID
        DWORD dwFlags;      // RGXF_REQUIRED, RGXF_CALLBACK...
        DWORD dwRegexOpt;   // CMRegex選項
        CString strName;    // 欄位名稱
        CMRegex regexVal;   // 驗證正則
        CMRegex regexChar;  // 字元過濾正則
        CString strHint;    // 工具提示
        CString strErrMsg;  // 自訂錯誤訊息
    };
    CArray m_fields;
    CToolTipCtrl m_tooltip;
    CEdit m_feedbackWnd;    // 錯誤回饋視窗
    // ...
};

核心流程

  1. 初始化:讀取巨集表與資源字串,編譯正則,建立ToolTip
  2. 字元級過濾:子類化編輯控制項,EN_UPDATE中以regexChar驗證新字元,非法則MessageBeep並撤銷
  3. 焦點切換提示:WM_SETFOCUS顯示strHint工具提示
  4. 整體驗證:OnOK中遍歷所有欄位,regexVal.Match()失敗收集錯誤
  5. 錯誤呈現:單一訊息框列出所有錯誤 → 使用者Tab到錯誤欄位 → m_feedbackWnd顯示詳細錯誤

五、回調驗證擴展 (RGXF_CALLBACK)

針對正則無法表達的邏輯 (如質數驗證):


// 巨集標記 RGXF_CALLBACK
// 衍生類別覆寫虛擬函數
virtual BOOL OnRegexCallback(int nCtrlID, const CString& strValue, CString& strErrMsg) {
    if (nCtrlID == IDC_PRIME) {
        long n = _ttol(strValue);
        if (n < 2 || !IsPrime(n)) {
            strErrMsg = _T("必須為質數");
            return FALSE;
        }
    }
    return TRUE;
}

六、在地化優勢

所有使用者可見字串 (名稱、提示、錯誤訊息) 集中在資源檔,翻譯時無需修改程式碼,甚至可執行期切換語言資源 DLL。

總結

CRegexForm將MFC對話框驗證從「程序式硬編碼」昇級為「宣告式表格驅動」,結合正則表達式表達力與豐富互動體驗 (即時過濾、工具提示、彙總錯誤、回饋視窗),並解決在地化難題。這是「拒絕程序化代碼、一個表格勝過千行代碼」原則的最佳實踐。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved