(标题已更新) 继this问题之后,现在我更清楚地了解发生了什么......
我有一个没有主窗口的MFC应用程序,它公开了一个API来创建对话框。当我反复调用其中一些方法时,创建的对话框是彼此的父级,而不是所有对象的父级......我不知道为什么。
但是无论如何,即使在创建之后,我也无法将父级更改回NULL或CWnd :: GetDesktopWindow()...如果我调用SetParent后跟GetParent,则没有任何更改。
除了真正奇怪的问题,为什么Windows神奇地将每个对话框教育到最后创建的对话框之外,还有什么我不知道能够将这些窗口设置为桌面的孩子吗?
更新:我找到了所有这些的原因,但没有找到解决方案。从我的对话框构造函数中,我们最终进入:
BOOL CDialog::CreateIndirect(LPCDLGTEMPLATE lpDialogTemplate, CWnd* pParentWnd,
void* lpDialogInit, HINSTANCE hInst)
{
ASSERT(lpDialogTemplate != NULL);
if (pParentWnd == NULL)
pParentWnd = AfxGetMainWnd();
m_lpDialogInit = lpDialogInit;
return CreateDlgIndirect(lpDialogTemplate, pParentWnd, hInst);
}
注意: if (pParentWnd == NULL)pParentWnd = AfxGetMainWnd();
我的对话框构造函数中的调用堆栈如下所示:
在调试器中运行,如果我在CDialog :: CreateIndirect中手动将pParentWnd更改回0,一切正常......但我如何在第一时间停止它?
答案 0 :(得分:7)
一些想法:
首先,您在整个链中传递父窗口的NULL。当MFC试图找到你的应用程序主窗口时它的预测非NULL。
我认为你有两种缓解措施:
最后一点。 MFC术语很不幸: - 在Windows上,只有子窗口有父窗口。弹出窗口或桌面窗口具有所有者窗口。 CreateWindow接受一个接受所有者的参数,或者正在创建的窗口的父级。区别很重要,因为虽然父窗口可以更改,但所有者不能。 SetParent不会更改弹出窗口或重叠窗口的所有者窗口。
答案 1 :(得分:1)
好的,找到了!
实际上有两个问题。我作为父/所有者传递NULL ...但尝试传递CWnd::GetDesktopWindow()
没有帮助,所以我放弃了这个想法,直到找到CDialog::CreateIndirect
的行为。这让我仔细看看我的代码,我终于发现MyDialog::MyDialog(CWnd *pParent)
正在调用super::Create(NULL)
,而不是super::Create(pParent)
...因为我们总是在它之前将它传递给NULL从未如此明显。
再一次,难以解决的问题只是距离错字一步之遥!
答案 2 :(得分:0)
MFC一次只能创建一个窗口。至少在黑暗和遥远的过去,当MFC创建Win32窗口时,它需要将MFC CWnd实例与窗口关联。因为窗口接收的第一条消息不是带有LPVUSERDATA参数的WM_CREATE消息MFC将CWnd实例存储在线程局部变量中 - 在不合理的期望下,对CWnd :: WindowProc的下一次调用将是它开始尝试的窗口创建
我不知道如何实际编写代码来破坏这个过程。这一切都取决于你如何以不同的速度创造窗户。