CreateWindow never returning

CreateWindow never returning

Post by news » Wed, 11 Oct 2006 19:46:15


According to the docs, if an application returns -1 from WM_CREATE the
CreateWindow function returns a NULL. However I'm finding that if I
return -1 from WM_CREATE the CreateWindow function never returns at
all, and I have to forcibly end the task! What might be happening
here?

Richard.
http://www.yqcomputer.com/
To reply by email change 'news' to my forename.
 
 
 

CreateWindow never returning

Post by news » Thu, 12 Oct 2006 22:15:48

Can somebody explain this please? The program listed below (which
returns -1 from WM_CREATE) never *displays* the "CreateWindow returned
NULL" message box but does make the associated warning sound! The
other message boxes are displayed correctly, and the "CreateWindow
returned NULL" box is correctly displayed if the program is modified to
return zero from WM_NCCREATE. What is going on here to stop the
message box appearing? The program was compiled using gcc 3.2.3 in
case that's relevant.

Richard.
http://www.yqcomputer.com/
To reply by email change 'news' to my forename.

#include <windows.h>

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM
lParam)
{
switch(iMsg)
{
case WM_CREATE :
MessageBox(NULL, "About to return -1 from WM_CREATE", 0, 0);
return -1;

case WM_DESTROY :
PostQuitMessage(0);
return 0;

case WM_NCCREATE :
MessageBox(NULL, "WM_NCCREATE invoked", 0, 0);
return 1;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
MSG msg;
HWND hwnd;
WNDCLASSEX wndclass;

wndclass.cbSize = sizeof(wndclass);
wndclass.style = 0;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = NULL;
wndclass.hCursor = NULL;
wndclass.hbrBackground =
CreateSolidBrush(GetSysColor(COLOR_WINDOW));
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = "Debug";
wndclass.hIconSm = NULL;

RegisterClassEx(&wndclass);

MessageBox(NULL, "About to call CreateWindow", 0, 0);

hwnd = CreateWindow("Debug", "Test", WS_OVERLAPPEDWINDOW,
0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);

if (hwnd == NULL)
{
MessageBox(NULL, "CreateWindow returned NULL", 0, 0);
return 1;
}

ShowWindow(hwnd, SW_SHOW);

while(GetMessage(&msg, NULL, 0, 0) != FALSE )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return 0;
}

 
 
 

CreateWindow never returning

Post by William De » Fri, 13 Oct 2006 00:21:42


I can't.


Good question. I have good news and bad news.

The good news is that I pasted the the text of your application directly
from your post in VS 2003 and ran it on this XP/Pro/SP2 box. I saw three
messages boxes.

The bad news is that I saw three message boxes. :-)

Just by the way, I use the "classic" UI.

I can't for the life of me figure out how the compiler could make a
difference with such plain vanilla code (though the linker might). To
eliminate the toolset as a possible culprit, you can download the freebie
from MS

http://www.yqcomputer.com/

For the heck of it, I'd recast your WM_CREATE handler

case WM_CREATE :
ReplyMessage(-1);
MessageBox(NULL, "About to return -1 from WM_CREATE", 0, 0);
return -1;

Regards,
Will
 
 
 

CreateWindow never returning

Post by news » Fri, 13 Oct 2006 00:34:29


If it worked properly you should have seen four message boxes:

"About to call CreateWindow"
"WM_NCCREATE invoked"
"About to return -1 from WM_CREATE"
"CreateWindow returned NULL"

Which one didn't you see? In my case I don't see the last.


It made no difference.

Richard.
http://www.yqcomputer.com/
To reply by email change 'news' to my forename.
 
 
 

CreateWindow never returning

Post by William De » Fri, 13 Oct 2006 00:40:07


Mea culpa, mea culpa, mea culpa. I apologize for not being able to count.
You have _four_ message boxes not three. The one I didn't see is the one
that you don't see.

That said, the good news is that the behavior is now EASY to explain. Remove
the call to PostQuitMesssage() and you will see the message box.

Regards,
Will
 
 
 

CreateWindow never returning

Post by news » Fri, 13 Oct 2006 01:18:17


Thanks for that, but you will need to explain it to this mere mortal in
a little more detail. Why is PostQuitMessage having that effect (I
assumed nothing would happen until GetMessage reads the WM_QUIT)? What
should I have in my WM_DESTROY handler?

What I am trying to achieve is the ability to abort the window creation
if a memory allocation in WM_CREATE fails. I want the calling thread
to continue running normally in that event.

Richard.
http://www.yqcomputer.com/
To reply by email change 'news' to my forename.
 
 
 

CreateWindow never returning

Post by news » Fri, 13 Oct 2006 03:32:25


Trying to answer my own question, is it because the queued WM_QUIT is
affecting the message box's 'private' message loop? The observed
effect would be explained if the message box was quitting immediately
without displaying its window or waiting for user confirmation.

My current plan is to move some of my code into WM_NCCREATE, because it
would appear that returning zero from that causes CreateWindow to abort
*without* executing the code in WM_DESTROY. I'd be more confident if I
could find that explicitly stated in the docs though.

Richard.
http://www.yqcomputer.com/
To reply by email change 'news' to my forename.
 
 
 

CreateWindow never returning

Post by William De » Fri, 13 Oct 2006 08:52:36


:-)


The WM_QUIT message is used as a way to signal to Windows that you don't
need the UI anymore. On receipt of one, GetMessage() returns 0 which causes
most apps to end their message pumps (they should also exit on -1 btw, but
almost none does).


The clean up code that you need to execute when your window is torn down
should be there. For windowed applications with a single main window it is
customary to put a PostQuitMessage() in the WM_DESTROY handle because the
lifetime of the main window and the lifetime of the application coincide.


Then you should be able to just let DefWindowProc() handle the job.

Save the call to PostQuitMessage() for the spot in your application where
you terminate - perhaps in response to the user clicking File->Exit.

Regards,
Will
 
 
 

CreateWindow never returning

Post by William De » Fri, 13 Oct 2006 09:02:45


Yup. MessageBox() is just a modal dialog displayed by the window manager. At
the heart of nearly every modal dialog is code logically similar to this

while ( GetMessage(...) )
{
TranslateMessage(...);
DispatchMessage(...);
}


You may want to look a look at this:

http://www.yqcomputer.com/

wherein Raymond goes into a little detail on what PostQuitMessage() does.

Regards,
Will
 
 
 

CreateWindow never returning

Post by Alexander » Fri, 13 Oct 2006 14:11:09

ReplyMessage is only useful for cross-thread SendMessage. WM_CREATE is sent
from the same thread.
 
 
 

CreateWindow never returning

Post by news » Fri, 13 Oct 2006 17:16:15


It seems to me that one needs to be very careful if returning from
WM_CREATE with -1. The 'natural' use of this return (certainly the way
I was trying to use it) is to abort the window creation if something
fails during initialisation: in my case it was a failed memory
allocation. However since returning -1 from WM_CREATE causes the code
in WM_DESTROY to be executed, and since that should contain the 'clean
up' code as you say, you'll very likely find yourself trying to 'clean
up' something that has never been dirtied!

This explains why, in my main application, the consequence of returning
-1 from WM_CREATE was more serious than just failing to display a
message box: the entire application froze. I can see now that this was
because of code in WM_DESTROY waiting for a worker thread - that had
never been created - to terminate!

I know it's easy to ctiticise the documentation, but really I think the
comment under WM_CREATE that "the window is destroyed" should more
explicitly state that the code in WM_DESTROY is executed.

I'll continue to use the technique of moving some of my initialisation
into WM_NCCREATE, from which it appears I can return zero without any
problems. That's easier than modifying WM_DESTROY to test that various
elements of WM_CREATE have completed successfully.

Richard.
http://www.yqcomputer.com/
To reply by email change 'news' to my forename.