基于 CDialog 的应用程序是不是应该设置 AfxGetApp()->m_pMainWnd

Posted

技术标签:

【中文标题】基于 CDialog 的应用程序是不是应该设置 AfxGetApp()->m_pMainWnd【英文标题】:Should a CDialog based app set AfxGetApp()->m_pMainWnd基于 CDialog 的应用程序是否应该设置 AfxGetApp()->m_pMainWnd 【发布时间】:2013-12-05 18:03:42 【问题描述】:

编辑:

我需要先研究一些奇怪的东西,有什么办法可以“搁置”这个问题吗?

原文:

我正在使用基于 CDialog 的 GUI 处理现有代码库。该应用程序包含一个 CDialog“MainWindow”,它使用 CDialog.DoModal 生成其他 CDialog“SubWindow”。 这在显示子窗口、主窗口块等时确实有效。

当我们从“子窗口”调用 AfxMessageBox 时,主窗口重新启用并获得焦点。

调试到 AfxMessagebox 显示,该函数获取 mainWindow 并重新启用它。这会导致许多不同的错误。使用 ::MessageBox 可以正常工作,但我们有大约 50 个不同的 SubWindows,如果可能的话,我只想做一些小的本地化更改。

C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\atlmfc\src\mfc\appui1.cpp

int CWinApp::ShowAppMessageBox(CWinApp *pApp, LPCTSTR lpszPrompt, UINT nType, UINT nIDPrompt)
...
HWND hWndTop;
HWND hWnd = CWnd::GetSafeOwner_(NULL, &hWndTop);

// re-enable the parent window, so that focus is restored 
// correctly when the dialog is dismissed.
if (hWnd != hWndTop)
    EnableWindow(hWnd, TRUE);
...

在我们的入口点我们做这样的事情:

::AfxGetApp()->m_pMainWnd = &mainDlg;
mainDlg.DoModal();

首选的方式是什么?我应该评论该行以使成员保持 NULL 吗?

或者这会导致任何副作用吗?

我猜(尚未测试)我也可以设置

AfxGetApp()->m_pMainWnd = &subDlg;

在 subDlg.DoModal() 之前并在之后重置它,但这也意味着更改 50 个不同的文件,每个子窗口一个。

MFC 是否依赖于 m_pMainWnd,还是应该让它保持为 NULL? 谢谢。

编辑:

我尝试将 MainWindow 传递给 SubWindow 的构造函数,但无济于事。

这是 MainWindow 重新启用的地方:

这是 MFC 找到 MainWindow 的地方: 我需要手动设置 m_pActiveWnd 吗?

(OFF 主题:我喜欢有可用的 mfc 源代码。)

编辑 2:

MFC App实际上是一个DLL,可以通过两种方式调用: 由简单的 loader.exe 或任何其他大型应用程序加载。 这个其他应用程序也可能使用 MFC,因此可能有两个不同的 CWinApp 对象。

如果是loader.exe加载,则不会出现错误。

【问题讨论】:

【参考方案1】:

MFC 在很多情况下都依赖于 m_pMainWnd。将其保留为 NULL 不是一个好方法,也不能解决您的问题。

主要问题接缝更加微妙。问题是为什么 AfxMessageBox 发现主对话框是最后一个活动的,而不是你的子对话框。如果您在创建新的基于子对话框的 con CDialog 时没有定义 pParent,这可能只是个问题。

尝试将当前活动的对话框传递给您正在调用的子对话框。 CDialog“自动”找到父级。但有时它对我不起作用。 我遇到了同样的问题,在消息框或 DoModal 之后再次启用了错误对话框。

我修复了它,在创建子对话框时始终定义父级。

【讨论】:

不幸的是,将 MainWindow 传递给 SubWindow 的构造函数并没有改变。 你有simle小样吗。我刚刚使用向导创建了一个,但它按预期工作。 调试到函数 CWnd::GetSafeOwner。查看此代码。 (由 ShowAppMessageBox 调用)。此代码确定被禁用和再次启用的窗口。最好使用远程调试,因为调试此代码可能会更改活动窗口...

以上是关于基于 CDialog 的应用程序是不是应该设置 AfxGetApp()->m_pMainWnd的主要内容,如果未能解决你的问题,请参考以下文章

MFC中CDialog 的OnKeyDown()为啥不好使?

★VC-MFC◆CToolbarCtrl && CDialog 下拉菜单 ★

MFC中 如何设置CDialog可以拉伸? 就像单文档的窗口那样? 还是要自己去实现的?

设置基于MFC对话框的应用程序窗口的位置

错误 C2309:不是 CDialog 的成员

WTL 没有 CDialog 怎么办