How to test for WM_CLOSE message before Dispatching it ?

Started by
9 comments, last by Direct4D 20 years, 4 months ago
Okay i''m new to this forum, so first of all: Hi to everyone Ok, to the business now... I''m working on some piece of window handling code. And i need to test for a WM_CLOSE message before i dispatch it to the message handler. I tried the following:

// following code is implemented in a class method

// receivedCloseMessage is a boolean class property


MSG msg;
while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )){
    if( WM_CLOSE == msg.message ) receivedCloseMessage = true;
    TranslateMessage( &msg );
    DispatchMessage( &msg );
}
But the WM_CLOSE message doesn''t seem to show up there. However it will show up in the message handler itself. I''m also not able to test for WM_DESTROY messages. Only message that i can seem to test for is the WM_QUIT message. Does anyone have a clue as to why i''m unable to find WM_CLOSE or WM_DESTROY messages in my message dispatching code ?
Advertisement
Just handle the WM_CLOSE message in your message handler and set the flag there?


"Absorb what is useful, reject what is useless, and add what is specifically your own." - Lee Jun Fan
"Absorb what is useful, reject what is useless, and add what is specifically your own." - Lee Jun Fan
I think WM_CLOSE and WM_DESTROY are associated with a particular window which your program could have many of. You need to pass the window handle into PeekMessage to receive those.

WM_QUIT will only be retrieved when the window handle passed is NULL because is it a message to the program not a specific window. This was causing me lots of problems when using the code from OpenGL Game Programming.
Thx for the quick replies.

JY,
The reason i don't want to handle the WM_CLOSE in my message handler itself, is because i'm trying to build some sort of wrapper class for windows.
The message handler must either be a normal function or a static function inside that class.
I implemented it as an static function. But because it is static it doesn't know which WindowObject instance it is handling messages for.

However i was digging through the articles here on GameDev and i found an solution here:
Creating a Win32 Window Wrapper Class

I implemented it roughly in the same fashion now.

Londey,
I tried passing the window handle in the PeekMessage. But my WM_CLOSE messages still don't show up there
It's just as if WM_CLOSE messages get send to the message handler directly. But my logic tells me that that should not be the case.
I guess it will remain a mystery for me as to why i cannot find my WM_CLOSE messages.


[edited by - Direct4D on November 27, 2003 7:56:30 AM]

[edited by - Direct4D on November 27, 2003 7:56:49 AM]

[edited by - Direct4D on November 27, 2003 7:57:18 AM]

[edited by - Direct4D on November 27, 2003 7:57:48 AM]
tried putting a breakpoint in your message handler and looking at the callstack to see if it goes through your message dispatch or not?
Some messages are generated indirectly.
Means you will see some (but NOT all) messages in your loop.

Some of these messages get heavily processed by the defwindowproc; resulting in one or more other messages sent to your handler proc (e.g. WM_CLOSE). You will not get WM_CLOSE in a loop.

If you have only one general message pump for all your windows it''s enough to check for WM_QUIT.
If you have a message pump for only one window (which you shouldn''t unless that window is modal) you could get away with having a member variable of type HWND in the class and check if it is still valid (either set to NULL upon receiving WM_NCDESTROY in your handler or use IsWindow).

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

depending on how the application is "closed," WM_CLOSE is not necessarily even sent. so assuming it is and trying to write a wrapper class that makes that assumption is not a good idea.

anyway, iirc, both WM_CLOSE and WM_DESTROY are sent directly to the appropriate window''s message processing function. there are a number of messages which are handled in this way. they do not get put onto the message queue, so your app will never see them unless it looks for them in a message handler.

also, Londey''s suggestion that you need to use an HWND with PeekMessage to retrieve them is incorrect. using NULL for the HWND in a PeekMessage call means that any window or non-window message will be retrieved. it''s only when you use a particular HWND that PeekMessage filters the messages so that only messages associated with that given HWND are returned.
Fair enough - so can you not call the static function with a pointer (or a reference) to the particular object you want it to manipulate?


"Absorb what is useful, reject what is useless, and add what is specifically your own." - Lee Jun Fan
"Absorb what is useful, reject what is useless, and add what is specifically your own." - Lee Jun Fan
i believe that article you referenced shows one method of passing an object''s this pointer to a message handler.

the most straightforward way, for me anyway, tying a non-static class message handler to an instance of a window object is to pass the this pointer of the object as the lpParam parameter during a CreateWindow call. the static message handler function''s WM_NCREATE handler then extracts that value from the passed CREATESTRUCT and sets the associated window''s USERDATA value via a SetWindowLong call.

at that point each window created in this manner will have its associated object''s this pointer in its USERDATA value. so subsequent messages handled by the static message handler simply use GetWindowLong to retrieve this this pointer, cast it to a pointer of the appropriate window class type, and then call that class object''s non-static message handler to complete the processing.

here''s what my window object''s static message handler looks like:
LRESULT CALLBACK aqWindow::aqWndMsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){    if( uMsg == WM_NCCREATE )        SetWindowLong(hWnd, GWL_USERDATA, (LONG)(((LPCREATESTRUCT)lParam)->lpCreateParams));    aqWindow* pWindow = reinterpret_cast<aqWindow*>(::GetWindowLong(hWnd, GWL_USERDATA));    if( pWindow )        return pWindow->MsgProc(hWnd, uMsg, wParam, lParam);    return DefWindowProc(hWnd, uMsg, wParam, lParam);} 

the upside to this method is its simplicity. the downside is that it misses a few messages which get passed in before the WM_NCCREATE message is passed. also, it only works well for Window classes that have been registered by the app. wrapping dialogs, for instance, requires a different method to set up the object/window association.
btw, the above method is typical of how to associate a wrapper class object with a C library''s callback functions, which is all a window message processing function is in the end. most callbacks take in an arbitrary (void*) 32bit value which makes it perfect for this pointer storage/retrieval.

This topic is closed to new replies.

Advertisement