Message Management

There are two kinds of messages which you, as a programmer, can defined. The
first kind is the compile-time-constant variety. I have found, after years of
experience, These Are Not Your Friend. I'll nonetheless describe them as many
people still prefer them, but as a matter of opinion I avoid them as much as I
can. The second kind are messages which are guaranteed to be unique within a
system. I much prefer these, and use them exclusively.

Older books on Windows programming tell about how to define user-defined
messages using the symbol WM_USER. This technique is obsolete. There were
too many problems with WM_USER-based symbols conflicting with messages
that Microsoft was using. The new method is to use WM_APP as the base. If
you have something that uses WM_USER, the usage is identical to the usage
of messages based on WM_APP. Therefore, I will not reproduce the
discussion here.

If you are comfortable with the idea of compile-time constant messages--and
after you read the next section, you may not be--then you can use definitions
based on the symbol WM_APP, which Microsoft now specifies as the
desirable symbol to use. The correct form of the definition of such a symbol is

#define UWM_MYMESSAGE (WM_APP + n)

where n is some integer, typically a small integer like 1, 2, 3, etc.
This defines a value which identifies the message. While strictly speaking the
parentheses are not mandatory, good programming practice demands their presence.

I prefer a naming convention that does not conflict with the Microsoft naming
convention. For one thing, it makes your code difficult for someone else to read
and understand; for another, it makes it hard for you to read and understand. My
preference is to use a UWM_ prefix (User Window Message); other people
have used WMU_ (Window Message, User), and you can pick any convention
you want, but do not use prefixes that conflict with those already in use
by Microsoft.

Note that there is absolutely no requirement that every user-defined
message be unique. Messages are always interpreted in the context of a
particular window. Thus, you can have messages like

#define UWM_PAINT_VIEW_PURPLE (WM_APP + 7)

#define UWM_RESET_VIEW (WM_APP + 7)

These are perfectly valid providing that the view that accepts the purple
request is never sent a reset request, and vice-versa.

To create an entry in the table to dispatch on these messages, you make an
entry

ON_MESSAGE(UWM_RESET_VIEW, OnReset)

This requires that you define the handler OnReset. In the message
handler part of your .h file, you add the declaration

afx_msg LRESULT OnReset(WPARAM, LPARAM);

When your window class receives the UWM_RESET_VIEW message, it will
call the OnReset handler.

You can't send them between processes reliably. If you accidentally send a
message to a process that has never heard of your message, it could crash.
If you receive a message that you think you understand, you might
crash.

You can't create a DLL that notifies its clients via messages. This is
because you might choose (WM_APP+7) as your desired message, and some
other DLL writer you never heard of might have also chosen (WM_APP+7)
as his or her desired message. The poor programmer who is trying to use both
DLLs is in deep trouble, because of the conflict.

You can't even think of sending one of these messages down through
your window hierarchy by using SendMessageToDescedants, because some
window you never heard of may be using that message. Consider the example in
the previous section where a message to paint the view purple and a message
to reset the view were the same code. If you sent this message to all
descendants of your main frame, some would reset and some would change to
purple, which is not a particularly desired outcome.

The way this is solved is by using a Registered Window Message. This
is a message which is guaranteed to be unique. Only those windows or
processes or DLLs that create it, and those which specifically use it, will
actually have the same message number.

How is this done?

There is a range of messages, 0xC000 through 0xEFFF, which is reserved for
use by registered window messages. When you call the API function ::RegisterWindowMessage
you pass it a string. It looks up the string in an internal table. If it finds
the string, it returns the integer which has been assigned. If it does not find
the string, it creates a new entry in the table, assigns it a new integer value
from the range 0xC000 through 0xEFFF, and returns that integer value. The table
in which these strings are kept is global to all processes on the machine, so if
two completely different programs register the same string, they both get the
same integer. They may now communicate with each other via these messages.

No, you can't "unregister" a message. You don't need to.

So a simple form of the user-defined message would be to declare a variable,
which I usually just make static in each module that uses it:

static const UINT UWM_RESET_VIEW =

::RegisterWindowMessage(_T("UWM_RESET_VIEW"));

I'll tell you later why this still isn't quite adequate, but take it as a
working example for the moment.

The way you handle a registered message is just like you handle a constant
user-defined message. The macro is slightly different, but the rest of the
handling is the same. Add the line to your MESSAGE_MAP:

ON_REGISTERED_MESSAGE(UWM_RESET_VIEW, OnReset)

As with the constant messages, you will need to define the OnReset
handler by adding a declaration to the handler section of your class in the .h
file:

afx_msg LRESULT OnReset(WPARAM, LPARAM);

The handlers for a registered window message and for a constant user-defined
message are absolutely identical. In fact, in the handler, you can't really tell
if the programmer has rewritten the code to use one or the other.

You may have already discovered a problem that is identical for both constant
messages and registered messages. What if you choose a nice, obvious name like
"UWM_RESET_VIEW" as the string name of the message, and some
other programmer has also chosen another nice, obvious, simple name for his or
her DLL, such as "UWM_RESET_VIEW". Have we really made
progress?

No.

But there is a way around it. There is a program which is part of the SDK,
called GUIDGEN. What this program does is create a unique 128-bit binary
value. Each time you create a new Globally Unique IDentifier,
a GUID, you can be sure that it is really, truly, unique. It is not only unique
for you, it is unique for everyone, everywhere, all the time. It incorporates
the time and date, the MAC address from your network card (and if you don't have
a network card, it uses another method, which has something like one chance in 263
of conflicting with another GUID), and a bunch of other information. Therefore,
there is no way, short of explicit collusion between two programmers, that they
will use the same GUID.

Select option 4, "Registry format". Click the "Copy"
button. A copy of the string as shown in the Result box will be placed in the
clipboard. Then go to your editor and type something like

#define UWM_RESET_VIEW_MSG _T("UWM_RESET_VIEW-<paste>")

which creates a name like

_T("UWM_RESET_VIEW-{4E7F6EC0-6ADC-11d3-BC36-006067709674}")

I actually have a macro

#define DECLARE_USER_MESSAGE(name) \

static const UINT name = ::RegisterWindowMessage(name##_MSG);

which handles most of the hassle for me. While strictly speaking my GUID can
suffice for all my messages, I usually just generate a new GUID for each
message.

Any time I want to create an instance of a message, for use in a message
table or for posting, I just do

DECLARE_USER_MESSAGE(UWM_RESET_VIEW)

and, because of my convention of naming the string the same, I get the
variable initialized. Typically these appear in the outer block of each module
that uses the symbols. All I have to make sure is that the header file for DECLARE_USER_MESSAGE
and the header file for the messages I want are both included.

So why do I even bother to put a readable name into the string? The 128-bit
GUID should be sufficient! Well, the truth is that the readable name is totally
redundant and essentially irrelevant. Unless you happen to be using Spy++ to
trace message traffic. In that case, you really, really want to see something you
understand, and 128-bit GUIDs are not really high on the list of easily readable
values. The only reason the readable string is there is for the convenience of
you, the developer. It doesn't matter, otherwise.

User-defined messages are an interface. As an interface, they need to be
defined. I have some macros in my text editor that make this easy. They generate
a standard header for me which I fill in. The header looks something like the
examples below.

Example 1: A message which has simple parameters, and which is sent
but whose response doesn't matter:

Note that I carefully document the casting that is required to get the
desired WPARAM and LPARAM values. Then I know when I'm writing my
method how I should cast it. Here's an example of a handler for another message,
which takes a pointer to an object.

When you pass a pointer as a WPARAM or LPARAM, you need to be
careful about what you pass and how you pass it. The key is in whether you do a SendMessage
or a PostMessage. If you do a SendMessage, you can use a reference
to an object on the stack, an object in static storage, or an object on the
heap. This is because control does not resume in the thread that does the
SendMessage until the handler completes its action. In particular, this means
that any address referencing the stack remains valid during the processing of
the message. This does not apply to cross-process messages! See below!

However, if you ever plan to use PostMessage to pass a pointer to an
object, then you are constrained to always use a static or heap-based
object. The address of a stack-based object is nonsensical in this context. This
is because the function that performs the PostMessage will quite possibly
return long before the message is processed--in fact, if it is posting the
message to the same thread, it must return before the message is
processed. This means that the object reference to the stack is pointing to
valid space, but space that may have been overwritten. If the object on the
stack is a C++ object that has a destructor, the destructor will be called and
objects within the object on the stack might be deallocated. For example, you
cannot use PostMessage in the following context:

{

CString s;

// ... assign a value to s

PostMessage(UWM_LOG_MESSAGE, 0, (LPARAM)&s);

}

Even if the address referenced on the stack is not overwritten by subsequent
calls, the data referenced by the string is deallocated by the CString
destructor. When the handler is called and attempts to reference the string, you
will get some effect between completely incorrect data and an access fault. The
chances of anything working as you expect are incredibly slim.

However, the following code is correct. We first look at the definition:

/***************************************************************

* UWM_LOG_MESSAGE

* Inputs:

* WPARAM: ignored, 0

* LPARAM: (LPARAM)(CString *): String to log

* Result: LRESULT

* Logically void, 0, always

* Effect:

* Logs the message in the debug output window

* Notes:

* The CString object must explicitly deallocated by

* the handler for this message.

* This message is usually sent via PostMessage. If sent

* via SendMessage, the sender must not delete the

* CString, nor should it assume upon return that it has

* not been deleted. The sender must send a pointer to a

* deletable string. To do otherwise is a serious error.

***************************************************************/

Then we can write the handler:

/***************************************************************

* CMainFrame::OnLogMessage

* Inputs:

* WPARAM: ignored, 0

* LPARAM: (LPARAM)(CString *): String to log

* Result: LRESULT

* Logically void, 0, always

* Effect:

* Logs the message in the debug output window

* Notes:

* The CString object must explicitly deallocated by

* the handler for this message

***************************************************************/

(Note that I often replicate the definitions in both places; while it means I
have to update the handler comments if I make changes, since I have to edit the
code anyway it is no serious hazard).

It is often a Bad Idea to send messages across threads. The problems of
potential deadlock are substantial. If you SendMessage to a thread that
is blocked, and that thread is waiting for the sending thread to complete,
you're dead in the water. Your process is blocked, and it will stay blocked, and
you will have to set of sticks of dynamite under it to make it go away.

Note that you can get into this inadvertently. You should never, ever
manipulate a GUI object from a worker thread, or a GUI object owned by a thread
other than the user-interface thread that is sending the message. If you are
getting deadlock, these are key problems to look for.

You are safest, when transferring information across threads, to use PostMessage
to handle it. A cross-thread PostMessage will not block the sender. If
you need a positive acknowledgement, it is often best to restructure your
algorithm to be a two-phase algorithm, where one method posts a message to the
alternate thread, and expects the alternate thread to post a message back
indicating completion. While harder to program, it avoids the deadlock issue.

If you must send across threads, and you need a positive response, and you
have the potential for deadlock, you should use SendMessageTimeout. This
will send the message to the thread, but if the thread does not respond within
the timeout period, the message is completed, and you get control back, with an
error indication. A typical call I use looks like the example below.

Sending a user-defined message across processes is somewhat more complex.
First, you really have to use a Registered Window Message. Using a WM_APP-based
message is somewhere between seriously dangerous and totally insane.

When you send a message across processes, you are implicitly sending it
across threads. All of the caveats about cross-thread messages apply. But even
more, there are other serious restrictions on cross-process messages.

The most significant one is that you cannot send a pointer across process
boundaries. This is because process address spaces are separate, and a pointer
has no meaning when it is received in the other process. For example,

LRESULT CMainFrame::OnLogMessage(WPARAM, LPARAM lParam)

{

CString * s = (CString *)lParam;

if(s[0] == _T('$')) // app crashes hard here

{ /* special message */

// ...

} /* special message */

}

When the operation s[0] is performed, the chances are almost dead
certainty that the application receiving the message will take an access fault.
The chances of the pointer being valid (and if it is, it will point to
meaningless gibberish) are close to zero, and the gibberish pointed to will
certainly not resemble a CString.

You can't even pass a pointer to shared memory, even DLL-shared-segment
shared memory. This is because the shared memory is not guaranteed to be in the
same locations in all processes that share the memory (this is described in
detail in Win32 Programming).
Essentially, figure that you can't pass information across the process boundary
using ordinary messages.

In addition to all of the previous issues, posting messages across processes
have additional hazards. For example, you cannot under any circumstances pass an
address across process boundaries.

This is true even if the address is in a shared memory area, such as shared
DLL data segment or a memory-mapped files. Just because an address is valid in
one process does not guarantee it is valid in a different process. And if you
have evidence that says this is not so, that you've seen that you can pass a
shared memory pointer from one process to another and it is valid, be aware that
the phenomenon you are seeing is transient and accidental. While Win32 makes a
sincere attempt to map shared memory into the same location in each process, it
is important to emphasis that it does not guarantee this. Depending on
this opens you to serious problems with the delivered product, which might not
show up for months. But that's an essay for some other time.

In addition, you can hit nasty deadlock situations, where a SendMessage
does not complete, and hangs forever, or appears to.

Here's a typical example, and we've actually seen this in practice:

My application wants to be the one-and-only-copy running. One of the many
detection mechanisms for this is to search for a window of the same class (which
is a Bad Idea, since the class names are invented by MFC), the same caption
(which is a Bad Idea since the captions may vary depending on which MDI child is
active), etc. One of the better ways is to send a Registered Window Message to
each window and look for a specific response. It used to be easy; it is now
somewhat harder. The naive approach is to do something like shown below. What I
show here is the handler for the EnumWindows call:

BOOL CMyApp::myEnumProc(HWND hWnd, LPARAM lParam)

{

CMyApp * me = (CMyApp *)lParam;

if(::SendMessage(hWnd, UWM_ARE_YOU_ME))

{ /* found duplicate */

// ... do something here, e.g.,

me->foundPrevious = TRUE;

return FALSE; // stop enumerating

} /* found duplicate */

return TRUE; // keep enumerating

}

If I have a handler in my main window

LRESULT CMainFrame::OnAreYouMe(WPARAM, LPARAM)

{

return TRUE;

}

then in principle any message sent to any window that doesn't recognize the
Registered Window Message will pass it on to DefWindowProc, which,
because it does not recognize the message, will return 0, which means
that only my window will respond. This is also a technique for locating a client
or server window of an affiliated application.

So if I initially set foundPrevious to FALSE and call EnumWindows(myEnumProc,
(LPARAM)this) then when I return I'll know if I found a previous instance.

There are three major flaws in this code, none of which are evident.

First, while this is a fine technique for recognizing an affiliated window
such as a client window or server window (and in that case, the message would
probably pass a window handle as WPARAM to tell the affiliated window who
sent the message), it won't work for finding a duplicate instance of the
application. That's the topic of a different essay.

Second, it can deadlock on a failed or non-responsive application, leaving
you hanging.

Third, Microsoft has gone out of their way to make life totally miserable by
installing, on Windows 98, as part of the FrontPage product, a window which
ALWAYS responds with TRUE to any message!!!! While it is hard to believe
that anyone would have been stupid enough to do this, they have done it, and we
all suffer.

Let's look at these problems in detail:

The first flaw is very evident when you have a desktop configured to launch
an application on a single click. A user who is accustomed to double-clicking to
launch an application will double-click, and this will launch TWO copies of the
application. The first one does the EnumWindows loop and sees that it is
the only instance running. It then proceeds to create its main window and
continue on. The second instance comes up, and does the EnumWindows loop
as well. Because we are in a preemptive multithreaded environment, it actually
manages to complete its EnumWindows loop while the first application is
still creating its main window! So the first application's main window isn't up
yet, and the second application doesn't find it, and thinks that IT is the
one-and-only application. So we have two copies running, which is not what we
wanted.

We can't avoid this. Come up with any scenario (such as not calling the EnumWindows
until after the main window is created) and you still get the same race
condition.

which looks like a pretty good exchange of window handles. If you don't know
what Attach does, read my essay on Attach/Detach.

Now, somewhere on the system I've got a wedged application. Perhaps it is a
copy of IE waiting for an infinitely-long Web page timeout, and is blocked
somewhere in the network handler. Perhaps it is some poorly-designed program
that is doing a convolution algorithm on a terabit bitmap, and is doing it in
the one-and-only main thread, and isn't allowing any messages to come in (it
will be finished in a week or two). Perhaps it is one of your own programs
you're debugging that is lost in a loop. Whatever. The key is that there is very
long, possibly infinite delay, in an application you may not have even heard of.
And guess what? Your innocent application hangs.

The solution to this is to use ::SendMessageTimeout, so if one of
these applications would block you, you will not hang. You should select a small
timeout interval, such as 100ms, otherwise, you'll have a simply very long
startup.

Now to the nasty part, in which Microsoft really does us in. There is some
application which has a window whose class is "Front Page Message
Sink", and which exhibits the pathological and unsociable behavior that it
returns a nonzero value for EVERY message it receives. This is colossally
stupid. It is undocumented, it violates all known Windows standards, and it will
be fatal to you. This only shows up if you have Personal Web Server running. But
it is absolutely inexcusable to have done this.

All I know is that I see it return the value 1, consistently, for any kind of
Registered Window Message it receives. Perhaps this is the only value it
returns. I don't know, and nobody at Microsoft responded to my bug report with
anything explaining what is going on.

Thus testing the result of the ::SendMessage or the DWORD
result of ::SendMessageTimeout against 0 is not informative. Thus far, if
you see 0 or 1, you can't depend on the value having any meaning. With any luck,
Microsoft will fix this (hah!), and ideally they will not introduce other
gratuitous examples of such insanity in the future.

I worked around this by modifying the receiving handler to return a non-zero,
non-one value. For example, I actually use ::RegisterWindowMessage to get
a value, although I suppose I could have used ::GlobalAddAtom. At least I
know that ::RegisterWindowMessage will return a non-zero, non-one value.

If you are trying to pass a handle back, instead of just a designated value,
you would have to make the test

if(result != 0 &&

result != 1) // avoid Microsoft problem

{ /* found it */

target = new CWnd;

target->Attach(hWnd);

// ... do whatever you want here

return FALSE; // done iterating

} /* found it */

Note that if you choose to use ::FindWindow, it does an ::EnumWindows
internally, and consequently can be subject to the same permanent hang. Using ::FindWindow
is extremely hazardous, since it assumes that in fact every ::SendMessage
will complete. Note that ::FindWindow does a ::SendMessage(hWnd, WM_GETTEXT,
...) to get the window text to search for.

There is a possibly useful message, WM_COPYDATA, that will
transfer information across the boundary. It does this by passing the data thru
the kernel. Space is allocated in the receiving process to hold the information
that is copied, by the kernel, from the source process to the target process. Or
something that resembles that. The implementation details are actually concealed
from you.

The sender passes a pointer to a COPYDATASTRUCT, which is defined as a
structure of the following:

typedef struct tagCOPYDATASTRUCT {

DWORD dwData;

DWORD cbData;

PVOID lpData;

} COPYDATASTRUCT, *PCOPYDATASTRUCT;

The dwData member holds an arbitrary 32-bit value that is being passed
to the target. You can set this to any value the two processes agree on. The cbData
member tells how many bytes are in the value referenced by lpData. When
the target process receives the information, it handles it via a method

BOOL CMainFrame::OnCopyData(CWnd* pWnd,

COPYDATASTRUCT* pCopyDataStruct)

The CWnd * is a reference to the sending window, and the COPYDATASTRUCT
* references the COPYDATASTRUCT that was passed in. Note that you don't
know the actual address in the sender. The data which is passed in must not
contain pointers.

There are some potential problems with WM_COPYDATA, in that you need
to identify who has sent it in order to understand if it is valid, or you must
have some other way to identify it. One way to handle it is to use our old
friend the GUID. If you put a GUID in the beginning of the data packet, you can
compare it to the expected GUID and if they are equal you know for certain that
the packet you received is the packet you want.

You must not store the pCopyDataStruct.lpData pointer, because after
you return from the OnCopyData handler the pointer should be assumed to
be no longer valid. You must also not attempt to write into the data referenced
by the lpData pointer; it must be treated as read-only.

Two other considerations are important: you must not put pointers into the
data being passed, and you must completely process it before returning to the SendMessage
that sent it. This means you must not store the lpData pointer in any
place that would be accessible after you return from the handler (storing it in
a local variable in your handler is perfectly fine, but not in a global variable
or in any structure on the heap).

The problem of storing pointers is a little bit misleading. You must not
store pointers in the structure you pass, even if they are pointers into the
same area you are passing, because when the message is received the recipient
has no control over where it is placed, and the pointers are likely to be
nonsense. Obviously, you can't store pointers to other areas of your own memory
because they will be completely nonsensical in the receiving process; they will
be interpreted in its own address space.

But the misleading aspect is that if you have a structure which is entirely
self-contained in the data area you are sending over (that is, every pointer
refers to another structure in the area you are sending), then you can use based
pointers to encode them. Based pointers are actually relative offsets
measured from a specific starting point (such as the start of the area being
transmitted), and are automatically adjusted by the recipient (as long as you
set up the correct base value) so they are valid pointers. For example, consider
the following structure

Notice some problems with this from the viewpoint of object-oriented
programming. The operand of the __based qualifier must be an LPVOID
global variable. For reasons that are known only to the minds of the compiler
writers, this cannot even be a static class member! The name basevalue
is bound at the time of the declaration to the global variable. This means that
you have to set the value whenever you are doing any sequence of accesses. Using
a global variable is not thread-safe, but you can declare it using __declspec(thread)
to make the "global" variable actually a "thread global"
unique to each thread.

For more information on based pointers, see my essay on based pointer
techniques.

MFC has a wonderful message routing mechanism. A command message first comes
to the active view, then the view frame, then the document, and so on. This
works for WM_COMMAND and WM_UPDATE_COMMAND_UI messages, but does
not work for any other kind of message, including user-defined messages. This is
a real pain, and somewhat silly because it would be easy for Microsoft to
implement. So a problem arises when you need to send a message to some
sub-window, but you can't send a WM_COMMAND message because you are not
directly responding to a GUI component.

Of course, you could invent a fictitious control and generate your own
imitation WM_COMMAND messages. But this is very risky, and contributes to
significant future unmaintainability.

What can you do?

I've done several things. Sometimes, I just put a message handler in the
child frame whose sole purpose is to route the message to the child window
contained in the frame. This can be a pain, but gives you serious control over
how the messages are processed. Thus, the main frame, to which I post a message
(often from a thread), has a handler of the form

Sometimes you have to send the message not to the view, but to its parent
frame window. This is done by the following code:

RESULT CMainFrame::OnThreadDidSomething(WPARAM wParam, LPARAM lParam)

{

CFrameWnd * active = GetActiveFrame();

if(active != this)

active->SendMessage(UWM_THREAD_DID_SOMETHING,

wParam, lParam);

return 0;

}

Note the special test above. If, for some reason, you had managed to kill off
all the MDI children while the thread was still running, GetActiveFrame
returns this, which would mean you would get into a semi-infinite SendMessage
loop which would terminate when you ran out of stack space. Note that because
the function is defined as returning this we don't have to worry about
the possibility that a temporary window handle has been returned, a caution I
discuss in my essay on the use of Attach/Detach.
This requires that you use the CMDIChildFrame subclass, and introduce a
similar handler there:

Now, you may wonder why I didn't send it directly to the child window. Partly
because I'm lazy, and SendMessageToDescendants does what I need. Partly
because I don't need the result, because it came in from PostMessage. In
a case where I had to route a message to the descendant where I needed the
result, I'd instead write

CView * view = (CView *)GetWindow(GW_CHILD);

ASSERT(view != NULL && view->IsKindOf(RUNTIME_CLASS(CView)));

view->SendMessage(...);

Summary

User-defined messages are a powerful and flexible mechanism for handling the
passing of information and control between levels of your application, threads
of your application, and processes. However, using them effectively requires
certain degrees of care. I favor using ::RegisterWindowMessage and GUIDs
to define all messages. Interthread and interprocess sends are risky, and should
be avoided; if you must, use SendMessageTimeout to ensure that you will
not end up in deadlock.

The views expressed in these essays are those of the
author, and in no way represent, nor are they endorsed by, Microsoft.