What's the best way to send myself a message in MFC?

Those message maps in MFC do help tidy up a program, but they pose a problem for an SDK developer coming new to MFC - how to send my own program a message? This used to be easy in the old days - you just posted yourself a message value in the range WM_USER + N, and handled the message in your WndProc in the normal way. In this brave new world however, there are a few changes.

First of all, the value to be used. WM_USER messages have always caused some subtle bugs, because Windows itself uses a few messages in this range for dialog management (duh ?!?!). So, Microsoft added the new range beginning with WM_APP, which was guaranteed to be outside the range used by Windows itself: but not outside the range that might be used by another app - we'll come to that in a minute.

Well, that's fine if you're writing an SDK app, but what about MFC message maps ? Well, the special ON_MESSAGE macro was invented for this. Let's say we want to send ourselves a message of WM_APP+1000.

We have to add the macro to the message map, being careful to put it outside the markers for ClassWizard message handlers:

ON_WM_INITMENU()
ON_WM_INITMENUPOPUP()
//}}AFX_MSG_MAP

ON_MESSAGE (WM_APP+1000, OnMyMessage)
END_MESSAGE_MAP()

Then we add a prototype for the message to our class header:

afx_msg LRESULT OnMyMessage (WPARAM wParam, LPARAM lParam);

Then we can create a body for the handler, and invoke it by simply posting ourselves the message with whatever parameters we want:

PostMessage (WM_APP+1000, 1, 27);

This is all fine and dandy. But there's a fly in this ointment - a fly that's been around since the earliest days of Windows and messages. It is perfectly possible for one app to broadcast a message to all Windows, and therefore it is possible for another app to broadcast the same carefully-chosen WM_APP value to you. Thereby invoking your lovely handler when the event you're looking for has not happened at all. Oh calamity! This is especially likely if you choose a nice round number like I did above...

The solution is to use REGISTERED messages. I moved ALL my self-messaging code to registered messages a long time ago, and haven't suffered as a result. This requires a slightly different technique. First we have to "register" the message with windows using the Windows api call RegisterWindowMessage. This takes a textual name for the message, and returns an ID in a special range, which is guaranteed to be unique UNLESS another app calls RegisterWindowMessage with the same textual key. To lower this already low probability I use GUIDGEN.EXE (gui) or UUIDGEN.EXE (command line), which ship with the Platform SDK, to generate a GUID - Globally Unique IDentifier - value, then use this string with RegisterWindowMessage. I usually add a readable prefix to the GUID just for my own convenience. By the way, yes, these are the same GUID values that COM uses for identifying its classes.

static UINT g_uAppBarSlide = 0;
....
g_uAppBarSlide = RegisterWindowMessage ("APPBAR_da725800-71f1-11d4-8437-00c04f9d75f4");

The next thing to note is that the variable used to store the message value is a module global, NOT a class member. This is because the ON_REGISTERED_MESSAGE macro requires that. You declare the handler to the system much as we did before, but now using this new macro:

ON_REGISTERED_MESSAGE (g_uAppBarSlide, OnSlide)
END_MESSAGE_MAP()

Our prototype looks much like it did before:

afx_msg LRESULT OnSlide  (WPARAM, LPARAM);

Note that in this case I'm not using the parameters, so I use the type-only notation. So all I have to do now is to use the value stored in our global to send the message:

PostMessage (g_uAppBarSlide);