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
| Вернуться в корень Архива |