MFC补充第十四天 句柄嫁接与子类化

文章目录

  • 句柄嫁接与子类化
    • 示例代码
    • SubclassWindow源码
  • 总结嫁接与子类化:
    • DDX_CONTROL源码

句柄嫁接与子类化

句柄嫁接与子类化:
a)Attach和Detach就是单纯的嫁接与分离函数。
对象一旦嫁接入一个句柄,就可以自由地调用CWnd或其派生类的功能。
b)子类化Subclass内部包含Attach,额外再增加一个消息转拨到派生类(SubClass就是子类)
c)SubClassWindow函数内部核心功能就是Attach和::SetWindowLong
d)SubClassWindow必须与UnsubclassWindow()成对使用,如同Attach与Detach那样。
e)SubClassDlgItem是把2个函数合成一个函数:m_eye.SubclassDlgItem(IDC_SHOW, this);
m_eye.SubclassWindow(::GetDlgItem(m_hWnd, IDC_SHOW));
f)而且SubClassDlgItem不需要反子类化,可以不用调用UnsubclassWindow

示例代码

BOOL CLoginDlg::OnInitDialog(){
//m_eye.Attach(::GetDlgItem(m_hWnd, IDC_SHOW)); //attach让你自由的调用CWnd类的成员
//m_eye.SubclassWindow(::GetDlgItem(m_hWnd, IDC_SHOW));//子类化 消息不穿透里面包含attach 和消息转拨
	m_eye.m_pDlg = this;	
	m_eye.SubclassDlgItem(IDC_SHOW, this); //升级版  不需要成对使用		句柄和父窗口
	CDialogEx::OnInitDialog();
	auto hIcon = theApp.LoadIcon(IDI_LOGIN);
	SetIcon(hIcon,false);
	return TRUE;  // return TRUE unless you set the focus to a control 
}
void CLoginDlg::OnDestroy(){
	CDialogEx::OnDestroy();
	m_eye.UnsubclassWindow();	 
}

SubclassWindow源码

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)::SetWindowLongPtr(hWnd, GWLP_WNDPROC,
		(INT_PTR)AfxGetAfxWndProc());
	ASSERT(oldWndProc != AfxGetAfxWndProc());

	if (*lplpfn == NULL)
		*lplpfn = oldWndProc;   // the first control of that type created
#ifdef _DEBUG
	else if (*lplpfn != oldWndProc)
	{
		TRACE(traceAppMsg, 0, "Error: Trying to use SubclassWindow with incorrect CWnd\n");
		TRACE(traceAppMsg, 0, "\tderived class.\n");
		TRACE(traceAppMsg, 0, "\thWnd = $%08X (nIDC=$%08X) is not a %hs.\n", (UINT)(UINT_PTR)hWnd,
			_AfxGetDlgCtrlID(hWnd), GetRuntimeClass()->m_lpszClassName);
		ASSERT(FALSE);
		// undo the subclassing if continuing after assert
	  ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (INT_PTR)oldWndProc);
	}
#endif

	return TRUE;
}


总结嫁接与子类化:

a)Attach和Detach就是单纯的嫁接
b)子类化Subclass内部包含Attach,增强了消息转移机制。
c)SubClassDlgItem简化了子类化功能,不需要反子类化UnsubclassWindow
d)类向导中建立关联变量的方法(内部就是子类化)

DDX_Control函数内的核心内容是,引用类成员变量m_xxx,
{
pDX->m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl);
rControl.SubclassWindow(hWndCtrl))

}
void CXxxxxx::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST, m_list);
	DDX_Control(pDX, IDC_PRIOR, m_combo);
}

DDX_CONTROL源码

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 defined(_AFXDLL) || !defined(_AFX_NO_MFC_CONTROLS_IN_DIALOGS)
		CMFCControlContainer* pMFCCtrlContainer = pDX->m_pDlgWnd->GetMFCControlContainer();
		if (pMFCCtrlContainer != NULL && pMFCCtrlContainer->IsSubclassedFeaturePackControl(hWndCtrl))
		{
			pMFCCtrlContainer->ReSubclassControl(hWndCtrl, (WORD)nIDC, rControl);
			return;
		}
#endif

		if ((hWndCtrl != NULL) && !rControl.SubclassWindow(hWndCtrl))
		{
			ASSERT(FALSE);      // possibly trying to subclass twice?
			AfxThrowNotSupportedException();
		}
		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);
			}
		}
	}
}

你可能感兴趣的:(MFC开发,mfc,c++)