

Sending a window a WM_DESTROY is like prank calling pretending to be the police - mootothemax
http://blogs.msdn.com/b/oldnewthing/archive/2011/09/26/10216420.aspx

======
oozcitak
Then WM_DESTROY should have been called NM_DESTROY, since it is clearly a
notification message not a command. The user is not wholly innocent here, but
the Windows API team should be blamed for the misleading naming as well.

~~~
roel_v
No, because the NM_ messages are for standard controls only. There are more
messages in the WM_ family that aren't really 'command' messages, but more
'notification' messages, like WM_CREATE. It's not like one can create a window
by allocating memory, casting to an HWND and sending WM_CREATE to it.

I guess the conclusion is that one cannot blindly take WM_xxx message and
think 'oh I can use ::SendMessage() and friends to make windows do certain
things'. Only the documented behavior are valid use cases.

I guess one could say that the WM_xxx message should've been split up into
more subclasses, but where to draw the line? I'm quite fine with using WM_xxx
for all the fundamental window manager messages, as long as one minds their
documented behavior there is no problem. (I realize that this last sentence
can spark a whole discussion by itself on how far self-documenting a 'sane'
API should be, but that's rather subjective imo).

~~~
jxcole
I disagree with you and I think the grandparent is right. Even though the
handle based architecture of the wind32 system is not object oriented, it was
meant to have some object oriented features. If you think about this system as
one in which a window handle is a window object and a message to that window
represents a function call, then the WM_CLOSE is a public method that anyone
can call. WM_DESTROY, on the other hand, would be a protected method that can
only be evoked by the window system. Even though they decided that the
overhead of a full OO system was too much, they still could have made the
intention more clear by doing something like this:

WM_PUBLIC_CREATE and WM_PROTECTED_DESTROY

Then there would be no confusion about who was supposed to send the messages
and how they were meant to be interpreted. Of course they don't have to use
this exact terminology, but you get the idea.

~~~
roel_v
"If you think about this system as one in which a window handle is a window
object and a message to that window represents a function call, then the
WM_CLOSE is a public method that anyone can call. WM_DESTROY, on the other
hand, would be a protected method that can only be evoked by the window
system."

Yeah well there's the error in your thinking, and exactly what the OP was
about: window messages aren't that. _Every_ message is a callback, a
'notification' if you will. If you call RegisterClass() and pass a WNDPROC
that does nothing (ignores all messages), it can still be created/destroyed
with CreateWindow()/DestroyWindow(), and the 'notifications' it gets (WM_CLOSE
and WM_DESTROY) can happily be ignored ('happily' as far as the window manager
is concerned).

Win32 is _not_ an OO API, and thinking of it too much in those terms will
cause all sorts of confusion. Win32 is a C api, and yes things like MFC put an
OO wrapper around it, but at some point the abstraction _will_ start to leak
if you take it to the extreme without thinking about the underlying system.
Win32 is based around the OS calling back into your code through a well-
defined callback function (the WNDPROC), a function with a fixed signature,
and taking two arguments that are for all intents and purposes void*'s. The
message ('WM_xxx') is a way to tell you how to interpret its arguments, and
inform you about changes in the life cycle or state of the window. Everything
else (like being able to 'send' messages to HWND's and make them behave in a
certain way) comes from there, and much of it is convention - which often
works, but when it doesn't, it's not the design's 'fault'.

------
raganwald
This is a very good example of the kind of thing I see in all sorts of
frameworks, where someone (often me) is trying to do something that isn’t 100%
plain vanilla, and TheOneTrueRightWayToDoThis isn’t obvious. Our hapless
programmer thinks of something, tries it, it appears to work, and they move
along. Meanwhile, it only appears to work “by coïncidence," and in reality
there is a hidden bug waiting to bite.

The ideal situation is to do more research and really understand how the leaky
abstraction actually works, but there is never enough time in the day and
deadlines in the calendar are closer than they appear...

~~~
fferen
Haha, this happens to me a lot when learning new libraries or frameworks. My
current solution is to just search StackOverflow with what I'm trying to do.
Often, the Right Way is posted as a snippet, but even if there are no directly
pertinent answers, related ones can also give insight on other things I'm
doing wrong.

------
orochimaru
Irrespective of the article and its crux, the analogy is plain weird. Maybe he
had a particular aspect of a prank call in mind, but it's tough to relate to.

------
rbanffy
> This thread creates an invisible window whose job is to do something until
> it is destroyed

Is this a common pattern? Why?

Wouldn't it be simpler to just create a thread or separate process without an
attached window?

------
molo_
Wow, thanks for exposing me to how braindamaged win32 really is.

~~~
mattmanser
I'm sure every operating system has weird quirks like this.

The odd thing about this article is it tries to pretend it's the user's fault.
Which is doubly odd as Raymond Chen's stuff is usually pretty good.

~~~
molo_
This is more than just a quirk. Lets go through the bogons here:

1\. Signal system confuses notifications with commands

2\. API ties windows to threads

3\. System allows you to send WM_DESTROY from one thread to another even
though it provides undefined behavior

4\. DestroyWindow() can only be called from a particular thread (related to
item #2)

5\. The API doesn't detect that the window has been destroyed as far as the
application is concerned (whatever happens in ForgetWorkerThread() or
PostQuitMessage(), the window actually goes away) without a DestroyWindow()
call.

In short, WTF.

[edit: format]

~~~
roel_v
"2. API ties windows to threads"

OK, so what's the alternative? Automatic locking at OS-level? How can the
performance penalty in those many cases where it is not needed be justified?
Same goes for your arguments 3, 4 and 5 btw. Why should such low-level
functionality impose important design decisions on those who follow the
documentation, just to protect the beginners who don't? I much prefer my raw
control, thanks - and I'll happily take the few times I shoot myself in the
foot with it, err, with it.

Despite its warts and its legacy cruft, the win32 is quite flexible, and easy
to understand - at a very basic level, not much studying of under-the-hood
stuff required. For an OS-level API, it packs a lot of power into a small set
of concepts.

~~~
molo_
You argue for more control, but tying windows to threads at the OS layer is
actually enforcing less control.

~~~
chollida1
Just a quick meta response because i see you're new.

You don't need to sign your posts as your user name appears above your post.

~~~
molo_
Hi, thanks but that is what I've been doing for ages.

~~~
molo_
Is it really necessary to downmod me for that?

~~~
chollida1
I think we're way off topic but I'll try to end on a good note by pointing out
that I can't downvote you as you responded to my post.

You'll find the community here is great, but you should try to play by it's
rules:)

~~~
molo_
Sure, that wasn't directed at you personally. Thanks and cheers.

