免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
MFC編程中的窗口子類化淺析

窗口子類化的作用

       窗口子類化技術(shù)最大的特點(diǎn)就是能夠截取Windows的消息。一旦用戶自定義的窗口函數(shù)截取了傳向原窗口函數(shù)的消息,就可以對(duì)被截取的消息進(jìn)行如下處理:

       將其傳給原來的窗口函數(shù)。這是對(duì)大多數(shù)消息應(yīng)該采取的措施,因?yàn)樽宇愅ǔV粚?duì)原來的窗口特性作少量的改動(dòng)

       截取該消息,阻止其向原窗口函數(shù)發(fā)送。

      修改該消息,修改完畢以后再向原窗口函數(shù)發(fā)送

MFC編程中的窗口子類化

       MFC窗口實(shí)際上已經(jīng)是被子類化的窗口。所有的MFC窗口共享同一個(gè)窗口函數(shù),由這個(gè)窗口函數(shù)根據(jù)窗口句柄,查找這個(gè)窗口對(duì)應(yīng)的CWnd派生類實(shí)例,再通過消息映射這個(gè)窗口類的消息處理函數(shù)。鑒于以上原因,在MFC中要子類化一個(gè)窗口就比較容易了,因?yàn)槟愕娜蝿?wù)只是編寫一個(gè)新的MFC窗口類而不需要寫一個(gè)窗口函數(shù)。

       假如我們現(xiàn)在有一個(gè)對(duì)話框,里面有一個(gè)編輯控件,我們只希望在該控件中接受非數(shù)字字符輸入,我們可以攔截WM_CHAR消息,在它的處理函數(shù)中忽略任何數(shù)字的輸入。具體實(shí)現(xiàn)步驟如下。

VC中窗口子類化的應(yīng)用舉例

MFC為廣大編程者提供了很多功能豐富的窗口類,如果能在這些通用窗口類的基礎(chǔ)上進(jìn)行子類化的話,將會(huì)給編程者帶來很多便利。下面舉一個(gè)例子來說明MFC編程中的子類化是多么的簡(jiǎn)單易行。該例完成上面提到的在編輯控件只接受非數(shù)字字符輸入的功能。實(shí)現(xiàn)這個(gè)子類化的基本步驟和相關(guān)代碼如下:

(1)利用AppWziard創(chuàng)建一個(gè)基于對(duì)話框的程序SubClassing。

(2)對(duì)MFC提供的標(biāo)準(zhǔn)的對(duì)話框中的控件進(jìn)行修改,刪除MFC提供的靜態(tài)文本控件,添加自己的一個(gè)編輯控件,設(shè)置新控件的ID為IDC_EDIT。合理布置對(duì)話框上各控件的位置,使程序界面布局合理、美觀。

(3)用ClassWizard從CEdit類派生一個(gè)新的窗口類,新窗口的窗口類叫CNoNumEdit。截取CNoNumEdit類的WM_CHAR消息,在OnChar函中完成忽略任何數(shù)字的輸入的處理。實(shí)現(xiàn)代碼如下:

void CNoNumEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

{

         TCHAR ch=nChar;

         if(ch>=_T('0')&&ch<=_T('9'))

        {

              AfxMessageBox(("請(qǐng)不要輸入數(shù)字!"),MB_OK);

              //當(dāng)輸入數(shù)字字符時(shí)將被忽略,并顯示警告信息

              return;

        }

        CEdit::OnChar(nChar, nRepCnt, nFlags);//輸入為非數(shù)字字符時(shí)調(diào)用原處理函數(shù)

}

(4)在對(duì)話框窗口類CSubClassingDlg的定義中添加變量CNoNumEdit ed。在CSubClassingDlg::OnInitDialog()函數(shù)中調(diào)用CWnd類的成員函數(shù)SubClassWindow進(jìn)行子類化。

代碼:

if (ed.GetSafeHwnd() == NULL)
    ed.SubclassWindow(GetDlgItem(IDC_EDIT1)->GetSafeHwnd());

(5) 在對(duì)話框窗口類CsubClassing的OnDestroy中調(diào)用UnSubClassWindow()執(zhí)行窗口類的反子類化。

代碼:

if (ed.GetSafeHwnd() != NULL)
   ed.UnsubclassWindow();

現(xiàn)在可以編譯執(zhí)行這個(gè)程序了,當(dāng)用戶輸入數(shù)字字符時(shí)將會(huì)忽略該輸入,并顯示警告信息。

在Windows編程中,適當(dāng)使用窗口子類化技術(shù),可以很方便地達(dá)到改變一個(gè)窗口的特性的目的。當(dāng)然子類化也存在其局限性。實(shí)際上,子類化的概念是針對(duì)一個(gè)已經(jīng)創(chuàng)建的窗口來談的,所以修改窗口函數(shù)是在窗口創(chuàng)建之后進(jìn)行的,在窗口創(chuàng)建期間的消息無法捕獲,也就無法處理。另外有些窗口的特性與窗口類本身的屬性有關(guān)。比如如果一個(gè)窗口類沒有CS_DBLCLKS屬性的話,那么要想通過子類化這些窗口達(dá)到處理WM_LBUTTONDBLCLK消息的目的是無法實(shí)現(xiàn)的。對(duì)于子類化的以上局限性,可以通過超類化(SuperClassing)技術(shù)消除。

如果在創(chuàng)建對(duì)話框時(shí)已經(jīng)使用MFC的數(shù)據(jù)交換技術(shù)DDX將IDC_EDIT與變量ed進(jìn)行了綁定,則其效果同子類化一樣,子類化的要點(diǎn)在于一個(gè)動(dòng)態(tài)綁定。


MFC向?qū)傻膶?duì)話框?yàn)槟B(tài)對(duì)話框,當(dāng)我們?cè)谫Y源編輯器中向?qū)υ捒蛲献б粋€(gè)按鈕IDC_BTN時(shí),其布局信息將同步反映在DlgDemo.rc資源腳本文件中。

// DlgDemo.rc

IDD_MY_DIALOG DIALOGEX 0, 0, 320, 201

STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU

EXSTYLE WS_EX_APPWINDOW

CAPTION "DlgDemo"

FONT 9, "宋體"

BEGIN

    DEFPUSHBUTTON   "確定",IDOK,260,7,50,14

    PUSHBUTTON      "取消",IDCANCEL,260,23,50,14

    PUSHBUTTON      "MyBtn",IDC_BTN,141,79,50,14

END

    CDialog的構(gòu)造函數(shù)的參數(shù)一nIDTemplate指定了對(duì)話框模板的ID,即DlgDemo.rc中的IDD_MY_DIALOG。

CDialog::CDialog(UINT nIDTemplate, CWnd* pParentWnd)

{

// ……

    m_pParentWnd = pParentWnd;

    m_lpszTemplateName = MAKEINTRESOURCE(nIDTemplate);

// ……

}

模態(tài)對(duì)話框調(diào)用CDialog::DoModal()創(chuàng)建并顯示對(duì)話框,CDialog::DoModal()根據(jù)對(duì)話框模板名稱m_lpszTemplateName進(jìn)行FindResource、LoadResource加載模板資源。

CDialog::DoModal()調(diào)用CDialog::CreateDlgIndirect,最終調(diào)用::CreateDialogIndirectParam完成非模態(tài)對(duì)話框的創(chuàng)建。::CreateDialogIndirectParam參數(shù)二LPCDLGTEMPLATE lpTemplateDlgDemo.rcIDD_MY_DIALOG模板資源,該API將根據(jù)腳本描述創(chuàng)建對(duì)話框及其上的子控件(底層調(diào)用CreateWindowEx,傳入風(fēng)格、標(biāo)題和布局大小等參數(shù))。

對(duì)于外部而言,可見的只是一些子控件的ID,而沒有具體的子類(例如按鈕IDC_BTNàCButton)。實(shí)際上,對(duì)話框內(nèi)部維護(hù)了一個(gè)控件IDà控件HWND”的映射,這樣我們就可以通過::GetDlgItem(hDlg, nIDDlgItem)獲取子控件的窗口句柄,進(jìn)行相關(guān)Get/Set操作。

下面在點(diǎn)擊按鈕IDC_BTN時(shí),修改其標(biāo)題。

ON_BN_CLICKED(IDC_BTN, OnBtn)

void CMyDlg::OnBtn()

{

    // TODO: Add your control notification handler code here

 

    GetDlgItem(IDC_BTN)->SetWindowText("FXM"); // change button caption

}

CWnd* GetDlgItem(int nID)調(diào)用CWnd::FromHandle(::GetDlgItem(m_hWnd, nID))FromHandle創(chuàng)建一個(gè)臨時(shí)的CWnd(子類)對(duì)象,并把Windows對(duì)象(HWND)映射到臨時(shí)的MFC對(duì)象上,然后返回臨時(shí)MFC對(duì)象。MFC框架在線程的Idle處理中刪除臨時(shí)對(duì)象。

利用向?qū)?/span>按鈕IDC_BTN添加CButton類型的控件變量,內(nèi)部調(diào)用了Attach函數(shù)建立了控件變量(CButton)與窗口(HWND)之間的永久映射(SetPermanent)。在整個(gè)對(duì)話框的生存周期中,可以通過這個(gè)控件變量實(shí)現(xiàn)對(duì)窗口的訪問。至此,我們對(duì)按鈕IDC_BTN的操作依然局限在相關(guān)屬性的Get/Set訪問上,而其后續(xù)狀態(tài)行為依然故我地輪回著CButtonDefWindowProc

怎樣實(shí)現(xiàn)XP風(fēng)格按鈕、釘子按鈕甚至任意形狀按鈕呢?這里涉及到一個(gè)重要的概念——窗口子類化。

所謂窗口子類化,實(shí)際上就是改變窗口內(nèi)存塊中的有關(guān)參數(shù)。由于這種修改只涉及到一個(gè)窗口的內(nèi)存塊,因此它不會(huì)影響到屬于同一窗口類的其它窗口的功能和表現(xiàn)(IDàHWNDàCWnd)。窗口子類化中最常見的是修改窗口內(nèi)存塊中的窗口函數(shù)地址(lpfnWndProc),使其指向一個(gè)新的窗口函數(shù),從而改變?cè)翱诤瘮?shù)的處理方法,做出特定功能適應(yīng)。

在實(shí)際開發(fā)中,有些情況標(biāo)準(zhǔn)控件的標(biāo)準(zhǔn)過程是無能為力的。比如:在我們的應(yīng)用中要求一個(gè)EDIT控件接收老師對(duì)學(xué)生的評(píng)價(jià),評(píng)價(jià)分三個(gè)等級(jí)A、B、C(不要對(duì)我說你想用ComboBox實(shí)現(xiàn)),這就要求在EDIT中禁止對(duì)其它字母、數(shù)字的輸入操作,怎么辦?EDIT控件本身沒有提供這種機(jī)制,采用子類化可以很好的解決這類問題。

我們知道,每一個(gè)Windows窗口(這里指EDIT)都有一個(gè)窗口處理函數(shù)負(fù)責(zé)對(duì)消息的處理,子類化通常就是用我們自己的消息處理函數(shù)來替代窗口原有的、標(biāo)準(zhǔn)的處理函數(shù)。當(dāng)然我們自己的窗口處理過程只是關(guān)心那些特定的消息(在這里是WM_CHAR),而其它消息將發(fā)給原來的窗口函數(shù)做默認(rèn)處理。在SDK中的實(shí)現(xiàn)方法是調(diào)用函數(shù)SetWindowLong,其原型如下:

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

其中AfxGetAfxWndProc()是我們自己的窗口處理函數(shù),在其中處理我們感興趣的消息后,然后調(diào)用原窗口函數(shù)oldWndProc來對(duì)其它消息做標(biāo)準(zhǔn)處理。

我們先來梳理一下一個(gè)窗口創(chuàng)建過程中的附加和子類化過程。

CWnd::CreateàCWnd::CreateExàAfxHookWindowCreate(this)à_AfxCbtFilterHook。在鉤子函數(shù)_AfxCbtFilterHook中,將已創(chuàng)建的窗口(HWND附加到當(dāng)前正在初始化的CWndCEdit)對(duì)象(_AFX_THREAD_STATE:: m_hWndInit)上。然后再調(diào)用::SetWindowLong改變窗口的過程AfxWndProc。窗口函數(shù)AfxWndProcAFX_MODULE_THREAD_STATE::m_pmapHWND中查詢hWnd對(duì)應(yīng)的CWnd對(duì)象,AfxCallWndProc將消息委托給具體窗口對(duì)象的WindowProc函數(shù)處理。

利用MFC實(shí)現(xiàn)上面提到的EDIT控件過濾輸入要求,只能輸入A、B、C中的一個(gè)字母。

CEdit派生一個(gè)自己的類CSuperEdit,在其中處理WM_CHAR。

void CSuperEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

{

    // TODO: Add your message handler code here and/or call default

    TCHAR ch[20];

    GetWindowText(ch, 20);

   

    if (strlen(ch)==1 && (nChar<='C' && nChar>='A'))

       return;

   

    if ((nChar!='A') && (nChar!='B') && (nChar!='C'))

       return;

 

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

}

然后再給我們CProg1Dlg類中加入一個(gè)數(shù)據(jù)成員CSuperEdit m_edit,在CProg1Dlg::OnInitDialog()中加入以下兩行代碼:

    m_edit.SubclassDlgItem(IDC_EDIT1, this);

    m_edit.SetWindowText("<請(qǐng)輸入A、BC>");

處理EDITDIALOG發(fā)送的通知消息EN_SETFOCUS

ON_EN_SETFOCUS(IDC_EDIT1, OnSetfocusEdit1)

void CProg1Dlg::OnSetfocusEdit1()

{

    // TODO: Add your control notification handler code here

    m_edit.SetWindowText("");

    m_edit.SetFocus();

}

OK,一切搞定!和SDK的子類化方法比起來,這是多么的容易!

我們看看MFC背著我們到底做了什么!這里主要解決兩個(gè)容易讓初學(xué)者比較疑惑的問題:

1m_edit只是我們定義的一個(gè)C++類對(duì)象,為什么通過它調(diào)用其成員函數(shù)SetWindowText便可以控制我們程序中資源編號(hào)為IDC_EDIT1的控件?

2、CSuperEdit類為什么可以處理WM_CHAR消息?

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

這里你應(yīng)該聯(lián)想到為什么大多數(shù)窗口API函數(shù)都有一個(gè)參數(shù)HWND hwnd了吧!

// WINUSER.H

BOOL

SetWindowTextW(

    HWND hWnd, // handle to window or control

LPCWSTR lpString // title or text

);

變量m_edit要想控制IDC_EDIT1,必通過EDIT控件窗口的句柄,但這又是如何實(shí)現(xiàn)的呢?您可能注意到了m_edit.SubclassDlgItem(IDC_EDIT1, this);一句,對(duì)了,這就是關(guān)鍵所在!

在此處F9設(shè)置斷點(diǎn),F5之后,程序到達(dá)此處,F11跟入SubclassDlgItem函數(shù):

// WINCORE.CPP

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);

 

#ifndef _AFX_NO_OCC_SUPPORT

    if (pParent->m_pCtrlCont != NULL)

    {

       // normal dialog control not found

       COleControlSite* pSite = pParent->m_pCtrlCont->FindItem(nID);

       if (pSite != NULL)

       {

           ASSERT(pSite->m_hWnd != NULL);

           VERIFY(SubclassWindow(pSite->m_hWnd));

 

#ifndef _AFX_NO_OCC_SUPPORT

           // If the control has reparented itself (e.g., invisible control),

           // make sure that the CWnd gets properly wired to its control site.

           if (pParent->m_hWnd != ::GetParent(pSite->m_hWnd))

              AttachControlSite(pParent);

#endif //!_AFX_NO_OCC_SUPPORT

 

           return TRUE;

       }

    }

#endif

 

    return FALSE;   // control not found

}

代碼開始時(shí)對(duì)傳入的父窗口做些檢查,然后就是

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

    if (hWndControl != NULL)

       return SubclassWindow(hWndControl);

這是關(guān)鍵的代碼,先用hWndControl得到我們IDC_EDIT1控件的句柄,然后調(diào)用SubclassWindow函數(shù),這個(gè)函數(shù)是實(shí)現(xiàn)的關(guān)鍵,我們來看一下它做了什么:

// WINCORE.CPP

BOOL CWnd::SubclassWindow(HWND hWnd)

{

    if (!Attach(hWnd))

       return FALSE;

 

    // allow any other subclassing to occur

    PreSubclassWindow();

 

    // now hook into the AFX WndProc

    WNDPROC* lplpfn = GetSuperWndProcAddr();

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

    ASSERT(oldWndProc != (WNDPROC)AfxGetAfxWndProc());

 

    if (*lplpfn == NULL)

       *lplpfn = oldWndProc;   // the first control of that type created

#ifdef _DEBUG

    else if (*lplpfn != oldWndProc)

    {

       TRACE0("Error: Trying to use SubclassWindow with incorrect CWnd/n");

       TRACE0("/tderived class./n");

       TRACE3("/thWnd = $%04X (nIDC=$%04X) is not a %hs./n", (UINT)hWnd, _AfxGetDlgCtrlID(hWnd), GetRuntimeClass()->m_lpszClassName);

       ASSERT(FALSE);

       // undo the subclassing if continuing after assert

       ::SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)oldWndProc);

    }

#endif

 

    return TRUE;

}

函數(shù)Attach建立窗口對(duì)象CWnd與窗口句柄HWND的關(guān)聯(lián)(映射),其內(nèi)部實(shí)現(xiàn)如下:

// WINCORE.CPP

BOOL CWnd::Attach(HWND hWndNew)

{

    ASSERT(m_hWnd == NULL);     // only attach once, detach on destroy

    ASSERT(FromHandlePermanent(hWndNew) == NULL);

       // must not already be in permanent map

 

    if (hWndNew == NULL)

       return FALSE;

 

    CHandleMap* pMap = afxMapHWND(TRUE); // create map if not exist

    ASSERT(pMap != NULL);

 

    pMap->SetPermanent(m_hWnd = hWndNew, this);

 

#ifndef _AFX_NO_OCC_SUPPORT

    AttachControlSite(pMap);

#endif

 

    return TRUE;

}

這里要說明的是pMap->SetPermanent(m_hWnd = hWndNew, this);一句,它把IDC_EDIT1的句柄賦值給類CSuperEdit的數(shù)據(jù)成員m_hWnd(別忘了我們的CSuperEdit類是派生于CEdit),即建立hWndNew(IDC_EDIT1)m_edit(this)對(duì)象之間的關(guān)聯(lián)。大家可能現(xiàn)在已經(jīng)隱約的明白了些什么,不錯(cuò),在m_edit.SetWindowText("<請(qǐng)輸入AB、C>");中正是通過這個(gè)數(shù)據(jù)成員m_hWnd實(shí)現(xiàn)對(duì)IDC_EDIT1控制的:

// WINOCC.CPP

void CWnd::SetWindowText(LPCTSTR lpszString)

{

    ASSERT(::IsWindow(m_hWnd));

 

    if (m_pCtrlSite == NULL)

       ::SetWindowText(m_hWnd, lpszString);

    else

       m_pCtrlSite->SetWindowText(lpszString);

}

其它CEdit類的函數(shù)也都是圍繞“API函數(shù)+HWND參數(shù)(m_hWnd)”進(jìn)行包裝的。常用的DDX_Control方法說到底也是調(diào)用SubclassWindow: OnInitDialogàUpdateDataàDoDataExchangeàDDX_ControlàSubclassWindow

故一般在派生了CSuperEdit類后,可利用向?qū)?/span>CProg1Dlg添加CSuperEdit類型控件變量,向?qū)⒃?/span>void CProg1Dlg::DoDataExchange(CDataExchange* pDX)中自動(dòng)添加DDX_Control(pDX, IDC_EDIT1, m_edit); 在進(jìn)行子類化時(shí),SubclassDlgItemDDX_Control兩種方式擇其一。

怎么樣?第一個(gè)問題的來龍去脈搞明白了吧?

現(xiàn)在看看第二個(gè)問題:CSuperEdit類為什么可以處理WM_CHAR消息?

可能有的朋友現(xiàn)在疑惑,雖然通過句柄實(shí)現(xiàn)了m_edit對(duì)IDC_EDIT的控制,但發(fā)送給它的消息照樣跑到EDIT的標(biāo)準(zhǔn)處理函數(shù)中,對(duì)WM_CHAR的處理是如何實(shí)現(xiàn)的呢?

如果消息照樣跑到EDIT的標(biāo)準(zhǔn)處理函數(shù)中,那當(dāng)然是不能處理了!不知您有沒有看到在上面的SubclassWindow函數(shù)中有這么一小段我加了重點(diǎn)標(biāo)示:

// now hook into the AFX WndProc

    WNDPROC* lplpfn = GetSuperWndProcAddr();

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

    ASSERT(oldWndProc != (WNDPROC)AfxGetAfxWndProc());

 

    if (*lplpfn == NULL)

       *lplpfn = oldWndProc;   // the first control of that type created

再和我們開始講到的SDK中子類化機(jī)制聯(lián)系起來,明白了吧?MFC在這里神不知鬼不覺的搞起偷天換日的勾當(dāng)!

這個(gè)AfxGetAfxWndProc()函數(shù)是這樣的:

// WINCORE.CPP

// always indirectly accessed via AfxGetAfxWndProc

WNDPROC AFXAPI AfxGetAfxWndProc()

{

#ifdef _AFXDLL

    return AfxGetModuleState()->m_pfnAfxWndProc;

#else

    return &AfxWndProc;

#endif

}

讀過侯捷先生《深入淺出MFC》的朋友不知還是否記得MFC的命令路由機(jī)制正是以這個(gè)函數(shù)為起點(diǎn)的!

我們可以對(duì)對(duì)話框CProg1Dlg進(jìn)行WM_CREATE的消息響應(yīng),但CProg1Dlg::OnCreate函數(shù)中對(duì)子控件所作的任何操作都會(huì)導(dǎo)致內(nèi)存非法訪問。OnCreate函數(shù)成功返回后,創(chuàng)建主對(duì)話框的CreateWindowEx接著返回,這時(shí)::CreateDialogIndirectParam過程中才開始創(chuàng)建對(duì)話框子控件窗口。等所有子控件創(chuàng)建完畢后,::CreateDialogIndirectParam發(fā)出WM_INITDIALOG消息,調(diào)用對(duì)話框的OnInitDialog的函數(shù)。因此,在OnInitDialog之后子類化,只能處理一些創(chuàng)建之后的狀態(tài)行為。通過子類化可對(duì)既有窗口特定消息進(jìn)行行為和狀態(tài)的自繪制處理。

當(dāng)程序收到發(fā)給EditWM_CHAR消息時(shí),本應(yīng)調(diào)用EDIT標(biāo)準(zhǔn)窗口處理函數(shù),現(xiàn)在被改為調(diào)用LRESULT CALLBACK AfxWndProc(HWND, UINT, WPARAM, LPARAM);了,然后WM_CHAR消息進(jìn)行一系列的流竄,最終成功到達(dá)我們的處理函數(shù)void CSuperEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);關(guān)于消息的分流派發(fā)請(qǐng)參考《深入淺出MFC》第9章《消息映射與命令繞行》。

終于,我們走出了FMC子類化的迷宮。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
走出MFC窗口子類化的迷宮
vc子類化和反子類化
(轉(zhuǎn))走出MFC子類化的迷宮:子類化,SUBCLASSWINDOW ,MFC消息機(jī)制
VC++中有關(guān)句柄和指針及其轉(zhuǎn)換
delphi HooK 指定程序窗體和控件的 WndProc
消息斷點(diǎn)在x64dbg中的應(yīng)用
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服