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

句柄嫁接与子类化

句柄嫁接与子类化:
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);
			}
		}
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jcrry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值