欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
VC知識庫文章 - 在MFC中用正則表達式對窗體進(jìn)行有效性驗證

在MFC中用正則表達式對窗體進(jìn)行有效性驗證

原著(zhù):Paul DiLascia
翻譯:Northxizang

下載源代碼:CATWork0504.exe (248KB)
原文出處:C++At Work: Form Validation with Regular Expressions in MFC

本文發(fā)布后有更新參見(jiàn)文中的:[編輯更新]

我想利用本月的專(zhuān)欄描述一個(gè)有趣的應用程序,這個(gè)程序是用本期我的一篇文章:“使用ManWrap 庫在本機 C++ 代碼中調用.NET”所討論的 RegexWrap 庫生成的。RegexForm 是一個(gè)基于正則表達式的MFC窗體有效性驗證系統。為了實(shí)現這個(gè)程序,我首先實(shí)現了RegexWrap。但因為許多細節與正則表達式本身無(wú)關(guān),所以感覺(jué)在這里描述 RegexForm 更好些。
正如我在這篇文章中所言,正則表達式最實(shí)用的一個(gè)地方是驗證用戶(hù)輸入。它可以輕松驗證郵編、電話(huà)號碼、信用卡號碼——以及現實(shí)世界中各種類(lèi)型的信息。一個(gè)正則表達式可以替換成打甚至上百行過(guò)程代碼。UNIX和 Web 編程語(yǔ)言如 Perl從一開(kāi)始就有正則表達式,但在 Windows 世界或MFC,從來(lái)都是使用第三方庫,一直到 .NET框架才結束這個(gè)局面。[編輯更新——3/15/2005:ATL Server Library 中的 CAtlRegExp 和CAtlREMatchContext 類(lèi)為正則表達式提供支持。] 因此現在 .NET 提供一個(gè)完整的正則表達式庫,為什么不在MFC應用程序中使用它呢?并且利用我在前述文章中描述的RegexWrap 庫,你甚至都不需要托管擴展或 /clr。
MFC 已經(jīng)具備一種稱(chēng)為“對話(huà)框數據交換”(Dialog Data Exchange,即 DDX)以及“對話(huà)框數據驗證”(DialogData Validation,即 DDV)的機制來(lái)驗證對話(huà)框輸入。從技術(shù)上講,DDX 只是在屏幕和你的對話(huà)框對象之間傳輸數據,而 DDV才驗證數據。當你從對話(huà)框的 OnOK 處理例程中調用 UpdateData 時(shí) DDX 才開(kāi)始工作。

// user pressed OK:void CMyDialog::OnOK() {UpdateData(TRUE); // 獲得對話(huà)框數據...}

  UpdateData 是一個(gè)虛擬 CWnd函數,你可以在自己的對話(huà)框中重寫(xiě)這個(gè)函數。其布爾型(Boolean)參數告知是將信息拷貝到屏幕還是相反從屏幕拷貝信息。(你可以在OnInitDialog 中調用 UpdateData(FALSE)以便初始化對話(huà)框)。默認的 CWnd 實(shí)現創(chuàng )建一個(gè)CDataExchange 對象并將它傳遞到另一個(gè)虛擬函數,DoDataExchange,你得重寫(xiě)這個(gè)函數去調用專(zhuān)門(mén)的 DDX函數來(lái)為單獨的數據成員傳遞數據:

void CMyDialog::DoDataExchange(CDataExchange* pDX) {CDialog::DoDataExchange(pDX);DDX_Text(pDX, IDC_NAME, m_name);DDX_Text(pDX, IDC_AGE, m_age);...// etc.}

  這里 IDC_NAME 和 IDC_AGE 是編輯控制的 IDs,m_name 和 m_age 分別是 CString 和 int數據成員。DDX_Text 將用戶(hù)輸入的 Name 和 Age 拷貝到 m_name 和 m_age(用一個(gè)重載順便將 Age 轉變成int)。DDX 函數知道走哪條路,因為當從屏幕拷貝到對話(huà)框時(shí),CDataExchange::m_bSaveAndValidate 為T(mén)RUE,反之則為 FALSE。MFC 為各種數據和控制類(lèi)型加載 DDX 函數。例如,DDX_Text至少有一些重載函數用來(lái)將輸入文本拷貝和轉換成不同的類(lèi)型,如 CString、int、double、COleCurrency等等。DDX_Check 用來(lái)將復選框的狀態(tài)轉換成整型值,DDX_Radio 則對單選按鈕做同樣的事情。
DDX 函數傳輸數據;DDV 函數則驗證它。例如,為了限制用戶(hù)名稱(chēng)為 35個(gè)字符,你可以這樣做:

// in CMyDialog::DoDataExchangeDDX_Text(pDX, IDC_NAME, m_sName); // 獲得/設置值DDV_MaxChars(pDX, m_sName, 35); // 驗證

為了限定你的用戶(hù)年齡為 1-120之間的一個(gè)整數,你可以這樣寫(xiě):

// m_age is intDDX_Text(pDX, IDC_AGE, m_age);DDV_MinMaxInt(pDX, m_age, 1, 120);

  雖然 DDX 工作表現得很好,DDV 是不免有點(diǎn)老土。MFC在有效性驗證方面所能做到的很有限。你可以在文本域中限制數字字符,不同類(lèi)型的最小/最大約束。最小/最大是不錯,但如果你想驗證郵編或電話(huà)號碼怎么辦?MFC對此無(wú)能為力。你不得不編寫(xiě)自己的 DDV 函數。當我第一次用正則表達式實(shí)現有效性驗證時(shí),我只要寫(xiě)一個(gè)函數即可,就像這樣:

void DDV_Regex(CDataExchange* pDX, CString& val,LPCTSTR pszRegex){if (pDX->m_bSaveAndValidate) {CMRegex r(pszRegex);if (!r.Match(val).Success()) {pDX->Fail(); // throws exception}}}		

這使你很容易象下面這樣用正則表達式驗證輸入:

// in CMyDialog::DoDataExchangeDDX_Text(pDX, IDC_ZIP, m_zip);DDV_Regex(pDX, m_zip,_T("^\\d{5}(-\\d{4})?$"));

  好酷啊,僅用四行代碼就搞掂。(當然,那要假設你有 RegexWrap——否則你得使用托管擴展直接調用框架 Regex類(lèi)。)DDV_Regex 在 MFC 的 DDX/DDV 方案中工作表現很完美,但是當我開(kāi)始添加更多的域時(shí),我馬上發(fā)現一些 DDX/DDV的主要缺點(diǎn),其一,如果域輸入無(wú)效,則每個(gè) DDV函數都顯示一個(gè)出錯消息框并丟出異常,那么要是有五個(gè)無(wú)效域,用戶(hù)就會(huì )看到五個(gè)消息框——真實(shí)糟透了!此外,在對 DDV的調用中,我不想將正則表達式寫(xiě)死在代碼中。但我拒絕 DDX/DDV 的主要理由是它太程序化。為了驗證新的域,你不得不添加另外的數據成員以及在DoDataExchange 加更多的代碼,不久這個(gè)函數便膨脹臃腫,就像下面這樣:

DDX_Text(pDX, IDC_FOO,...);DDV_Mumble(pDX, ...)DDX_Text(pDX, IDC_BAR,...);DDV_Bletch(...)... // etc for 14 lines

為什么我非得要墨守成規編寫(xiě)過(guò)程指令來(lái)描述固有的驗證規則呢?我的五條編程最高準則之一是:拒斥程序化代碼。另一個(gè)是:一個(gè)表格勝過(guò)一千行代碼。你肯定猜到我要干什么了。最終,我編寫(xiě)自己的對話(huà)框驗證系統,一個(gè)基于規則的、表格驅動(dòng)的驗證系統。它依靠在DDX 的最上層,但廢掉了 DDV并有好得多的用戶(hù)接口。當然,它還易于使用,借助正則表達式進(jìn)行驗證。所有細節都封裝在一個(gè)類(lèi)中,CRegexForm,你可以在任何 MFC對話(huà)框中使用這個(gè)類(lèi)。


Figure 1 TestForm 里的工具提示

與往常一樣,我編寫(xiě)了一個(gè)測試程序來(lái)示范它的工作原理。初看起來(lái),TestForm 有點(diǎn)像再平常不過(guò)的基于 MFC的對話(huà)框程序。它的主對話(huà)框中有幾個(gè)編輯框——郵編、SSN(社會(huì )保險號),電話(huà)號碼等。但當你通過(guò)對 TestForm的測試,你會(huì )很快認識到它蘊含著(zhù)許多玄機。如果你用tab鍵在輸入域間移動(dòng),TestForm 會(huì )顯示一個(gè)工具提示,它描述在這個(gè)輸入域能輸入什么(如圖Figure 1)。如果你敲入了一個(gè)非法字符——例如,在電話(huà)號碼輸入域敲入一個(gè)字符——TestForm將拒絕接受該字符并發(fā)出蜂鳴聲。當你按下確認鍵或OK鍵,你會(huì )得到一個(gè)描述所有無(wú)效輸入域的出錯信息框,如圖 Figure 2所示。所有的錯誤都顯示在一個(gè)消息框中,而不是每個(gè)錯誤一個(gè)消息框。接著(zhù)當用戶(hù)tab到其中一個(gè)無(wú)效輸入域時(shí),TestForm會(huì )再次在對話(huà)框本身的一個(gè)應用程序提供的“反饋”窗口內顯示出錯信息(如 Figure3),因此用戶(hù)不必記住錯誤信息所描述的內容,當他們更正每個(gè)無(wú)效輸入域時(shí),窗體會(huì )提醒他們。如果只有一個(gè)輸入域無(wú)效,TestForm會(huì )放棄消息框而直接在“反饋”窗口顯示錯誤信息。


Figure 2 集中顯示出錯的輸入域

所有這些神奇的特性都是由 CRegexForm 自己實(shí)現的。你只需使用它即可,使用方法相當直白,首先你得定義一個(gè)自己窗體。下面是TestForm 的窗體內容,這些定義位于 MainDlg.cpp:

// form/field mapBEGIN_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()

  這個(gè)宏定義了一個(gè)靜態(tài)表格,表格描述每個(gè)編輯控制域。大多數情況下你只需要控制 ID,還要有地方放標志和 RegexOptions。例如,在TestForm 中,郵政編碼是必輸域(RGXF_REQUIRED),質(zhì)數(PrimeNumber)輸入域使用回調(稍后會(huì )詳細討論),最喜愛(ài)的專(zhuān)欄作家(IDC_FAVCOL)指定 CMRegex::IgnoreCase,它使得大小寫(xiě)不敏感。


Figure 3 Pietrek? I Think Not!

看著(zhù)表格你可能想知道正則表達式在哪?;卮鹗牵涸谫Y源文件中。對于每個(gè)域/控制ID,CRegexForm都期望有一個(gè)具有相同ID的資源串。資源串由五個(gè)子串組成,子串之間用新行符(‘‘\n‘‘)分隔。一般格式為:
“Name\nRegex\nLegalChars\nHint\nErrMsg”。以下是 IDC_ZIP 所用的串:

"Zip Code\n^\\d{5}(-\\d{4})?$\n[\\d-]\n##### or #####-####"

第一個(gè)子串“ZipCode”是域名。第二個(gè)“^\d{5}(-\d{4})?$”,是用于驗證郵編的正則表達式。(在資源串中必須敲入兩個(gè)反斜線(xiàn),目的是轉義正則表達式中反斜線(xiàn))。第三個(gè)子串是另外一個(gè)正則表達式,用來(lái)描述合法字符。對于郵編來(lái)說(shuō),即是“[\d-]”,意思是允許數字和連字符(hyphen)。如果輸入域無(wú)字符限制,你可以通過(guò)敲入兩個(gè)連續的新行符(“\n\n”意思是空子串)省略 LegalChars檢查。第四個(gè)子串全部為工具提示串。最后你可以提供第五個(gè)子串,如果該輸入域無(wú)效則顯示錯誤信息。對于郵編來(lái)說(shuō),它沒(méi)有錯誤信息,所以CRegexForm 產(chǎn)生一個(gè)默認的信息,形式為“Should be xxx”,xxx 被工具提示替代。“Shouldbe”本身即是另一個(gè)資源串(稍后還要說(shuō)到)。這些子串中,只有第一個(gè)域是必輸域。
為什么用資源串來(lái)保存所有信息,而不直接在域映射中編碼處理呢?首先,將它放在映射中使得代碼很笨拙。把這些亂七八糟的字符串放在不顯眼的地方有利于代碼更整潔。此外宏無(wú)法處理可選參數,根據你所用參數的多少,你需要多個(gè)宏,如:RGXFIELD3、RGXFIELD4 和RGXFIELD5。這樣不是太笨拙了嘛?使用資源串真正的好處在于容易本地化。翻譯者可以翻譯字符串并創(chuàng )建不同的資源DLLs。甚至正則表達式本身都需要翻譯(不同的國家和地域郵編可能是不同的),所以它們也放在資源串中。
此外,再讓我順便指出用正則表達式解析這些子串是多么容易。MFC 有一個(gè) 26 行的專(zhuān)門(mén)用來(lái)解析子串的函數AfxExtractSubString,但 CRegexForm 使用 CMRegex 來(lái)做只要一行代碼!

CString str;str.LoadString(nID);vector<CString> substrs = CMRegex::Split(str, _T("\n"));

  現在 substrs[i] 是第 i 個(gè)子串,如果你想知道有多少個(gè)子串,調用 substrs.size()即可。我真的很高興我包裝了Split 函數來(lái)返回 STL vector。
一旦你用 BEGIN/END_REGEX_FORM 定義了自己的域映射并編寫(xiě)了自己的資源串,下一步要做的就是在對話(huà)框中實(shí)例化CRegexForm 并進(jìn)行初始化:

// in OnInitDialogm_rgxForm.Init(MyRegexForm, this,IDS_MYREGEXFORM,MYWM_RGXFORM_MESSAGE);

  自然,CRegexForm需要域映射并指向你的對話(huà)框;第二和第三個(gè)參數是另一個(gè)資源串和回調消息ID。與單獨的域字符串一樣,初始串由包含新行符分隔的多個(gè)子串組成。對于TestForm,IDS_MYREGEXFORM 是“Error: %s\nRequired\nShould be: %s\nBadValue”。第一個(gè)子串“Error: %s”是錯誤前綴。CRegexForm 用來(lái)顯示“Error: xxx,”,xxx是實(shí)際的出錯信息。第二個(gè)子串,“Required,”是一個(gè)詞/短語(yǔ),當該域為必輸域(RGXF_REQUIRED)時(shí)使用。第三個(gè)子串“Shouldbe: %s,”我前面已經(jīng)描述過(guò),CRegexForm 用它來(lái)產(chǎn)生出錯信息。“Should be: xxx”中的 xxx是域提示。最后一個(gè)子串,“Bad Value,”CRegexForm可以用它來(lái)放任何信息,當域沒(méi)有提示也沒(méi)有出錯信息時(shí)使用。用戶(hù)是看不到此信息的,因為你肯定會(huì )為每一個(gè)域配一個(gè)提示或出錯信息,對不對?
Init 的最后一個(gè)參數 MYWM_RGXFORM_MESSAGE 是應用程序定義的回調消息 ID,利用它可以使 CRegexForm與你的應用程序溝通并做一些需要過(guò)程代碼來(lái)定制驗證的事情。如果你需要用數學(xué)算法來(lái)驗證你的輸入,你可以在域標志中設置RGXF_CALLBACK,CRegexForm 將在進(jìn)行驗證時(shí)用通知代碼 RGXNM_VALIDATEFIELD方式向對話(huà)框發(fā)送回調消息。TestForm 使用回調來(lái)驗證其 Prime Number 域;具體詳細參見(jiàn)Figure 4。
CRegexForm 用其內部擁有的 CStrings 來(lái)進(jìn)行 DDX,所以你不必為每個(gè)文本域定義對話(huà)框成員。你只要調用CRegexForm 來(lái)傳遞數據即可。

void CMyDialog::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);m_rgxForm.DoDataExchange(pDX);}

  當你初始化 CRegexForm 時(shí),它分配一個(gè) protected 類(lèi)型的 FLDINFO結構數組,映射中的每個(gè)域都有一個(gè)這樣的數組。FLDINFO 結構的成員之一是 FLDINFO::val,類(lèi)型為 CString,用來(lái)保存當前的域值。CRegexForm在內部使用以此 CString 作為參數的 DDX_Text。你可以通過(guò)調用 CRegexForm::GetFieldValue 或SetFieldValue 獲取或設置該內部域值,它們都用控制ID來(lái)區分域。

m_rgxForm.SetFieldValue(IDC_ZIP,_T("10025"));

  CRegexForm 將所有值都當作文本對待,并將它們存儲在 CStrings 中,同時(shí)提供 GetFieldValInt 和GetFieldValDouble 方法來(lái)獲得轉換為 int 或 double 的值。對于其它類(lèi)型,你得自己進(jìn)行轉換——或者你仍可以用 MFCDoDataExchange 中的 DDX 函數。TestForm 有一個(gè) “Populate”按鈕,它調用CRegexForm::SetFieldValue 將樣板數據填充到窗體中,如圖 Figure 3 所示。通常,CRegexForm 使用控制ID 來(lái)區分輸入域。它包含有 GetFieldName、GetFieldHint 和 GetFieldError來(lái)獲取域名、提示和出錯信息——它們都帶有一個(gè)參數就是控制 ID。
到此,我說(shuō)明了如何創(chuàng )建域映射,編寫(xiě)資源串,初始化你的 CRegexForm 以及通過(guò) DDX來(lái)關(guān)聯(lián)。所有這些都是序曲。真正的用戶(hù)輸入驗證是在用戶(hù)按下 OK 鍵后進(jìn)行的:

void CMyDialog::OnOK(){UpdateData(TRUE); // 拷貝屏幕輸入->對話(huà)框int nBad = m_rgxForm.Validate();if (nBad>0) {m_badFields = m_rgxForm.GetBadFields();...}

  UpdateData 調用 MFC 的 DDX 機制,即調用對話(huà)框的 DoDataExchange。然后 DoDataExchange調用 CRegexForm::DoDataExchange,從而將用戶(hù)輸入拷貝到其內部的 FLDINFO 結構。接著(zhù)CRegexForm::Validate 遍歷輸入域,針對域的正則表達式調用 CMRegex::Match來(lái)驗證每一個(gè)域。如果域輸入無(wú)效,CRegexForm 便在其內部的 FLDINFO 中設置錯誤碼 RGXERR_NOMATCH或者必輸于域如果為空,則設置 RGXERR_MISSING。Validate 返回無(wú)效域數量。如果有無(wú)效域,你可調用CRegexForm::GetBadFields 來(lái)獲得一個(gè)無(wú)效域 IDs 數組(STLvector)。然后你可以遍歷該數組以獲取各個(gè)錯誤嗎和出錯信息。這便是 TestForm 中 CMainDlg 建立其錯誤消息框所做的事情,如Figure 2 所示。如果只有一個(gè)域無(wú)效,CMainDlg 調用 CRegexForm::ShowBadField高亮該輸入域并在反饋窗口顯示出錯信息,如圖 Figure 3 所示。如果所有域都沒(méi)問(wèn)題,TestForm 便顯示一個(gè)消息框展示輸入的值(參見(jiàn)Figure 5)。


Figure 5 顯示輸入的數據

在實(shí)際應用中,你會(huì )將這些值拷貝到其最終目的地。Figure6 是 CMainDlg::OnOK 的全部代碼。通過(guò)數據交換中的非耦合式的數據驗證,CRegexForm 給予你更充分的 UI控制,并使你避免 MFC 固有的缺陷。
我提到的反饋窗口,它由 CRegexForm 全權管理;你只需通過(guò)調用 CRegexForm::SetFeedBackWindow提供一個(gè)這樣的窗口即可。你可以為出錯信息指定一種顏色。CRegexForm還負責提示功能。默認情況下,當用戶(hù)tab到某個(gè)新輸入域時(shí)顯示域提示(如圖 Figure 1)。你可以調用 CRegexForm::SetShowHints(FALSE)來(lái)關(guān)閉提示功能。SetShowHints(TRUE,nDelay, nTimeout) 可以再次打開(kāi)提示功能,這里 nDelay 是顯示提示之前要等待的毫秒數(默認值=250),nTimeout是提示顯示的毫秒數(默認值=0,表示一直顯示)。當用戶(hù)離開(kāi)輸入域時(shí)(EN_KILLFOCUS),CRegexForm自動(dòng)清除其提示。TestForm 使用 SetShowHints 實(shí)現復選框提示的開(kāi)啟和關(guān)閉(參見(jiàn) Figure 1)。
還有另外一個(gè)特性是否提出來(lái)我有些舉棋不定。CRegexForm有一個(gè)選項來(lái)做立即驗證。我不建議使用它,因為我覺(jué)得那是一種不好的GUI設計,但很多時(shí)候在沒(méi)有輸入有效的信息之前你不想讓用戶(hù)tab到下一個(gè)輸入域。在這種情況下,你可以在域映射中使用RGXF_IMMED,或調用 SetValidateImmed 來(lái)使所有域都進(jìn)行立即驗證。TestForm有一個(gè)復選框專(zhuān)門(mén)控制立即驗證功能的開(kāi)關(guān)。如果選中,你會(huì )看到為什么立即驗證不是個(gè)好主意。
最后,看看最小/最大和字符限制約束特性?最小/最大是正則表達式無(wú)法做到的一件事。雖然“.{0,35}”是一個(gè)描述最多35個(gè)字符長(cháng)的字符串正則表達式,但你還是愿意使用EM_LIMITTEXT 來(lái)限制編輯控制的文本長(cháng)度,所以當用戶(hù)敲入過(guò)長(cháng)的字符時(shí)發(fā)出蜂鳴聲。因為我容忍實(shí)現了一個(gè)窗體驗證系統,但它缺乏 MFC已經(jīng)支持的特性,我引進(jìn)了“偽正則表達式”的概念。例如,IDC_AGE 的正則表達式(Age輸入域)為“rgx:minmax:int:1:120,maxchars:3”。顯然,它不是一個(gè)真正的正則表達式。它是一個(gè)偽表達式,它由CRegexForm 自己來(lái)識別和解釋。其一般格式是:“rgx:expr,expr,..expr”,這里每個(gè)表達式描述不同的約束。目前支持兩種類(lèi)型:“minmax:type:minval:maxval”(此處type 是 int 或 double)以及“maxchars:maxval”。CRegexForm 負責做專(zhuān)門(mén)解析,并對 maxchars使用 EM_LIMITTEXT,就像 DDV_MinMaxInt一樣。具體實(shí)現細節請下載源代碼。至于資源子串,正則表達式解析它們簡(jiǎn)直是小菜一碟。
CRegexForm 所能做的事情我已經(jīng)說(shuō)完了。它是如何工作的呢?由于篇幅所限,恕不贅言,但我大概勾勒一下。CRegexForm 我的CSubclassWnd 來(lái)子類(lèi)化對話(huà)框。對之前不了解它的讀者來(lái)說(shuō),CSubclassWnd是我很早以前寫(xiě)的一個(gè)類(lèi),它使用Windows的子類(lèi)化機制來(lái)截獲發(fā)送到另一個(gè)窗口的消息。CSubclassWnd真正酷的地方是它不需要在你的類(lèi)層次中插入新類(lèi)便能讓你子類(lèi)某個(gè) MFC 窗口。我可以從 CDialog 派生出 CRegexForm,但那樣你就得從CRegexForm 派生自己的對話(huà)框。那么如果你已經(jīng)自己實(shí)現了從 CDialog 派生的 CBetterDialog怎么辦呢?此時(shí),你不得不進(jìn)行外科手術(shù)來(lái)插入 CRegexForm,結果將不可預見(jiàn)。
這是MFC的一大缺陷:它用派生實(shí)現子類(lèi)化,所以類(lèi)層次確切地反映了 Windows 子類(lèi)機制。但沒(méi)必要這樣,編寫(xiě)像 CRegexForm這樣的插件類(lèi)來(lái)子類(lèi)化你的對話(huà)框而不用改動(dòng)你的類(lèi)層次是更好的解決方法。對我來(lái)說(shuō),CSubclassWnd 是如此不可或缺,沒(méi)有它我無(wú)法編程!
CRegexForm 使用 CSubclassWnd 截獲 EN_KILLFOCUS 和 EN_SETFOCUS 以隱藏和顯示提示,截獲EN_CHANGE 以便用戶(hù)敲入任何信息后清除輸入域的出錯狀態(tài)。CRegexForm 用我的 CPopupText 類(lèi)實(shí)現本身的提示,CPopupText類(lèi)第一次討論是在2000年九月的專(zhuān)欄。為了防止用戶(hù)敲入不允許的字符,CRegexForm 為每一個(gè)具有 LegalChars正則表達式的編輯控制安裝了另一個(gè) CSubclassWnd 派生的鉤子。這是一個(gè)嵌套類(lèi),CRegexForm::CEditHook截獲發(fā)送到編輯控制的 WM_CHAR 消息,它吃掉任何非法輸入字符并發(fā)出蜂鳴。詳情參見(jiàn) RegexWrap的源代碼,這個(gè)代碼你可以從本期中我的另外一篇文章中下載:“使用ManWrap 庫在本機 C++ 代碼中調用.NET

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
MFC中的DoDataExchange(CDataExchange *pDX)
理解MFC(五)
MFC淺析(6) 對話(huà)框數據交換及驗證
VS2010/MFC編程入門(mén)之八(對話(huà)框:創(chuàng )建對話(huà)框類(lèi)和添加控件變量)
使用classwizard時(shí) 出錯
第十二章 對話(huà)框和對話(huà)框類(lèi)CDialog
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久