Why does CreateWindowW fail?

Started by
27 comments, last by MarkS_ 11 years, 6 months ago
Probably irrelevant, but you are passing messages to DefWindowProc() only if they are not in the switch statement, and returning 0 for all messages in the switch statement. This requires that you check that 0 is the expected return value for each and every message you handle in the switch statement. Instead, forget about "default:", and have the function return the value returned from DefWindowProc(), and explicitly return 0 or whatever is appropriate for messages which you process and which you don't want DefWindowProc() to process. So you get this:


switch( Msg )
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(&ps);
this->OnPaint( hdc );
EndPaint(&ps);
}
return 0; // We've already handled it and we don't want to pass it to DefWindowProc().

case WM_SIZE:
// Here lies code which we want to execute whenever the window is resized,
// but we still want DefWindowProc() to handle the message, so we break.
this->OnSize();
break;
}

return DefWindowProc();


Of course, you could still replace your "break;" statements with a "return DefWindowProc(...);" statement, but that seems counter-intuitive to me.

There is an somewhat old article which discusses coupling a C++ object with a native window handle (HWND) here. It's one of the better ways to do it. The finished code is in what he calls the AngelCode Tool Box, and the files most relevant to this discussion are acWindow.h and acWindow.cpp which you can find here.

Notice that WM_NCDESTROY is guaranteed to be the last message that a window will receive from the system, WM_NCCREATE is not the first message it will receive. I think the first message received by a window's message processor is WM_NCCALCSIZE, but I don't think it says so in the docs, so it can change, so good code will not depend on that piece of information. The article I linked above talks about how to do it by setting a hook procedure that gets called whenever a window is created, creating the window (and consequently the hook procedure that will do the coupling), then removing the hook procedure.

Good luck.
Advertisement
Thanks Arm0. I did already get my Window class working though, but this is good information and thanks for the links!

My problem now is explained on the last post of page 1... SetWindowTextW/A will not work... they don't do anything. And it's driving me crazy! :P
_______________________________________________________________________________
CEO & Lead Developer at ATCWARE™
"Project X-1"; a 100% managed, platform-agnostic game & simulation engine

Please visit our new forums and help us test them and break the ice!
___________________________________________________________________________________
SetWindowText will fail if:
* The supplied window handle is invalid. Maybe you're passing the wrong handle somehow. Check which window you are passing by retrieving the window text and displaying it in, say, the debug output window (see OutputDebugString()).
* The WM_SETTEXT message is not being passed to DefWindowProc(), which will do what is necessary to change the window's text.
@ Arm0: No, my handle is valid. I will re-describe the problem:

Does anyone know why SetWindowText W/A does not work? No matter what I do or what variation of parameters and such I try nothing happens...

HWND hWnd;

//! All of these get same, valid HWND handle
hWnd = GetActiveWindow();
hWnd = FindWindow( null, WINDOW_TITLE );
hWnd = FindWindow( WND_CLASS_NAME, null );
hWnd = FindWindow( WND_CLASS_NAME, WINDOW_TITLE );
hWnd = pWindow->hWnd; // << made public for testing
SetWindowTextW( hWnd, L"TESTING 123" ); // nothing happens...
SetWindowTextA( hWnd, "TESTING 123" ); // nothing happens...


I've confirmed my HWND handle is valid. Using it I can call other Win32 functions and easily move around or resize the window or do any number of other things. And as I show above, I've tested my Window class internal HWND against GetActiveWindow and FindWindow to make sure I've got the right handle and yes, they return an identical handle. So the the HWND IS valid.
Calling the SetWindowText function returns a value of true/1 for success, and the Window recieves the WM_SETTEXT message which I can intercept and update my Window's "title" field, like so:

[source lang="cpp"] case WM_SETTEXT:
this->title = wstring( reinterpret_cast<WCHAR_STR>(lParam) );
break;[/source]


...I've run in debug mode and the text I get on the WM_SETTEXT message matches the text I use in SetWindowText calls, demonstrating that everything about this seems to be working correctly except for one incredibly annoying fact: nothing happens and the text in the caption/title bar remains untouched! *double facepalm*
What the hell is going on here? This is serious frustrating... sleep.png

Thanks,

--ATC--
_______________________________________________________________________________
CEO & Lead Developer at ATCWARE™
"Project X-1"; a 100% managed, platform-agnostic game & simulation engine

Please visit our new forums and help us test them and break the ice!
___________________________________________________________________________________
Try replacing the message processor code in your window class with

LRESULT MsgProc( UINT Msg, WPARAM wParam, LPARAM lParam ) { return DefWindowProc( this->hWnd, Msg, wParam, lParam ); }
Hmmm, that did it... WTF lol...

Is it acceptable to just redefine my WndProc like so:

[source lang="cpp"]
LRESULT Window::WndProc( UInt32 msg, WPARAM wParam, LPARAM lParam ) {

HDC hDC;
PAINTSTRUCT paintStruct;

switch( msg )
{
case WM_PAINT:
hDC = BeginPaint( this->hWnd, &paintStruct );
EndPaint( this->hWnd, &paintStruct );
break;

case WM_SIZE:
this->width = (Int32)LOWORD(lParam);
this->height = (Int32)HIWORD(lParam);
break;

case WM_SETTEXT:
this->title = wstring( reinterpret_cast<WCHAR_STR>(lParam) );
break;

case WM_DESTROY:
PostQuitMessage( 0x00 );
break;
}

return DefWindowProc( this->hWnd, msg, wParam, lParam );
}
[/source]

???

Now my text is changing correctly, but I just want to be sure that structuring my WndProc method like this is ok and isn't going to cause any problems for my class. The original version was returning 0x00 instead of the result of DefWindowProc.

EDIT:

I assume that if I do it this way and I want to block Windows from getting a message then I can replace a break with a return.
_______________________________________________________________________________
CEO & Lead Developer at ATCWARE™
"Project X-1"; a 100% managed, platform-agnostic game & simulation engine

Please visit our new forums and help us test them and break the ice!
___________________________________________________________________________________
That's what I spoke about in my first post. Always return DefWindowProc() for all messages, even the ones you process, except in the case where you know that you do NOT want DefWindowProc() to process the message, and that the value you are returning instead is meaningful to the system. DefWindowProc() does A LOT of things, and the less you interfere with it (the less messages you keep from it), the less problems you are likely to have. So yes, that structure of the message procedure is the natural one.
I assume that if I do it this way and I want to block Windows from getting a message then I can replace a break with a return.[/quote]
Yep, but again, see the documentation for the message in question to know what to return.

That's what I spoke about in my first post. Always return DefWindowProc() for all messages, even the ones you process, except in the case where you know that you do NOT want DefWindowProc() to process the message, and that the value you are returning instead is meaningful to the system. DefWindowProc() does A LOT of things, and the less you interfere with it (the less messages you keep from it), the less problems you are likely to have. So yes, that structure of the message procedure is the natural one.
I assume that if I do it this way and I want to block Windows from getting a message then I can replace a break with a return.

Yep, but again, see the documentation for the message in question to know what to return.
[/quote]

Gotcha! Thanks a lot! :-)

I've got a nice general purpose Window class coming together now... now working on wiring up some events and such. When it's done I won't feel so bummed out every time I start a new Win32 or native DirectX project (from having to do all this crap over again). :P

Thanks again,

--ATC--
_______________________________________________________________________________
CEO & Lead Developer at ATCWARE™
"Project X-1"; a 100% managed, platform-agnostic game & simulation engine

Please visit our new forums and help us test them and break the ice!
___________________________________________________________________________________
CRAP! I cannot believe I missed that! You don't need to process WM_CREATE or WM_PAINT or most of the other messages, but you do need to return DefWindowProc().sleep.png

This topic is closed to new replies.

Advertisement