Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

PostQuitMessage(0) seems not to work in case WM_DESTROY:

1,104 views
Skip to first unread message

Frank Fiedler

unread,
Sep 1, 2003, 6:13:04 PM9/1/03
to
Hello,

I have problems to close my simple win32 app in a correct way.
I wrote a callback function and called PostQuitMessage(0) to send WM_QUIT to
my event loop, as you can see below.
The window disappaers, but the event loop doesn´t receive the WM_QUIT
message, so the thread will not exit and I have to close it with the task
manager.

When I close the app by a button press, everything works fine.
In both cases, the Message boxes appear, so the code is reached.

What happens here? Maybe its a problem on my computer only, a win
configuration problem or something? Same thing on my laptop, too.

thanks for your help.
regards,

Frank


LRESULT CALLBACK WindowProc(HWND hwnd, UINT uiMessage, WPARAM wParam, LPARAM
LParam)
{
switch (uiMessage)
{
case WM_DESTROY:
{
MessageBox(hwnd, "WM_DESTROY" , "" ,MB_OK);
PostQuitMessage(0); // does not send WM_QUIT to message loop!
return 0;
} break;
case WM_LBUTTONDOWN:
{
MessageBox(hwnd, "Button pressed", "", MB_OK);
PostQuitMessage(0); // works fine
return 0;
}
default:break;
} // switch
return DefWindowProc(hwnd, uiMessage, wParam, LParam);
} // Windowproc

Tim Robinson

unread,
Sep 1, 2003, 7:19:34 PM9/1/03
to
PostQuitMessage generally works, even inside WM_DESTROY handling. Maybe
there's a problem with your message loop -- you should post that, too.

--
Tim Robinson (MVP, Windows SDK)
http://www.themobius.co.uk/

"Frank Fiedler" <fiedle...@web.de> wrote in message
news:fdaf4ca5.03090...@posting.google.com...

Frank Fiedler

unread,
Sep 2, 2003, 2:57:58 AM9/2/03
to
"Tim Robinson" <tim.at.gaat.f...@invalid.com> wrote in message news:<bj0k7r$djnra$1...@ID-103400.news.uni-berlin.de>...

> PostQuitMessage generally works, even inside WM_DESTROY handling. Maybe
> there's a problem with your message loop -- you should post that, too.
>
> --
> Tim Robinson (MVP, Windows SDK)
> http://www.themobius.co.uk/
>

Well, here is my message loop. As I mentioned it愀 working fine if the
WM_QUIT is send from "case WM_LBUTTONDOWN:" (in the callback
function).

MSG message;
while (true)
{
GetMessage(&message, hwnd, 0, 0);
if (message.message == WM_QUIT)
{
MessageBox(hwnd,"WM_QUIT received","",MB_OK);
break;
}
TranslateMessage(&message);
DispatchMessage(&message);
}

And here is again the callback function:

Elias Fotinis

unread,
Sep 2, 2003, 6:08:17 AM9/2/03
to
Frank Fiedler wrote:
> MSG message;
> while (true)
> {
> GetMessage(&message, hwnd, 0, 0);
> if (message.message == WM_QUIT)
> {
> MessageBox(hwnd,"WM_QUIT received","",MB_OK);
> break;
> }
> TranslateMessage(&message);
> DispatchMessage(&message);
> }

GetMessage never returns WM_QUIT. When it finds such a msg in the queue,
it simply returns FALSE. Use something like this:

MSG msg;
while (GetMessage(...)) {
...
}

MessageBox(..., "WM_QUIT", ...);

Note that GetMessage can also return -1 if there's an error, so a better
approach would be:

MSG msg;
int ret;
while ((ret = GetMessage(...)) > 0) {
...
}

if (ret == 0)
MessageBox(..., "WM_QUIT", ...);
else
MessageBox(..., "GetMessage failed", ...);


Patrick Philippot

unread,
Sep 2, 2003, 7:07:43 AM9/2/03
to
Elias Fotinis wrote:
> GetMessage never returns WM_QUIT. When it finds such a msg in the
> queue, it simply returns FALSE.

This is what I first thought, guessing that msg.message would be
undefined but I did some tests and actually, it does. You do get 0x0012
in msg.message when a WM_QUIT message arrives (I tested on Win2K and
Win98 SE). So this very strange way of implementing the message loop
actually works (at least on these two versions of Windows).

But you're correct, I would not implement the message loop like Frank
does.

--
Patrick Philippot - Microsoft MVP [.Net]
MainSoft Consulting Services
www.mainsoft.xx
(replace .xx with .fr when replying by e-mail)


Frank Fiedler

unread,
Sep 2, 2003, 7:15:25 AM9/2/03
to
"Tim Robinson" <tim.at.gaat.f...@invalid.com> wrote in message news:<bj0k7r$djnra$1...@ID-103400.news.uni-berlin.de>...
> PostQuitMessage generally works, even inside WM_DESTROY handling. Maybe
> there's a problem with your message loop -- you should post that, too.
>
> --
> Tim Robinson (MVP, Windows SDK)
> http://www.themobius.co.uk/
>

Well, here is my message loop. As I mentioned it愀 working fine if the


WM_QUIT is send from "case WM_LBUTTONDOWN:" (in the callback
function).

MSG message;

while (true)
{
GetMessage(&message, hwnd, 0, 0);
if (message.message == WM_QUIT)
{
MessageBox(hwnd,"WM_QUIT received","",MB_OK);
break;
}
TranslateMessage(&message);
DispatchMessage(&message);
}

And here is again the callback function:

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uiMessage, WPARAM wParam,

Tim Robinson

unread,
Sep 2, 2003, 8:21:48 AM9/2/03
to
"Frank Fiedler" <fiedle...@web.de> wrote in message
news:fdaf4ca5.03090...@posting.google.com...
> Well, here is my message loop. As I mentioned it´s working fine if the

> WM_QUIT is send from "case WM_LBUTTONDOWN:" (in the callback
> function).
>
> MSG message;
> while (true)
> {
> GetMessage(&message, hwnd, 0, 0);
^^^^
Here's your mistake -- use NULL instead. Once the window is destroyed (i.e.
after WM_DESTROY), hwnd is no longer valid. Afterwards, instead of
retrieveing a WM_QUIT message, GetMessage fails (and returns -1).

> if (message.message == WM_QUIT)
> {
> MessageBox(hwnd,"WM_QUIT received","",MB_OK);
> break;
> }
> TranslateMessage(&message);
> DispatchMessage(&message);
> }

A 'nicer' message loop would be:

MSG message;
while (GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}

You should hardly ever need to use the last 3 parameters to GetMessage.

r_z_...@pen_fact.com

unread,
Sep 2, 2003, 10:20:21 AM9/2/03
to
Here are some comments from my source code (sort of confirms earlier
posts):

// Check for > 0, because ::GetMessage can actually return -1 (see
comp....win32)
// But probably only when second argument is not NULL.
// From Paul Yao, windowscedev, 29 Jan 02, "messageloops":
// "Key point is that when a window handle is provided, if the
handle is
// invalid then the call returns -1 and not FALSE. This would
result in
// a race condition. I agree with the docs -- when you pass a
window
// handle in as the second parameter, you have to be careful and
check
// for (-1) as well as NULL return value."


On 1 Sep 2003 23:57:58 -0700, fiedle...@web.de (Frank Fiedler)
wrote:

-----------------------------------------
To reply to me, remove the underscores (_) from my email address (and please indicate which newsgroup and message).

Robert E. Zaret
PenFact, Inc.
500 Harrison Ave., Suite 3R
Boston, MA 02118
www.penfact.com

Elias Fotinis

unread,
Sep 2, 2003, 1:30:37 PM9/2/03
to
Patrick Philippot wrote:
> Elias Fotinis wrote:
>> GetMessage never returns WM_QUIT. When it finds such a msg in the
>> queue, it simply returns FALSE.
>
> This is what I first thought, guessing that msg.message would be
> undefined but I did some tests and actually, it does. You do get
> 0x0012 in msg.message when a WM_QUIT message arrives (I tested on
> Win2K and Win98 SE). So this very strange way of implementing the
> message loop actually works (at least on these two versions of
> Windows).

Ahem... it seems you're right. GetMessage *does* fill the MSG struct
with WM_QUIT (on all platforms); it's just the return value that
differs. This is very well documented. Too bad I've never read the
WM_QUIT help... :o)

Anyway, the OP's problem is probably the hWnd param, as the other
posters indicated.

SteveR

unread,
Sep 2, 2003, 5:39:54 PM9/2/03
to
Elias Fotinis <efoti...@SPAMpat.forthnet.gr> writes:
>Frank Fiedler wrote:
>> MSG message;
>> while (true)
>> {
>> GetMessage(&message, hwnd, 0, 0);
>> if (message.message == WM_QUIT)
>> {
>> MessageBox(hwnd,"WM_QUIT received","",MB_OK);
>> break;
>> }
>> TranslateMessage(&message);
>> DispatchMessage(&message);
>> }
>
>GetMessage never returns WM_QUIT. When it finds such a msg in the queue,
>it simply returns FALSE. Use something like this:
>
> MSG msg;
> while (GetMessage(...)) {
> ...
> }
>
> MessageBox(..., "WM_QUIT", ...);
>
>Note that GetMessage can also return -1 if there's an error, so a better
>approach would be:
>
> MSG msg;
> int ret;
> while ((ret = GetMessage(...)) > 0) {

Don't test > 0 here. The documented return values are:

0: found WM_QUIT
-1: had error
All other values, *including negative != -1*: success.

I've seen it return negative values other than -1 in success cases.

--
SteveR

Frank Fiedler

unread,
Sep 3, 2003, 4:31:23 PM9/3/03
to
Thank you all, this was really helpful.

Frank

Elias Fotinis

unread,
Sep 6, 2003, 6:06:08 PM9/6/03
to
SteveR wrote:

> Elias Fotinis <efoti...@SPAMpat.forthnet.gr> writes:
>> MSG msg;
>> int ret;
>> while ((ret = GetMessage(...)) > 0) {
>
> Don't test > 0 here. The documented return values are:
>
> 0: found WM_QUIT
> -1: had error
> All other values, *including negative != -1*: success.
>
> I've seen it return negative values other than -1 in success cases.

Hmm, you're right... GetMessage() returns *non-zero* for success, so I
guess any negative value (except -1) should be accepted too.

Anyway, I've always hated this BOOL type. Too bad the real 'bool' didn't
exist when Windows was being designed :)

0 new messages