【C++】DDX_Control、SubclassWindow、SubclassDlgItemの違い

3189 ワード

セルフペイントウィンドウの場合,サブクラス化はMFCで最もよく用いられるフォーム技術の一つである.サブクラス化とは?ウィンドウのサブクラス化とは、元のウィンドウ関数の代わりに新しいウィンドウ関数を作成することです.
Subclass(サブクラス化)はMFCで最も一般的なフォーム技術の一つである.サブクラス化は、2つの作業を完了します.1つは、フォームクラスオブジェクトattachをwindowsフォームエンティティに割り当てることです(つまり、フォームのhwndをクラスに割り当てることです).また、クラスオブジェクトのメッセージをメッセージルーティングに追加し、クラスがメッセージをキャプチャできるようにする.
通常DDXに遭遇しますControl、SubclassWindow、SubclassDlgItemなど、異なるサブクラス化方法.まず、次のコードを見てみましょう.
 
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()に何が書かれているかを見ます.
// 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.