Date: | April 6, 2005 / year-entry #87 |
Tags: | code |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20050406-57/?p=35963 |
Comments: | 10 |
Summary: | Last time, we solved the problem with the EndManualModalDialog function by posting a harmless message. Today, we're going to solve the problem in an entirely different way. The idea here is to make sure the modal message loop regains control, even if all that happened were incoming sent messages, so that it can detect that... |
Last time, we solved the problem with
the
The idea here is to make sure the modal message loop
regains control, even if all that happened were incoming
sent messages, so that it can detect that the
Instead of changing
the int DoModal(HWND hwnd) { DIALOGSTATE ds = { 0 }; HWND hdlg = CreateDialogParam(g_hinst, MAKEINTRESOURCE(1), hwnd, DlgProc, reinterpret_cast<LPARAM>(&ds)); if (!hdlg) { return -1; } EnableWindow(hwnd, FALSE); MSG msg; msg.message = WM_NULL; // anything that isn't WM_QUIT while (!ds.fEnded) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { /* fixed 8am */ break; } else if (!IsDialogMessage(hdlg, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } /* fixed 10am */ } else if (!ds.fEnded) { WaitMessage(); } } if (msg.message == WM_QUIT) { PostQuitMessage((int)msg.wParam); } EnableWindow(hwnd, TRUE); DestroyWindow(hdlg); return ds.iResult; }
We changed the call to
That's the control we want.
If
Exercise: If the whole point was to regain control
after sent messages are delivered, why isn't there a test
of the |
Comments (10)
Comments are closed. |
Raymond… Completely off topic, but you may want to make a post about the new login stuff.
Or if you could at least get a log in link on your page, that might help. It took some digging to figure out that I had to
a) Log in to post a comment.. and
b) Go to the main blogs.msdn.com to do it.
I think the reduction in your comment traffic shows that other people are just as confused.
"…why isn’t there a test of the fEnded flag immediately after DispatchMessage returns? "
There is, or at least the only thing between the return of DispatchMessage and the test of fEnded is most likely a single JMP instruction to the top of the while loop.
Since IsDialogMessage has the side-effect of processing the message when it returns TRUE, the DispatchMessage in the main loop isn’t being used for any case where fEnded might be set.
Is that loop handling WM_QUIT correctly now? PeekMessage retrieves WM_QUITs but GetMessage doesn’t and returns 0.
But why not to use Event and MsgWaitForMultipleObjects instead of using boolean variable?
Call me stupid, but I don’t get how this solves the problem. Can’t you get stuck in WaitMessage just like the previous implementation got stuck in GetMessage? Wouldn’t you still need to post a message to get the loop to wake up and see that the flag has changed?
I suppose that if you assume the EndManualModalDialog only gets called while processing a message that was dispatched from the modal loop, it’ll work, but that seems like you’re solving for a specific case.
[A sign-in link from the individual blog pages would be nice, since many of us navigate directly to postings we’re interested in from the RSS feed.]
"But why not to use Event and MsgWaitForMultipleObjects instead of using boolean variable?"
I would ask the question in reverse. Why use an Event and MsgWaitForMultipleObjects when a simple boolean variable is all you need?
[Alas I do not control the server software. I’ll forward these concerns to the people who run the server.]
Okay, it wasn’t handling WM_QUIT correctly. To correct my previous comment, I meant to say that GetMessage returns 0 on WM_QUIT, but it does retrieve it.
One topic I’d like to see discussed is when it is "safe" to ignore the fact that GetMessage can return -1. For example, am I safe if hwnd is valid and &msg is a good address? The GetMessage docs are pretty insistent that -1 is a possible outcome and should be handled gracefully.
That code still isn’t quite right; the braces don’t match. If I’m following this correctly I think there should be two close-braces after the DispatchMessage() call.
Doesn’t this suffer from the same thing as http://blogs.msdn.com/oldnewthing/archive/2005/02/17/375307.aspx ?
Adrian: As I understand it (from the MSDN docs) GetMessage does not return until a *posted* message is in the queue. WaitMessage returns if *any* message (posted, input, sent, WM_PAINT, WM_TIMER) is in the queue.
My stab at the exercise: From the SDK PeekMessage docs…
"The PeekMessage function *dispatches* incoming *sent messages*, checks the thread message queue for a posted message, and retrieves the message (if any exist)."
Therefore sent messages never get to the DispatchMessage branch.