Custom window messages
Terry Wellmann -- wellmatl@cs.purdue.edu
Monday, April 01, 1996
Win NT/95 VC++ 4.0
Here is a reply I received, from Rob Gue, in regards to my question of
custom windows messages.
This hit it right on the head and allowed me to create and use my own
custom messages within my app. At the end of the article I've appended a
snipit that I found from the VC++ on-line help on the matter.
Terry
>PSS ID Number: Q86835
>Article last modified on 11-02-1995
>
>3.00 3.10 4.00 | 3.50 3.51
>
>WINDOWS | WINDOWS NT
>
>
>-------------------------------------------------------------------------
>The information in this article applies to:
>
> - Microsoft Windows Software Development Kit (SDK) versions 3.1
>
> - Microsoft Win32 Application Programming Interface (API) included with:
>
> - Microsoft Windows NT versions 3.5 and 3.51
> - Microsoft Windows 95 version 4.0
>-------------------------------------------------------------------------
>
>SUMMARY
>=======
>
>In the Microsoft Windows environment, an application can define a private
>message for its own use without calling the RegisterWindowMessage API.
>Message numbers between 0x8000 and 0xBFFF are reserved for this purpose.
>
>For Windows NT and Windows 95, the system defines a new message WM_APP
>(value 0x8000). Applications can make use of the range WM_APP through
>0xBFFF for private messages without conflict. The only requirement is that
>the .EXE file must be marked version 4.0 (use the linker switch
>/subsystem:windows,4.0). Windows NT 3.5 and 3.51 and Windows 95 will run
>applications marked version 4.0.
>
>MORE INFORMATION
>================
>
>The documentation for the WM_USER message lists four ranges of message
>numbers as follows:
>
> Message Number Description
> -------------- -----------
>
> 0 through WM_USER-1 Messages reserved for use by Windows.
>
> WM_USER through 0x7FFF Integer messages for use by private window
> classes.
>
> 0x8000 through 0xBFFF Messages reserved for use by Windows.
>
> 0xC000 through 0xFFFF String messages for use by applications.
>
> Greater than 0xFFFF Reserved by Windows for future use.
>
>When an application subclasses a predefined Windows control or
>provides a special message in its dialog box procedure, it cannot use
>a WM_USER+x message to define a new message because the predefined
>controls use some WM_USER+x messages internally. It was necessary to
>use the RegisterWindowMessage function to retrieve a unique message
>number between 0xC000 and 0xFFFF.
>
>To avoid this inconvenience, messages between 0x8000 and 0xBFFF were
>redefined to make them available to an application. Messages in this
>range do not conflict with any other messages in the system.
>
>Additional reference words: 3.00 3.10 3.50 4.00 95
>KBCategory: kbui
>KBSubcategory: UsrMsg
>=============================================================================
>Copyright Microsoft Corporation 1995.
>
>
>
Defining a Message Map
The DECLARE_MESSAGE_MAP macro declares three members for a class.
* A private array of AFX_MSGMAP_ENTRY entries called _messageEntries,
* A protected AFX_MSGMAP structure called messageMap that points to
the _messageEntries array
* A protected virtual function called GetMessageMap that returns the
address of messageMap.
This macro should be placed in the declaration of any class using message
maps. By convention, it is at the end of the class declaration. For
example:
class CMyWnd : public CMyParentWndClass
{
// my stuff...
protected:
//{{AFX_MSG(CMyWnd)
afx_msg void OnPaint();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
This is the format generated by AppWizard and ClassWizard when they create
new classes. The //{{ and //}} brackets are needed for ClassWizard.
The message map's table is defined with a set of macros that expand to
message map entries. A table begins with a BEGIN_MESSAGE_MAP macro call,
which defines the class that is handled by this message map and the parent
class to which unhandled messages are passed. The table ends with the
END_MESSAGE_MAP macro call.
Between these two macro calls is an entry for each message to be handled by
this message map. Every standard Windows message has a macro of the form
ON_WM_xxx (where xxx is the name of the message) that generates an entry
for that message.
A standard function signature has been defined for unpacking the parameters
of each Windows message and providing type safety. These signatures may be
found in the file AFXWIN.H in the declaration of CWnd. Each one is marked
with the word afx_msg for easy identification.
Note ClassWizard requires that you use the afx_msg keyword in your
message map handler declarations.
These function signatures were derived using a simple convention. The name
of the function always starts with "On". This is followed by the name of
the Windows message with the WM_ removed and only the first letter of each
word capitalized. The ordering of the parameters is wParam followed by
LOWORD(lParam) then HIWORD(lParam). Unused parameters are not passed. Any
handles that are wrapped by MFC classes are converted to pointers to the
appropriate MFC objects. The following example shows how to handle the
WM_PAINT message and cause the CMyWnd::OnPaint function to be called:
BEGIN_MESSAGE_MAP(CMyWnd, CMyParentWndClass)
//{{AFX_MSG_MAP(CMyWnd)
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
The message map table must be defined outside the scope of any function or
class definition. It should not be placed within an extern "C" block.
Note ClassWizard will edit the message map entries that are found between
the //{{ and //}} comment bracket.
User Defined Windows Messages
User-defined messages may be included in a message map by using the
ON_MESSAGE macro. This macro accepts a message number and a member function
of the form:
// inside the class declaration
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
For example:
#define WM_MYMESSAGE (WM_USER + 100)
BEGIN_MESSAGE_MAP(CMyWnd, CMyParentWndClass)
ON_MESSAGE(WM_MYMESSAGE, OnMyMessage)
END_MESSAGE_MAP()
In this example, we establish a handler for a custom message with a Windows
message ID derived from the standard WM_USER base for user-defined
messages. You might invoke this handler with code such as:
CWnd* pWnd = ...;
pWnd->SendMessage(WM_MYMESSAGE);
The range of user defined messages using this approach must be in the range
WM_USER to 0x7fff.
Note ClassWizard does not support entering ON_MESSAGE handler routines
from the ClassWizard user interface: you must manually enter them from the
Visual C++ editor. Once entered, ClassWizard will parse these entries and
allow you to browse them just like any other message-map entries.
-----------------------------------------------------------------------
| Terry Wellmann |
| Programmer/Systems Analyst - MailCode Inc. - Lafayette, IN |
| http://www.cs.purdue.edu/people/wellmatl |
|---------------------------------------------------------------------|
| Will code for food. |
-----------------------------------------------------------------------
David W. Gillett -- DGILLETT@expertedge.com
Wednesday, April 03, 1996
> Here is a reply I received, from Rob Gue, in regards to my question of
> custom windows messages.
>
> This hit it right on the head and allowed me to create and use my own
> custom messages within my app. At the end of the article I've appended a
> snipit that I found from the VC++ on-line help on the matter.
Although these provide ways for you to send custom messages without
registering them, there's nothing to help you track how many private
messages you've defined, or to automatically give them names --
that's left up to the programmer.
What I have done, in at least one app, is use the WM_COMMAND
message. At the price of including in my executable a MENU resource
that I never load, AppStudio lets me group and name my messages, and
ClassWizard helps me create handlers for them by those names.
Purists may argue that this is more "trick" than "tip", but I
consider it "creative application of available tools to unanticipated
problem".
Dave
| Вернуться в корень Архива
|