Date: | July 26, 2005 / year-entry #203 |
Tags: | code |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20050726-00/?p=34803 |
Comments: | 16 |
Summary: | There are two window messages closely-associated with window destruction, the WM_DESTROY message and the WM_NCDESTROY message. What's the difference? The difference is that the WM_DESTROY message is sent at the start of the window destruction sequence, whereas the WM_NCDESTROY message is sent at the end. This is an important distinction when you have child windows.... |
There are two window messages closely-associated with window
destruction,
the
The difference is that
the hwnd = parent, uMsg = WM_DESTROY hwnd = child, uMsg = WM_DESTROY hwnd = child, uMsg = WM_NCDESTROY hwnd = parent, uMsg = WM_NCDESTROY
Notice that the parent receives the
Having two destruction messages, one sent top-down and the other
bottom-up, means that you can perform clean-up appropriate to
a particular model when handling the corresponding message.
If there is something that must be cleaned up top-down, then you can
use the
The
These two destruction messages are paired with the analogous
What's this "absence of weirdness" I keep alluding to? We'll look at that next time. [Typos corrected, 9:30am] |
Comments (16)
Comments are closed. |
Hi!
Does anybody (not the autor of the blog, this is not a .NET-blog), know how this is best mapped to .NET? What is the OnLoad-event, and how can I get the other three?
Just a couple of clean-up points:
"and it receives the WM_NCDESTROY come after they have been destroyed." could do with making sense. Maybe "and it receives the WM_NCDESTROY [message] after they have been destroyed."
Also your link to the scratch program has an additional quote at the end of the href, thus making the link fail without some editing.
How far do the WM_NCDESTROY and WM_NCCREATE messages date back? Windows 1.0?
Yes, obviously WM_NCCREATE is the first message sent to a window. Nothing else would make sense, would it?
Try setting a breakpoint on an window function and see what is really the first message sent to a window. It may surprise you…
I had a home-brew framework that would get an assertion-failure if a window proc received any message before the WM_NCCREATE. Turns out that top-level windows often receive a WM_GETMINMAXSIZE first. It’s annoying since you can’t respond rationally to the message before you’re initialized. I wonder if this is one of the weirdnesses Raymond will talk about.
No Child?
NC is probably non-client…
I also find the mention of NC_CREATE misleading, since AFAIK getminmaxinfo is always the first message ever sent to any ("frame"/non-child) window. For a (C++) framework I have worked on, testing has proved (to me) that it’s the only realiable message to depend on to create a C++ object and attach it to the frame window HWND being created (at least if you, like in my case, from then on use that C++ object to handle all messages to that window).
This under-documentation (to put it mildly) of the order of messages during creation I consider a quite serious flaw. Either you (as a developer) have to know about many of these undocumented behaviours by experience or just trial-and-error, or be prepared to create backing objects for windows no matter what message is recieved.
NC == non-client for the WM_NCPAINT message, so I would assume that NC == non-client here also.
Could be wrong, though.
Christian — you might be able to disassemble the System.Windows.Forms.dll assembly and find out which functions the various messages correspond to (though this may not be allowed by the framework’s license, I’m not sure). I’d think that System.Windows.Forms.Form.WndProc would be the logical place to start, if you want to do this.
I’d look at the MSIL opcodes using ildasm.exe (part of vs.net), not the raw x86 assembly. Or maybe Rotor would be helpful (I’m not entirely sure what Rotor even is, but I’ve heard mention of it relative to decompiling / disassembling before).
I remember there was some windows spy program that would send WM_GETICON (or maybe WM_SETICON) before the WM_NCCREATE message got to your wndproc and it would cause problems on certain programs.
The MSDN docs for MFC CWnd::CreateEx say:
"When CreateEx executes, Windows sends the WM_GETMINMAXINFO, WM_NCCREATE, WM_NCCALCSIZE, and WM_CREATE messages to the window."
and for the Win32 CreateWindowEx (which is called by the CWnd version):
"The CreateWindowEx function sends WM_NCCREATE, WM_NCCALCSIZE, and WM_CREATE messages to the window being created."
Another oddity is that MSDN says WM_SIZE and WM_MOVE aren’t sent if you don’t pass WM_WINDOWPOSCHANGED on to DefWindowProc, but you’ll still get one of each during creation. (at least on Windows 2000…)
One thing I learned the hard way while creating a menu-like widget was that while in WM_DESTROY all the children still exist, owned windows have already been destroyed. In order words, all the WM_POPUP that look like "children" (but actually, owned) by a window are destroyed before WM_DESTROY gets sent to that window.
Remember the order in which windows are destroyed.
WM_DESTROY 和 WM_NCDESTROY 消息之间有什么区别?