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

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:

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.

Related

may be a big problem if I declare a control that derives from CWnd but never use it ? MFC

Let me give you quick scenario:
I have CEdit decleration in MyDlg.h but never used.
CEdit m_edit; // member variable of CMyDlg
So, my guess is if I'm not mistaken, any CWndcontrols' m_pWnd gets destroyed through CWnd::DestroyWindow(); function when application gets closed.
In this case, m_edit is not getting be created, that means it has no valid m_pWnd value.
In result, when trying to destroy m_edit, which m_edit.m_pWnd == NULL, I think it may be problem.
So, here is my question:
What is the probability of an error occurring in this situation? and how bad is doing this?
Updating question:
When I run my app, sometimes gives this exception: unhandled exception occurred during a user callback
When I see in callStack, called in this order: ~CMainFrame()--> ~CMyDlg() --> ~CEdit() --> ~CWnd() and it stops in wincore.cpp line804: delete m_pMFCCtrlContainer;
As I explained in old question, I was thinking if it's because of my unused CEdit declaration. But no, even if I commented that out the same issue is happening.
Related to that, there was this answer:
Line 804 in wincore.cpp is only ever hit if m_hWnd != NULL. The statement that m_edit were never used is thus necessarily false. Your code is either constructing a window (through a call to Create or similar), or attaching the m_edit instance to an existing window (commonly done through a DDX_Control in DoDataExchange).
But CEdit variable is not attached to a window (checked in DoDataExchange), also any Create or similar functions are called
So, how do you think what can be the reason of this delete m_pMFCCtrlContainer; issue??

When is a Paint msg being invoked on a CCmdUI::Enable() call?

I'm trying to debug this problem in a library where a set of controls are not being updated to be disabled. I've drilled down to a point where I've hit a black box. A mfc120ud.dll!CCmdUI::DoUpdate() call will then call CCmdUI::Enable(). It'll then go through a bunch of calls one through ntdll.dll and 4 through user32.dll for which I have no source for and then sometimes stick its head our coming back to mfc123ud.dll or sometimes not.
I don't know why the WM_PAINT message gets invoked sometimes. Does anyone know?
Your call stack shows the reason.
CCmdUI::DoUodate finally calls CCmdUI::Enable.
Look into the CCmdUI::Enable code of the MFC. There are cases that WM_NEXTDLGCTL is called or EnableWindow. WM_NEXTDLGCTL may cause a focus change. It depends how the controls will handle this message. It is possible that they directly call UpdateWindow or RedrawWindow to reflect changes to the UI, instead of just calling Invalidate(Rec). There may be a control inside your ribbon that receives the WM_PAINT message.
The call to EnableMenuItem should be safe and I am sure that it doesn't cause a WM_PAINT call.

In MFC, when opening a file or creating a file, is WM_PAINT generated?

I am learning MFC programming with the book "Programming Windows with MFC (2nd Edition)". I have some questions about the book example from chapter 9.
When I open a file or click new file, the function CSquaresView::OnDraw() is called. I checked the stack, the reason is that CView::OnPaint() calls this function.
But I don't understand how CView::OnPaint() is called. Is the message WM_PAINT generated if CSingleDocTemplate::OpenDocumentFile() is called by the default setting? Is
it possible to change the behavior?
Thanks,
Brian
WM_PAINT is triggered for every window that just was created and gets visible.
But internally the following code is executed (depending of MDI/SDI) that forces a window update:
CSingle/MultiDocTemplate::OpenDocumentFile.
So either a new CDocument is created or a previous one is reused and prepared.
A new Frame window is created or reused.
The new view is created or the old ne reused.
finally InitialUpdateFrame is called!
InitialUpdateFrame sends a message to all created frames and this finally causes CView::OnInitialUpdate to be called.
OnInitialUpdate just calles again CView::OnUpdate and the default implementation calles CWnd::Invalidate
Now on the next turn in the message loop the window receives a WM_PAINT message.
Preventing OnDraw to be executed wouldn't be wise, because the contents of your document can't be displayed to the user in this case. And this has to be done, always when the window is new, or the contents of the document just changed (here it changed after loading a new document).
While I don't have the book or know what the sample is about (and I don't think many readers of this do...), I conjecture that the reason you're getting a WM_PAINT is because a file open dialog is opened which covers your drawing area at some point, and when it is closed, that area is invalidated. Is that possible?
Am I missing something? This is standard windows behavior. CView::OnPaint() is called because windows has generated WM_PAINT message. If you are debugging and set a break point in OnDraw() it will always break there because the debugger and application takes turns to run (but unless you application is running on a separate monitor) and WM_PAINT is generated. If you do want to stop redrawing though, try SetRedraw

Message Box sending Windows messages?

I've got a relatively simple Window class. I've created a window, associated my this, etc etc. Now later, I've thrown an exception to indicate a problem. When I call MessageBox to pop up the error, the program crashes, because it's attempting to call my Window Proc. Now, I mean, admittedly, I failed SRP here and just writing a brief self-owning HWND class will solve this problem, as the window wasn't cleaned up properly. However, I'm really mystified as to why it's trying to process Window messages in my MessageBox call- the owner parameter is nullptr. Any suggestions?
Edit: If I call DestroyWindow appropriately, then now the message box just doesn't show up, although the app doesn't crash. It only works if I manually remove this from the window, so that if the proc were called it would forward to DefWindowProc, and then DestroyWindow. I mean, I thought that if you called MessageBox without an owner, then it would just work, regardless of what you had done to other windows in the system.
What is happening here is that there are still messages for the dud window in the queue when you show the message box. The message box runs a modal window message pump and dispatches the troublesome messages. Remember that all windows created from the same thread share a single message queue.
I have no idea how to fix your problem but that's what's going on.
By the way, passing a null owner isn't a great idea as it will result in your message box not being minimised when your main app is minimised, for example.

Globally intercept window movement

I am having trouble getting a global system hook to work. I want to be notified whenever a window is moving, as early as possible, and change the window size. This means the CBT hook HCBT_MOVESIZE won't cut it, it only happens after the window has been moved. I want to hook the actual movement of the window, and be able to change the window size during the move.
The hooks are set from a DLL, and the callback function is within that DLL. This is what I've tried.
WH_CALLWNDPROC. It does alert me when a window is moved (WM_MOVING is received for windows from other applications), but I cannot change the contents of the message.
WH_CALLWNDPROCRET Same as WH_CALLWNDPROC.
CBT hook HCBT_MOVESIZE. Event happens to late.
WH_GETMESSAGE. Never receive WM_MOVE, WM_MOVING or WM_WINDOWPOSCHANGING. This hook would allow me to change the messages.
Update: Windows event hooks seem to allow me to capture it:
hWinEventHook = SetWinEventHook(EVENT_SYSTEM_MOVESIZESTART,
EVENT_SYSTEM_MOVESIZEEND, NULL, WinEventProc,
0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
However, this creates a different problem: changing the size of the window using SetWindowPos() does not work (it changes size alright, but immediately changes back to its previous size), even though I use SWP_NOSENDCHANGING. Ideas?
Update 2: Subclassing seems to work, however Visual Studio crashes after each program run (so does a lot of other windows). It works well if I place breakpoints and walk through the "unsubclassing", but not when I let the program run by itself. Ideas?
I have a CBT hook (it was there from earlier), and whenever HCBT_ACTIVATE is sent for a new window, I remove any previous subclassing using SetWindowLongPtr() (this has to run on 64-bit as well), and then subclass the new window. If I put a breakpoint anywhere, and immediately resume the session when it breaks, everything works fine. However, when I do not have any breakpoints, Visual Studio crashes when the program exits.
Hm, I would've thought that HCBT_MOVESIZE is precisely what you want, given that the MSDN says this about CBT hooks:
The system calls this function before activating, creating, destroying,
minimizing, maximizing, moving, or sizing a window.
and in particular:
HCBT_MOVESIZE
A window is about to be moved or sized.
(these quotes were taken from http://msdn.microsoft.com/en-us/library/ms644977%28VS.85%29.aspx)
...so I'd have thought that you get the HCBT_MOVESIZE call in time. The hook function which handles HCBT_MOVESIZE is also allowed to return an integer so that the system can determine whether the operation is allowed or should be prevented. Hence, given that the HCBT_MOVESIZE hook should get an option to prevent the operation, I'd say it's called before the move event occurred.
Are you really sure the hook function is called after the move event? If you do a GetWindowRect call on the particular handle within your hook function, does the returned rect equal the rectangle which is passed to the hook function?
Hooks are pretty heavy. You only want to use them when you absolutely have to.
That said, you could use one of the basic hooks simply as a way to get into the process. Once in the process, you could subclass the window you're interested in and handle the sizing messages in your subclass proc rather than trying to catch everything at the hook level.
Depending on what you want to do in response to the resize, you might need some interprocess communication.