句柄嫁接与子类化
句柄嫁接与子类化:
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文章来源:https://www.toymoban.com/news/detail-566677.html
示例代码
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)类向导中建立关联变量的方法(内部就是子类化)文章来源地址https://www.toymoban.com/news/detail-566677.html
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补充第十四天 句柄嫁接与子类化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!