Before we get to the meat of this article, here's a quick introductory story. The next release of Paper Plus will only allow one instance of the application to run at a time. One strange bug I ran into during the testing phase of this new feature, was the case where the application was minimized to the system tray. If a previous instance is already running (and minimized), I wanted the action of trying to start a new instance to restore the old one. For a number of reasons which I won't go into, I couldn't get the level of control I needed to restore things properly. So, to get things working, I turned to user defined messages which, happily, solved my problem. Here's a quick guide to getting custom messages up and running in a Visual C++ application.
Step 1: Define the Message ID
This is straightforward, but you'll need to make sure your definition appears in the appropriate place. I put mine in stdafx.h, which is included by nearly every file in the project.
#define WM_MYCUSTOMMESSAGE WM_USER+1
Step 2: Add the Message to a Message Map
Next, your custom message needs to be added to the appropriate message map. I added mine to the message map down in my CFrameWnd
derived class. Here's how the entry looks in my case:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
...
ON_MESSAGE(WM_MYCUSTOMMESSAGE, MyCustomCallback)
...
END_MESSAGE_MAP()
Step 3: Implement the Custom Callback
Your callback function declaration must adhere to the appropriate form, as shown below:
LRESULT MyCustomCallback(WPARAM wParam, LPARAM lParam);
Custom message callbacks must always return an LRESULT
, and must accept two parameters: a WPARAM
and an LPARAM
(down under the covers, both are simply pointers of varying types).
Once you've got the declaration in place, it's time for the definition:
LRESULT CMainFrame::MyCustomCallback(WPARAM wParam, LPARAM lParam)
{
// Do something clever here
return 0; // Make sure to return some value
}
Step 4: Post Your Custom Message
Now that we've got our custom message callback installed, we need to post our new message in the appropriate place. I decided to use the SendMessageTimeout function, based on some code I saw which used this function to prevent the application from hanging. Here's a variant of the code I used:
DWORD_PTR dwResult = 0;
// The hWnd parameter below is a handle to the window this message
// should be posted to. Setting this up is not shown, in order to keep
// this article as short as possible.
SendMessageTimeout(hWnd, WM_MYCUSTOMMESSAGE, 0, 0,
SMTO_ABORTIFHUNG, 5000, &dwResult);
And that's it! Being able to post your own messages can help you out of some sticky situations, and lets you take control of your application in some interesting new ways.