开发者

Window message: Different between WM_CREATE and WM_NCCREATE?

I tried to create button (child window) inside WM_NCCREATE message, and its position seemed to be created respected to screen coordinates, rather than client coordinates. At first, I thought WM_CREATE and 开发者_如何转开发WM_NCCREATE provide us the same handle to window, but this seem to be untrue. Therefore, can anyone explain me the differences between WM_CREATE and WM_NCCREATE messages? Also what are the differences between handle to window in WM_CREATE and in WM_NCCREATE?


WM_NCCREATE is an example of an arms race in progress. It seems to have been introduced to serve a need where DefWindowProc (or the base window proc of a commonly subclassed window) needed to perform some initialization perhaps before WM_CREATE was processed (or to make up for the fact that many window implementations handle WM_CREATE directly and return TRUE rather than passing it on to DefWindowProc).

WM_NCCREATE therefore is the message you should respond to if you are implementing a default window procedure, that needs to perform initialization before the users window proc handles the WM_CREATE message. WM_NCCREATE also MUST be passed on to the appropriate DefWindowProc, probably before you do your own processing as some lower level aspects of the window are clearly in an uninitialized state before WM_NCCREATE is processed.

If trying to guarantee first-look processing is NOT your consideration, then WM_CREATE is the appropriate place to perform your window initialization: All other layers that might have jist-in-time setup via WM_NCCREATE have been done, and the window is in a stable state wrt things like its non client metrics, screen position etc.

Or: If you don't know why you should use WM_NCCREATE over WM_CREATE, then you should not be using WM_NCCREATE.


The WM_NC messages are for the non-client area, i.e. the window border and caption. For your needs you are not interested in these non-client messages.


Per MSDN:

WM_NCCREATE:

Sent prior to the WM_CREATE message when a window is first created.

Return Value:

If an application processes this message, it should return TRUE to continue creation of the window. If the application returns FALSE, the CreateWindow or CreateWindowEx function will return a NULL handle.

WM_CREATE:

Sent when an application requests that a window be created by calling the CreateWindowEx or CreateWindow function. (The message is sent before the function returns.) The window procedure of the new window receives this message after the window is created, but before the window becomes visible.

Return Value:

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.


This device context includes the window title bar, menu, scroll bars, and frame in addition to the client area. Applications programs rarely use the GetWindowDC function. If you want to experiment with it, you should also trap the WM_NCPAINT ("nonclient paint") message, which is the message Windows uses to draw on the nonclient areas of the window.

from:《Programming Windows Fifth Edition》 -Charles Petzold

So I think it's believable, although MSDN didn't say it。


Not sure why you're creating a button in the WM_NCCREATE -- because the window onto which the button will appear doesn't exist yet, hence (I believe) the destop coords. WM_NCCREATE gets sent to you when the 'non-client' areas of the window are about to be created (non-client areas such as the window's border, title bar, etc.)

Are you needing to put a button on the non-client area? If the answer is no, then why not do the button create inside WM_CREATE.

If you have to create the button for some reason inside WM_NCCREATE, then why not store the window handle returned by your Createwindow() call. Then, inside your WM_CREATE message handler, grab that button's window handle and do a 'MoveWindow(...)' on it using the app window which you should now have coordinates to when you're in the WM_CREATE message handler.

I believe one of the parameters you can pass to your CreateWindow(...) call to create the button allows you to specify an 'SW_...' flag, such as 'SW_HIDE' if memory serves me correct. So create but don't show the button in WM_NCCREATE handling if you must, then when WM_CREATE comes quickly afterward, do a 'MoveWindow(....window coords,......SW_SHOW,......) etc. to position and make visible the button.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜