MFC:一个 window 上的 X 按钮也在关闭第二个 window

MFC: X button on one window is closing a second window also

我的应用程序有几个 windows,每个都是不同的 CDialog 派生的 class。

点击 window 框架右上角的 "X" 按钮关闭 window 并调用 PostNcDestroy.

但是,对于四个 windows 之一,它还另外调用另一个 window 的 PostNcDestroy() 并使 window 不可见。

有什么想法吗?

你提供的信息不多。我们只能猜测...因为您声明所有 windows 都是对话框,我猜想在您的应用程序的 InitInstance() 方法中,您调用了主 CDialog 派生的 DoModal() class.关闭主对话框后,它退出 DoModal() 循环,然后退出 InitInstance() 并关闭应用程序。应用程序关闭导致其他对话框被销毁,导致 WM_NCDESTROY 被发送,然后 PostNcDestroy() 被调用。

简短回答:该行为是由在创建所有四个 windows 之后设置 m_pMainWnd 引起的。如果在创建第二个window之前设置,则不会再出现上述问题。

长答案:问题是 windows 彼此不是兄弟姐妹。它们都是上一个的 CHILD。

Parent of window 1 是值“0”(桌面)。 window 2 的 Parent 是 window 1。 window 3 的 Parent 是 window 2。 window 4 的 Parent 是 window 3.

我最初的问题报告指出 window 4 在 window 3 关闭时神秘关闭。所以现在原因很明显了。 (关闭 window 也会关闭其所有 children。)我随后发现关闭 window 2 也会导致 3 和 4 关闭,这也被考虑在内。 (3 是 2 的 child 所以关闭,这使得 4 是 3 的 child,关闭。)最后,关闭 window 1 检查未保存的工作,如果 none调用 exit()。我假设如果这个 window 没有退出,另一个 windows 也会全部关闭。

CDialog::Create() 的第二个参数 pParentWnd 有默认参数 NULL,而 NULL 表示 parent "is set to the main application window." 进入 CDialog::Create(),它调用 CDialog::CreateIndirect(),它调用 AfxGetMainWnd() 我最终在 CWinThread::GetMainWnd()。该方法,如果尚未设置m_pMainWnd,则returns CWnd::GetActiveWindow() 即most-recently-created window.

所以:问题的根源是我的应用程序创建了四个 windows,然后设置了 m_pMainWnd。这就是为什么 window 3 是 window 2 的 child(当时活跃的 window)4 是 3 的 child,依此类推。

通过在创建window1之后设置m_pMainWnd,那么windows2 3和4就是1的children。这样就去掉了"closing window 3 makes window 4 close too"问题。

这仍然不是我所需要的,因为它阻止了 window 1 被带到其他三个 windows 的前面。这超出了我最初问题的范围,但这是解决方法。更改 Create() 调用以明确传入 GetDesktopWindow() 似乎已经让应用程序按我想要的方式运行,四个 windows 可以独立关闭并可以在 window 中自由订购堆栈:

  Create( resource_ID, GetDesktopWindow() );

我很惊讶这不是一个著名的问题,因为这些函数的 NONE 的文档(从 VS2008Pro 开始)实际上解释了当未设置 m_pMainWnd 时它们实际做了什么,并将该简单分配移动到 m_pMainWnd 到 window 创建的末尾可能会搞砸任何创建超过两个 windows...

的应用程序