HOWTO: MFC user defined message maps

We will add the user defined message WM_FIND, identified by the string
literal “MYMESSAGE”, to a Document/View MFC application. First of
all, the message can only be posted to objects of class CWnd or
classes derived from CWnd, i.e. actual windows. This makes sense; only
windows can receive window messages. Also note, that the class wizard
CANNOT be used to introduce message maps for user defined messages.
This task must be completed manually.

IN THE VIEW CLASS HEADER FILE

Add the prototype for the function to which the message is to be
mapped. This function will be named “On” + (Second half of message
name), here: “OnFind()”. Further, the function declaration will be
preceded by the term “afx_msg”. We will define this function to be of
type LRESULT (32 bit identifier) , and take the parameters (WPARAM
wParam, LPARAM lParam), the standard window messaging parameters. The
reason for this lies in the macro expansion of the AFX message map. If
your function is not declared in compliance with the AFX message map
macro, you will get error C2642.

Look for a section of code like this:

	// Generated message map functions
	protected:
	//{{AFX_MSG(CMyView)
	afx_msg void OnFileConfig();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()

Add the following line to the above list of function declarations:

	afx_msg LRESULT OnFind(WPARAM wParam, LPARAM lParam);

IN THE VIEW CLASS BODY FILE

Register the new window message. The string literal will later be used
to retrieve the number allocated to WM_FIND.

Add the following line somewhere at the top of the file:

	int WM_FIND = RegisterWindowMessage ("MYMESSAGE");

Map the message onto a member function. The AFX message map entry must
use the key word ON_REGISTERED_MESSAGE, and associate the message
number with the function name.

Look for a section of code like this:

	BEGIN_MESSAGE_MAP(CMyView, CListView)
	//{{AFX_MSG_MAP(CMyView)
	ON_COMMAND(ID_FILE_CONFIG, OnFileConfig)
	//}}AFX_MSG_MAP
	END_MESSAGE_MAP()

Add the following line to the above list of message maps:

	ON_REGISTERED_MESSAGE(WM_FIND, OnFind)

Add a message handler function to the class. Replace
“CMyView” with the class name of the view class in your
application:

LRESULT CMyView::OnFind(WPARAM wParam, LPARAM lParam)
{
	// do something useful

	return (LRESULT) MyReturnValue;
};

IN THE DOCUMENT CLASS HEADER FILE

Provide the document class that is to post the message with scope to
the view class window handle.

Add a member to hold a window handle.

	HWND PostToView;

IN THE VIEW CLASS BODY FILE

Obtain a reference to the document associated with the view and
initialize the document’s member variable (above) with the handle to
the view’s window.

Add the lines shown below to a member function that will be
executed
before the user message is posted to the view. Replace “CMyDoc”
with the class name of your document class. This assignment cannot
take place in the view’s constructor. The OnCreate() member,
however, would be a great place.

	"CMyDoc"* DocPtr = GetDocument();
	DocPtr->PostToView = this->m_hWnd;

IN THE DOCUMENT CLASS BODY FILE

Where you want to post the message, retrieve the reference to WM_FIND,
the user defined message and then post the message…

A second call to RegisterWindowMessage() with the same string literal
as an argument will retrieve the previously assigned ID for WM_FIND.

Add the code shown below in a function member of the document class

from which you wish to post a message. Substitute the question
marks for your actual parameters.

	int WM_FIND = RegisterWindowMessage ("MYMESSAGE");

	PostMessage(PostToView,   // handle to view window
	WM_FIND,                  // message to post
	(WPARAM) "?",             // window message parameter
	(LPARAM) "?");            // window message parameter

Alternatively, you can use SendMessage(). In contrast to PostMessage,
which sends the message `spiraling’ through the Windows messaging
system and returns control to the calling thread before the message is
actually processed, SendMessage will invoke the target message handler
before returning execution control to the caller of SendMessage. The
first is appropriate for asynchronous, de-coupled processing, the
latter for synchronous processing.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read