【C++】DDX_Control、SubclassWindow和SubclassDlgItem的區別

在自繪窗口的時候,子類化是MFC最經常使用的窗體技術之一。什麼是子類化?窗口子類化就是建立一個新的窗口函數代替原來的窗口函數。windows

Subclass(子類化)是MFC中最經常使用的窗體技術之一。子類化完成兩個工做:一是把窗體類對象attach到一個windows窗體實體中(即把一個窗體的hwnd賦給該類)。另外就是把該類對象的消息加入到消息路由中,使得該類能夠捕獲消息。
函數

而一般咱們會碰到DDX_Control、SubclassWindow、SubclassDlgItem等,不一樣的子類化方法。首先先看下面的代碼:spa

 

void AFXAPI DDX_Control(CDataExchange* pDX, int nIDC, CWnd& rControl)
{
if ((rControl.m_hWnd == NULL) && (rControl.GetControlUnknown() == NULL))    // not subclassed yet
{
ASSERT(!pDX->m_bSaveAndValidate);

pDX->PrepareCtrl(nIDC);
  HWND hWndCtrl;
  pDX->m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl);
if ((hWndCtrl != NULL) && !rControl.SubclassWindow(hWndCtrl))
{
ASSERT(FALSE);      // possibly trying to subclass twice?
AfxThrowNotSupportedException();
}
#ifndef _AFX_NO_OCC_SUPPORT
else
{
 if (hWndCtrl == NULL)
 {
if (pDX->m_pDlgWnd->GetOleControlSite(nIDC) != NULL)
{
   rControl.AttachControlSite(pDX->m_pDlgWnd, nIDC);
}
 }
 else
 {
   // If the control has reparented itself (e.g., invisible control),
   // make sure that the CWnd gets properly wired to its control site.
   if (pDX->m_pDlgWnd->m_hWnd != ::GetParent(rControl.m_hWnd))
   rControl.AttachControlSite(pDX->m_pDlgWnd);
 }
}
#endif //!_AFX_NO_OCC_SUPPORT

}
}

咱們發現 DDX_Control()函數中調用了SubclassWindow(),再看SubclassWindow()裏寫了什麼:code

// From VS Install PathVC98MFCSRCWINCORE.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)  
        {  
          
            ::SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)oldWndProc);  
    }  
#endif  
      
    return TRUE;  
}  
  

 

很顯然,SubclassWindow()中調用了Attach()函數和reSubclassWindow()函數,因爲SubclassWindow()函數是不可重載的,而PreSubclassWindow()函數是可重載的,因此咱們常常重載PreSubclassWindow()函數,以至於 窗口被子類化以前進行其它的必要的子類化,看下它原來的聲明:
CWnd::PreSubclassWindow
virtual void PreSubclassWindow( );

而SubclassWindow又與SubclassDlgItem有什麼區別?前者用於一切具備HWND的窗體,後者只限定於對話框控件對象

用法:在OnInitDialog中調用SubclassDlgItem將派生類的控件對象與對話框中的基類控件相鏈接,則這個基類控件對象變成了派生控件對象
路由


總而言之,比較經常使用的就是DDX_Control。get

相關文章
相關標籤/搜索