Purpose of WM_CREATE message? - c++

What's the point of having the WM_CREATE message when you can create windows without it.
Calling void CreateWindowA outside of WM_CREATE works so what's the deal?

WM_CREATE message is received by window procedure when window is created and not shown yet. You can prepare initial state. For example, you can create controls (child windows), set default values for controls, etc. If something is wrong, you can cancel creation of window and it will not be shown. In other words, in WM_CREATE you can add custom extension to CreateWindow API.

There are many reasons why an application could want/need to intercept the WM_CREATE message. For example, you may want to check a for a particular condition, and prevent the actual creation if that condition is wrong: you can do this by returning -1 from the WndProc that handles the message (see the documentation):
If an application processes this message, it should return zero to
continue creation of the window. If the application returns –1, the
window is destroyed and the CreateWindowEx or CreateWindow function
returns a NULL handle.

What's the point of having the WM_CREATE message when you can create
windows without it.
If you don't handle WM_CREATE message explicitly, it is actually handled by system via DefWindowProc(hwnd, uMsg, wParam, lParam); implicitly. So you see the window visible.
WM_CREATE message is sent before the CreateWindowEx or CreateWindow function returns, that give you an opportunity to intervene the result of mentioned function. You can allow (return zero to continue creation of the window) or prevent (returns –1, the window is destroyed) the window to be visible, and how it will looks like.
The WM_NCCREATE and WM_CREATE message are sent before the window
becomes visible. That makes them a good place to initialize your
UI—for example, to determine the initial layout of the window.
Refer to "Managing Application State", "WM_CREATE message".

Related

WM_SETFOCUS message and NULL wParam

I've a simple Win32 Windows app with a single, main window. Inside the window procedure I'd like to investigate a WM_SETFOCUS message. The doc says:
A handle to the window that has lost the keyboard focus. This
parameter can be NULL.
This is my case - I'm getting just NULL. What does it mean and why dont I get a handle to for e.g the desktop when the desktop was a previos top, active window?
32-bit Windows introduced an asynchronous input model. One consequence of this change is that the focus window is now recorded per thread (or input-attached group of threads).
Initially, a thread attached to an input queue doesn't have a focus window, so the first time a program sees a WM_SETFOCUS message, its wParam is NULL. There are other reasons why WM_SETFOCUS can have NULL as its parameter, but those aren't interesting here.
Bonus reading:
Eventually, nothing is special any more

How to use a handle as a function parameter?

I was writing code for a win32 application when I came across a problem, how to use a handle as a function parameter. For instance whit this function:
void refreshWindow (HWND myWNDhandle)
{
InvalidateRect(myWNDhandle, NULL, FALSE);
}
If I would pass in "hwnd" as the parameter and run the code, like this:
refreshWindow (hwnd);
I would assume my window will be painted again, unfortunately my window won't.
What did i do wrong?
Mechanically your call is perfect. So either the HWND itself is invalid and, as other commenters suggest, you should assert on IsWindow() to validate that, or you are falling victim to the asynchronous nature of window repainting:
Calling InvalidateRect will merely mark the window as in need of painting, and a subsequent call to GetMessage will generate a paint message to paint the window if there are no other higher priority events or messages to process.
Typically then, methods that want to refresh the contents of a window immediately, follow the call to InvalidateRect with a call to UpdateWindow - which will ensure the window is repainted before returning.

WM_CREATE doesn't seem to be processed in child window

I have a window HWND assignWnd that is a child window of the main window. This window doesn't seem to process the WM_CREATE message. For example, here is the WM_CREATE message within my window procedure.
case WM_CREATE:
{
hdc = GetDC(assignWnd);
GetTextMetrics(assignWnd,&tm);
cyChar = tm.tmHeight + tm.tmExternalLeading;
ReleaseDC(assignWnd,hdc);
return 0;
}
The variable cyChar is an int and is declared within the window procedure. It is used later in the WM_PAINT message. Whenever I compile the program, I get a run-time error stating that cyChar is being used before it initialized. If I place the above code within the WM_PAINT message however, the program works as expected.
The obvious problem is that I don't want these calls to be made every time the window is painted. I would like these commands (and others later on) to be processed during the WM_CREATE message.
Any explanation as to why the WM_CREATE message is not being processed in this child window be greatly appreciated.
Presumably cyChar is local to the window procedure. It's not a question of WM_CREATE not being processed, it's that the cyChar you assign in WM_CREATE is not the same cyChar that you use in WM_PAINT. You need to make your variable global or static so that it survives from one call to the window procedure to another.

The difference between the handle received in the WNDPROC window callback procedure vs the one returned by CreateWindow?

So i was wondering if there is any difference between the handle returned when creating the window using CreateWindow/CreateWindowEx, and the one that is passed as a parameter to the WNDPROC window callback procedure for the concerned window. The context for this question is that I need to use certain API functions that require a handle to the window, so I thought that instead of passing the handle received by the window callback procedures, I could just save a copy of the handle returned by CreateWindow once, and then use it for successive operations, in case both handles are the same.
Regards,
Devjeet
Be careful here, the window procedure is used by multiple instances of a window. The callback is determined by the value of WNDCLASSEX.lpfnWndProc so any CreateWindow/Ex() call that uses the same window class name uses the same callback. If you are doing this to map the callback to a class instance method then you first have to go through a thunk that maps the callback's hwnd argument to a class instance. Making a special case for WM_CREATE of course.
Yes they are the same, that's the whole point of having an HWND. Every window has only one HWND that identifies it within the system and remains valid until DestroyWindow is called with it. It is returned by CreateWindow(EX) and sent in with every message so you can use that as a unique identifier for your window, even if you create several windows of the same class.
But note that some messages are sent to the window procedure even before the CreateFunction returns, so if you use a global variable to hold your HWND:
HWND globalHwnd = NULL;
int main()
{
//...
globalHwnd = CreateWindow(...);
}
LRESULT WndProc(HWND hWnd, ...)
{
assert(hWnd == globalHwnd); //fail!
}
The assertion will fail because several messages such as WM_CREATE are sent before CreateWindow returns, so the global variable is not yet assigned.

What is the difference between WM_QUIT, WM_CLOSE, and WM_DESTROY in a windows program?

I was wondering what the difference between the WM_QUIT, WM_CLOSE, and WM_DESTROY messages in a windows program, essentially: when are they sent, and do they have any automatic effects besides what's defined by the program?
They are totally different.
WM_CLOSE is sent to the window when it is being closed - when its "X" button is clicked, or "Close" is chosen from the window's menu, or Alt-F4 is pressed while the window has focus, etc. If you catch this message, this is your decision how to treat it - ignore it, or really close the window. By default, WM_CLOSE passed to DefWindowProc() causes the window to be destroyed.
WM_DESTROY is sent to the window when it starts to be destroyed. In this stage, in opposition to WM_CLOSE, you cannot stop the process, you can only make any necessary cleanup. When you catch WM_DESTROY, none of its child windows have been destroyed yet.
WM_NCDESTROY is sent to the window when it is finishing being destroyed. All of its child windows have been destroyed by this time.
WM_QUIT is not related to any window (the hwnd got from GetMessage() is NULL, and no window procedure is called). This message indicates that the message loop should be stopped and the application should exit. When GetMessage() reads WM_QUIT, it returns 0 to indicate that. Take a look at a typical message loop snippet - the loop is continued while GetMessage() returns non-zero.
WM_QUIT can be sent by the PostQuitMessage() function. This function is usually called when the main window receives WM_DESTROY (see a typical window procedure snippet).
First of all, the WM_CLOSE and WM_DESTROY messages are associated with particular windows whereas the WM_QUIT message is applicable to the whole application (well thread) and the message is never received through a window procedure (WndProc routine), but only through the GetMessage or PeekMessage functions.
In your WndProc routine the DefWindowProc function takes care of the default behavoir of these messages. The WM_CLOSE messages requests that the application should close and the default behavoir for this is to call the DestroyWindow function. Its when this DestroyWindow function is called that the WM_DESTROY message is sent. Notice that the WM_CLOSE is only a message requesting that you close (like WM_QUIT) - you don't actually have to exit/quit. But the WM_DESTROY message tells you that your window IS being closed and destroyed so you must cleanup any resources, handles etc.
Just so it doesn't get lost in the comments... don't forget about WM_CANCEL. When you click the close (x) button on an MFC dialog, it will certainly send WM_CLOSE. The default OnClose() function will then call the default (base class) OnCancel() function.
However, if you simply type the ESC key, this will lead to the closure of the dialog, but (as far as I can tell) without generating the WM_CLOSE event - it goes directly to the WM_CANCEL/OnCancel() mechanism.
I hereby invite the community to elaborate on this... or edit that elaboration into the accepted answer.
At first let's discuss WM_QUIT - the difference from another messages that this is not associated with window. It is used by application. For example this can be handled by non-visible standalone OLE server (.exe, but not in-proc as .dll)
WM_CLOSE - per msdn: "An application can prompt the user for confirmation, prior to destroying a window" - it is used as notification about intention to close (you can reject this intention).
WM_DESTROY - is a fact that window is closing and all resources must(!) be deallocated.
I know this is old, but just trying to provide a clearer answer for anyone.
// What causes each message?
WM_CLOSE: // Pressed Close Button (X) / Alt+F4 / "Close" in context menu
WM_DESTROY: // Called DestroyWindow(hwnd)
WM_QUIT: // Called PostQuitMessage(exit)
// What do they do by default?
case WM_CLOSE: DestroyWindow(hwnd); return 0; // pressed close? destroy window.
case WM_DESTROY: PostQuitMessage(0); return 0; // destroyed window? quit message loop.
// WM_QUIT isn't associated with a window, so isn't sent to the window procedure
So WM_CLOSE is just so we can request to destroy the window. However you might want it to show a popup in your game asking if you're sure. (and if you want to save first)
And WM_DESTROY doesn't actually post the quit message by default, since you could have multiple windows. That's just the usual event we quit after. You could have WM_CLOSE call PostQuitMessage(exit) and destroy your window(s) after the message loop if you wanted.
If you wanted a custom close button in your game, it should do what WM_CLOSE does.
Also there is the function CloseWindow(hwnd), however it simply minimizes the window.
Hope this helps anyone.