Search code examples
mfcvisual-studio-2019

Why is my AfxMessageBox invisible/hidden until Alt is pressed?


I'm working on an MFC app. I have a class inheriting from CWinApp which tries to open an AfxMessageBox inside its InitInstance function.

When the AfxMessageBox function is called, no message-box is visible, but I hear a Windows bell sound. If I press Alt, the message box appears. Why isn't the AfxMessageBox appearing immediately?

This question mentions a similar issue, but the answer only refers to the non-MFC function MessageBox, not AfxMessageBox which is what I'm using:

MFC MessageBox Not Showing at Top Of All Windows


Update 1

I'm working on a minimal reproducible example, but it's tricky because this is part of a large application with poor encapsulation.

In my app, it appears that a call to the function ProcessShellCommand() is causing AfxMessageBox to stop working. However, calls to AfxMessageBox work correctly both before and after ProcessShellCommand in a newly-created MFC application.

It looks like some consequence of calling ProcessShellCommand is causing AfxMessageBox to behave differently, but I'm not sure how to identify all the consequences of calling ProcessShellCommand. When I'm debugging, the particular call to ProcessShellCommand includes a filename, so the file-open command is causing the app's CView to be launched.

In the OnInitialUpdate code for my CView-inheriting class, AfxMessageBox functions correctly. The best transition point I can identify between AfxMessageBox working, and not working, is when the CView's OnInitialUpdate function returns from it being called by ProcessShellCommand.


Update 2

It seems that m_pMainWnd is NULL before the call to ProcessShellCommand (while AfxMessageBox is working as expected), and non-NULL after the call to ProcessShellCommand.

Based on this discussion: Why would a message box be not displaying? , I tried printing out the message-queue contents before and after the call to ProcessShellCommand. Before, the message-queue only contains a single message. Afterwards, the message-queue printout loop is full of WM_PAINT and it never terminates until I press Alt. This makes me think that I'm running into a message-pump-related issue rather than something related to e.g. visibility state.

---------- More observations ------------

It looks like the call to AfxMessageBox stops inside win32u.dll; I determined this by hitting the 'pause execution' button while waiting for the message-box to appear. Here's the call-stack and debug screenshot:

Call stack Program pointer


Solution

  • It turns out that my CWinApp had a CFrameWnd class that I had forgotten about; I was focusing too much on the CView class.

    In the CFrameWnd class, in the BEGIN_MESSAGE_MAP block, there was an ON_WM_TIMER(). I removed this from the message-map to test, and the AfxMessageBox() worked as expected.

    When I create a fresh SDI application, there is no ON_WM_PAINT() in the message-map block, so I think this may have been added incorrectly. The class itself does not implement OnPaint(), so I guess this caused some unhandled WM_PAINT messages to be floating around.

    It's a bit surprising that this doesn't lead to a compiler error; as I understand it, having ON_WM_PAINT() only makes sense if there's a corresponding OnPaint() function.