• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            微塵--KeepMoving

            為了忘卻的記憶
            posts - 3, comments - 2, trackbacks - 0, articles - 13
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            摘要:本文主要介紹了如何通過窗口子類化技術(shù)來實(shí)現(xiàn)對編輯控件的限制輸入。

              關(guān)鍵詞:窗口,子類化,句柄, 消息。

              1.問題的提出

              盡管Windows系統(tǒng)提供了許多通用的控件如:Edit、ComboBox 、ListBox……等,有些情況下這些標(biāo)準(zhǔn)控件也無能為力。比如:在對學(xué)生成績考評過程中需要一個(gè)供教
            師輸入評測等級的編輯控件,要求在編輯框內(nèi)只能輸入A、B、C、D四個(gè)等級,這樣在編輯框內(nèi)就禁止對其他字母或數(shù)字的操作。簡單地使用Windows的編輯框控件是不能對輸入字符進(jìn)行有效過濾的,對于這類問題的解決,我們可以采用子類化的方法來實(shí)現(xiàn)編輯控件的限制輸入。

              2.實(shí)現(xiàn)方法

              每個(gè)應(yīng)用程序?yàn)榱说怯浺粋€(gè)窗口類,首先要填寫好一個(gè)WNDCLASS,其中的結(jié)構(gòu)參數(shù)lpfnWndProc就是該類窗口函數(shù)的地址,接著調(diào)RegisterClass()函數(shù)向Windows系統(tǒng)申請登記這個(gè)窗口類。這時(shí)Windows會為其分配一塊內(nèi)存來存放該類的全部信息,這個(gè)內(nèi)存塊稱為窗口類內(nèi)存塊。當(dāng)應(yīng)用程序要創(chuàng)建一個(gè)屬于某一已登記窗口類的窗口時(shí),Windows便為這個(gè)窗口分配一塊內(nèi)存,即窗口內(nèi)存塊,用來存放與該窗口有關(guān)的專用信息。這些信息一部分來自傳遞給窗口創(chuàng)建函數(shù)CreateWindow() 或CreateWindowEx()的參數(shù)信息,另一部分則來自所屬窗口類的窗口類內(nèi)存塊,其中參數(shù)lpfnWndProc便被Windows從窗口類內(nèi)存塊復(fù)制到為新創(chuàng)建窗口分配的窗口內(nèi)存塊中。當(dāng)有消息被發(fā)送到這個(gè)窗口時(shí),Windows檢查該窗口內(nèi)存塊中的窗口函數(shù)地址(lpfnWndProc),并調(diào)用該地址上的函數(shù)來處理這些消息。

              所謂窗口子類化,實(shí)際上就是改變窗口內(nèi)存塊中的有關(guān)參數(shù)。由于這種修改只涉及到一個(gè)窗口的窗口內(nèi)存塊,因此它不會影響到屬于同一窗口類的其它窗口的功能和表現(xiàn)。窗口子類化中最常見的是修改窗口內(nèi)存塊中的窗口函數(shù)地址(lpfnWndProc),使其指向一個(gè)新的窗口函數(shù),從而改變原窗口函數(shù)的處理方法,改進(jìn)其功能。

              3. 實(shí)現(xiàn)過程

               首先利用MFC建立一個(gè)基于對話框的應(yīng)用程序NewDialg; 在對話框中添加一個(gè)ID為IDC_DEIT1的編輯控件資源。

              并派生一個(gè)自己的類CNewEdit (它的基類為CEdit)。通過這個(gè)類實(shí)現(xiàn)對該編輯控件的限制輸入。

             ?。?) 處理CNewEdit的消息函數(shù)OnChar:

              void CNewEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) {

               TCHAR ch[20];

               GetWindowText(ch,20);

              //處理只能輸入A,B,C,D的情況

              if (strlen(ch) == 1 && (nChar <= ‘D‘ && nChar >= ‘A‘)) return;

              if (nChar != ‘A‘ && nChar != ‘B‘ && nChar != ‘C‘ && nChar!= ‘D‘ ) return;

              CEdit::OnChar(nChar, nRepCnt, nFlags);

              }

              (2) 為CNewDialogDlg類中添加一個(gè)數(shù)據(jù)成員CNewEdit m_edit,并在CtestDlg::OnInitDialog( )中加入下面代碼:

              m_edit.SubclassDlgItem(IDC_EDIT1,this);

               m_edit.SetWindowText("<請輸入A、B、C、D>"); //提示可以輸入的內(nèi)容

             ?。?)處理ID為IDC_EDIT1的控件向?qū)υ捒虬l(fā)送的通知消息:EN_SETFOCUS:

              void CNewDialogDlg::OnSetfocusEdit1( ) {

              // TODO: Add your control notification handler code here

               m_edit.SetWindowText("");

               m_edit.SetFocus( );}

             

              4 過程分析

              下面我們看一下m_edit如何控制程序中資源編號為:IDC_EDIT1的控件的。

              大家都知道,控制Windows窗口、控件、資源……都是通過它們的句柄來實(shí)現(xiàn),如HHANDLE、HWND、HDC都是句柄,它表現(xiàn)為一個(gè)32位長整形數(shù)據(jù),存放于Windows中的特定區(qū)域,我們可以把它理解為指向我們想控制的窗口、控件、資源的索引,有了它,我們就可以控制我們想要控制的對象。

              那么CNewEdit的數(shù)據(jù)成員m_edit要想控制IDC_EDIT1,也要通過它的句柄,這就要通過SubclassDlgItem函數(shù)來實(shí)現(xiàn)。

              BOOL CWnd::SubclassDlgItem(UINT nID, CWnd* pParent){

              ASSERT(pParent != NULL);

              ASSERT(::IsWindow(pParent->m_hWnd));

              // check for normal dialog control first

              HWND hWndControl = ::GetDlgItem(pParent->m_hWnd, nID);

              if (hWndControl != NULL)

               return SubclassWindow(hWndControl);

              ……

              }

              SubclassDlgItem函數(shù)是CWnd的一個(gè)成員函數(shù),它開始時(shí)對傳入的父窗口做些檢查,然后就是先用hWndControl得到我們IDC_EDIT1控件的句柄,再調(diào)用SubclassWindow函數(shù),這個(gè)函數(shù)是實(shí)現(xiàn)的關(guān)鍵。

              BOOL CWnd::SubclassWindow(HWND hWnd){

              if (!Attach(hWnd))

               return FALSE;

              ……

              WNDPROC oldWndProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)AfxGetAfxWndProc());

              ……

              }

              在這個(gè)函數(shù)中,首先調(diào)用了Attach函數(shù),將hwand這個(gè)窗口句柄與一個(gè)窗口對象連接,在Attach函數(shù)中,有重要的一句: pMap->SetPermanent(m_hWnd = hWndNew, this); 顯然只要把窗口的句柄保存下來,就可以在系統(tǒng)中唯一地指定一個(gè)窗口,然后對該窗口進(jìn)行操作。在Attach 函數(shù)中把IDC_EDIT1 的句柄保存在了CnewEdit的成員變量m_hWnd 中,那么在m_edit.SetWindowText("<請輸入A、B、C>")中,正是通過這個(gè)數(shù)據(jù)成員m_hWnd實(shí)現(xiàn)對IDC_EDIT1控制的:

              void CWnd::SetWindowText(LPCTSTR lpszString){

              ASSERT(::IsWindow(m_hWnd));

              if (m_pCtrlSite == NULL)  

              ::SetWindowText(m_hWnd, lpszString);

              else    

              m_pCtrlSite->SetWindowText(lpszString);

              }

              雖然通過句柄實(shí)現(xiàn)了m_edit對IDC_EDIT1的控制,對CNewEdit的WM_CHAR的處理是還要通過SubclassWindow函數(shù)來實(shí)現(xiàn),在SubclassWindow中有這樣一句:

              WNDPROC oldWndProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)AfxGetAfxWndProc());

              其中AfxGetAfxWndProc()是我們自己的窗口處理函數(shù),在其中處理過我們感興趣的消息后,通過返回的原窗口處理函數(shù)指針oldWndProc來把其它消息按標(biāo)準(zhǔn)方法處理掉,這樣當(dāng)程序收到發(fā)給Edit的WM_CHAR時(shí),本應(yīng)調(diào)用EDIT標(biāo)準(zhǔn)窗口處理函數(shù),現(xiàn)在被改為調(diào)用LRESULT CALLBACK AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)了,然后WM_CHAR消息進(jìn)行一系列的過程,最終成功到達(dá)我們的處理函數(shù)CNewEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags), 實(shí)現(xiàn)對編輯控件的限制輸入。

             

              參考文獻(xiàn):

              [1] aaaaaaaaaawww.msdn.com

              [2] 楊曉鵬 《Visual C++ 7.0 實(shí)用編程技術(shù)》 北京 中國水利水電出版社。

            99精品国产综合久久久久五月天| 91亚洲国产成人久久精品网址| 亚洲v国产v天堂a无码久久| 国产精品欧美久久久久天天影视| 国产精品久久久久影院嫩草| 国产精品欧美久久久久无广告 | 久久无码专区国产精品发布 | 久久综合色区| 无码AV波多野结衣久久| 国产精品成人99久久久久 | 久久久久久久99精品免费观看| 亚洲?V乱码久久精品蜜桃 | 色欲综合久久中文字幕网| 国产精品久久影院| 国产精品久久久久久久久软件| 99精品久久久久久久婷婷| 亚洲国产精品无码久久一区二区| 国产精品一区二区久久精品无码| 日本强好片久久久久久AAA | 精品少妇人妻av无码久久| 无码人妻久久一区二区三区蜜桃| 91精品国产综合久久婷婷| 久久九九久精品国产免费直播| 国产日韩久久久精品影院首页| aaa级精品久久久国产片| 亚洲午夜精品久久久久久app| 99热成人精品免费久久| 国内精品久久久久久野外| 久久久无码一区二区三区| 2021国产精品久久精品| 亚洲国产精品狼友中文久久久 | 久久精品国产亚洲精品2020 | 国产一级持黄大片99久久 | 国产精品毛片久久久久久久| 久久性精品| 武侠古典久久婷婷狼人伊人| 久久久久亚洲精品无码网址 | 久久久婷婷五月亚洲97号色| 久久久久国色AV免费观看| 热综合一本伊人久久精品| 欧美久久久久久午夜精品|