为啥在按下 Alt 之前我的 AfxMessageBox 是不可见/隐藏的?

Posted

技术标签:

【中文标题】为啥在按下 Alt 之前我的 AfxMessageBox 是不可见/隐藏的?【英文标题】:Why is my AfxMessageBox invisible/hidden until Alt is pressed?为什么在按下 Alt 之前我的 AfxMessageBox 是不可见/隐藏的? 【发布时间】:2020-12-09 22:30:05 【问题描述】:

我正在开发 MFC 应用程序。我有一个继承自 CWinApp 的类,它试图在其 InitInstance 函数中打开一个 AfxMessageBox

当调用AfxMessageBox 函数时,看不到任何消息框,但我听到了Windows 铃声。如果我按 Alt,则会出现消息框。 为什么AfxMessageBox 没有立即出现?

这个问题提到了一个类似的问题,但答案只涉及非 MFC 函数MessageBox,而不是我正在使用的AfxMessageBox

MFC MessageBox Not Showing at Top Of All Windows


更新 1

我正在研究一个可重现的最小示例,但这很棘手,因为这是一个封装不佳的大型应用程序的一部分。

在我的应用程序中,对函数 ProcessShellCommand() 的调用似乎导致 AfxMessageBox 停止工作。但是,在新创建的 MFC 应用程序中,在 ProcessShellCommand 之前和之后对 AfxMessageBox 的调用都能正常工作。

看起来调用ProcessShellCommand 的某些后果导致AfxMessageBox 的行为有所不同,但我不确定如何识别调用ProcessShellCommand 的所有后果。当我调试时,对 ProcessShellCommand 的特定调用包含一个文件名,因此 file-open 命令导致应用程序的 CView 启动。

在我的CView-inheriting 类的OnInitialUpdate 代码中,AfxMessageBox 正常工作。我可以确定AfxMessageBox 工作和不工作之间的最佳转换点是当CViewOnInitialUpdate 函数从它返回时被ProcessShellCommand 调用。


更新 2

似乎m_pMainWnd 在调用ProcessShellCommand 之前是NULL(而AfxMessageBox 正在按预期工作),而在调用ProcessShellCommand 之后不是NULL

基于此讨论: Why would a message box be not displaying? ,我尝试在调用ProcessShellCommand 前后打印出消息队列的内容。以前,消息队列只包含一条消息。之后,消息队列打印输出循环充满了WM_PAINT,并且在我按下Alt 之前它永远不会终止。这让我觉得我遇到了与消息泵相关的问题,而不是与例如相关的问题。可见性状态。

---------更多观察------------

看起来对 AfxMessageBox 的调用在 win32u.dll 内停止;我通过在等待消息框出现时点击“暂停执行”按钮来确定这一点。这是调用堆栈和调试屏幕截图:

【问题讨论】:

minimal reproducible example 是必需的。 什么版本的VS?另见AfxMessageBox going on background。 @dxiv VS2019。谢谢,我检查了该链接-似乎通过PostMessage(WM_SYSKEYDOWN)以编程方式创建按键来建议一种解决方法。这可能是一个好的创可贴,但我更愿意以“正确”的方式解决这个问题。 @afarley This 当时被报告为一个错误,但 Microsoft Connect 站点已停用,旧链接不再有效。 AfxMessageBox 本质上是MessageBox 的包装。后者接受一个明确的所有者窗口句柄。前者没有,并且所有者是从应用程序状态推导出来的。这就是 MFC:它似乎以要求用户了解其内部实现的几乎每个方面为代价来简化界面。首先单步进入AfxMessageBox 并从那里获取。 【参考方案1】:

原来我的CWinApp 有一个我忘记的CFrameWnd 类;我过于关注CView 类。

CFrameWnd 类中,在BEGIN_MESSAGE_MAP 块中,有一个ON_WM_TIMER()。我将其从消息映射中删除以进行测试,并且 AfxMessageBox() 按预期工作。

当我创建一个新的 SDI 应用程序时,消息映射块中没有 ON_WM_PAINT(),所以我认为这可能是添加不正确的。该类本身没有实现OnPaint(),所以我猜这会导致一些未处理的WM_PAINT 消息四处飘荡。

这并没有导致编译器错误,这有点令人惊讶;据我了解,只有在有相应的 OnPaint() 函数时,ON_WM_PAINT() 才有意义。

【讨论】:

可能是基类提供了一个默认的OnPaint 函数,它不能满足您的需要。

以上是关于为啥在按下 Alt 之前我的 AfxMessageBox 是不可见/隐藏的?的主要内容,如果未能解决你的问题,请参考以下文章

在android中,为啥我的服务在按下电源按钮后没有进入睡眠状态

为啥不显示消息框?

如何在按下按钮之前激活按钮?

在按下 UIButton 之前预加载动画图像

确定在按下按钮之前最后一个焦点的 QWidget

WPF Focused Visual State 仅在按下按钮时才会启动,为啥?