Technical Note 062: Message Reflection of Windows Control TN062: Message Reflection for Windows Controls
This technology pays attention to the message reflection, a new feature in an MFC4.0. At the same time, the guidance of using message reflection is established to establish a simple reusable control. This Technical Note Describes Message Reflection, A New Feature IN MFC 4.0. IT Also Contains Directions for Creating A Simple Reusable Control That Uses Message Reflection.
This article does not perform message reflection on the ActiveX control (previously referred to as OLE control). For information on this, see "ActiveX Controls: Subclassing A Windows Control In Visual C Programmer's Guide". This technical note does not discuss message reflection as it applies to ActiveX controls (formerly called OLE controls) Please see the articleActiveX Controls:. Subclassing a Windows Control in Visual C Programmer's Guide.
What is message reflection? What is message reflection?
The window constantly sends a notification message to its parent window. For example: Many controls send control color notification messages (WM_CTLCOLOR or a variant thereof) to their parent windows to allow their parent windows to provide a brush for a background of a control.
Windows controls frequently send notification messages to their parent windows. For instance, many controls send a control color notification message (WM_CTLCOLOR or one of its variants) to their parent to allow the parent to supply a brush for painting the background of the control.
In Windows and MFC4.0, the parent window - is usually a dialog, which will respond to processing these messages. This means that the code to handle these messages needs to be implemented in the parent window class, and these messages are handled for each class. In the above case, each dialog that needs to customize the background control has to handle the control color notification message. If a control can handle your background color and can be reused, things will become simpler. In Windows and in MFC prior to version 4.0, the parent window, often a dialog box, is responsible for handling these messages. This means that the code for handling the message needs to be in the parent window's class and that it has to be duplicated in every class that needs to handle that message. in the case above, every dialog box that wanted controls with custom backgrounds would have to handle the control color notification message. It would be much easier to reuse code if a control class could be written that Would Handle ITS OWN Background Color.
In MFC 4.0, the old message mechanism is still in the work - parent window to handle the notification message. Also, MFC 4.0 is much easier to repeat the use by providing a new mechanism called "message reflection". Message reflection allows these notification messages to be handled by control itself, and can also be processed by their parent windows. In the above control background color example, now you can write a control class that is emitted from the WM_CTLColor message you can handle, all everything is no longer relying on its parent window. (Note that since this message reflection can only be implemented in the MFC, not a Windows system. So the parent window must be derived from CWND, so message reflection can work properly). In MFC 4.0, the old mechanism still works-parent windows can handle notification messages. In addition, however, MFC 4.0 facilitates reuse by providing a feature called "message reflection" that allows these notification messages to be handled in either the child control window or the parent window, or in both. in the control background color example, you can now write a control class that sets its own background color by handling the reflected WM_CTLCOLOR message-all without relying on the parent. (Note that since message reflection is implemented By MFC, Not by Windows, The Parent WINDOW CLASS MUST BE WORK.. The old version implemented similar features by providing virtual functions for some messages, the most typical list of self-drawn Box (WM_DRAWITEM, etc.). Then new message reflex mechanism is more common and lasting. Older versions of MFC did something similar to message reflection by providing virtual functions for a few messages, such as messages for owner-drawn list boxes (WM_DRAWITEM, and so on). The new message reflection mechanism is generalized and consistent.
The message message mechanism is compatible with the code before the MFC4.0 version. Message Reflection Is Backward Compatible with code Written for version of mfc previous to 4.0. If you provide a handler for one or a range of specific messages in the parent window class of the control, for the same message, if you have You did not call the processing function of the base class, which overwrite the reflected message processing. For example, if you try to process WM_CTLCOLOR in a dialog class, your process will overwrite any reflected message processing functions. If you have supplied a handler for a specific message, or for a range of messages, in your parent window's class, it will override reflected message handlers for the same message provided you do not call the base class handler function in your own handler. For example, if you have ingle wm_ctlcolor in your dialog box class, your handling will override any reflected message handlers. If you provide a handler for one or a range of specific WM_NOTIFY messages, your handle function is only When the subcipes of these send messages will not have a reflected message to handle it through an on_notify_reflecéct () macro. If the process returns True, the message will also process the parent window, and if it returns a FALSE value, the parent window will not process the message. Note: The reflected message is processed before the notification message.
If, in your parent window class, you supply a handler for a specific WM_NOTIFY message or a range of WM_NOTIFY messages, your handler will be called only if the child control sending those messages does not have a reflected message handler through ON_NOTIFY_REFLECT (). If you use ON_NOTIFY_REFLECT_EX () in your message map, your message handler may or may not allow the parent window to handle the message. If the handler returns TRUE, the message will be handled by the parent as well, while a call that returns FALSE does NOT Allow The Parent to Handle It. Note That The Reflected Message IS Handled Before The Notification Message.
When a WM_NOTIFY message is sent, the control has received the first opportunity to handle it. If any other reflected message is sent, the parent window will have a first chance to process, and the control will be able to receive the reflected message. In order to achieve this, a process function and a suitable entry are required in the control class message mapping. When a WM_NOTIFY message is sent, the control is offered the first chance to handle it. If any other reflected message is sent, the parent window has the first chance to handle it and the control will receive the reflected message. To do so, it Will NEED A HANDLER FUNCTION AND AN Appropriate Entry In The Control's Class Message Map. The message map of the reflected message is a bit slightly different from the message mapping macro that is usually notified: it needs to be added in its regular name. For example, in order to process the WM_NOTIFY message in the parent window, you can use the macro on_notify in the message map of the parent window class. To process reflection messages in the child control class, you must use on_notify_reflect to respond to the message. In some cases, the parameters are different. Note: ClassWizard can usually add a message entry for you and provides a general framework for implementation functions with the correct parameters. The message-map macro for reflected messages is slightly different than for regular notifications: it has _REFLECT appended to its usual name For instance, to handle a WM_NOTIFY message in the parent, you use the macro ON_NOTIFY in the parent's message map To handle.. the reflected message in the child control, use the ON_NOTIFY_REFLECT macro in the child control's message map. in some cases, the parameters are different, as well. Note that ClassWizard can usually add the message-map entries for you and provide skeleton function implementations with Correct parameters.
See TN061: ON_NOTIFY with WM_NOTIFY information in the new WM_Notify message See tn061: on_notify and wm_notify message for information on the new wm_notify message.
Message mapping entry and processing function prototype Message-map entries for reflected Messages
In order to process the reflected control notification message, use the message mapping macro and function prototypes listed in the table below. To Handle A Reflected Control NOTIFICATION Message, Use the message-mapmed in The Table Below.classwizard typically can join the message mapping entry and provide you with a skeleton that implements functions. See "Defining a Message Handler for a Reflected Message In The Visual C Programmer's Guide" to get information about how to define the process of processing the function. ClassWizard can usually add these message-map entries for you and provide skeleton function implementations. SeeDefining a Message Handler for a Reflected Message in the Visual C Programmer's Guide for information about how to define handlers for reflected messages.
In order to convert the message name to the reflected macro name, the message name is before, then adds _REflect after the message name. For example, the WM_CTLCOLOR is converted to ON_WM_CTLCOLOR_REFLECT. To convert from the message name to the reflected macro name, prepend ON_ and append _REFLECT. For example, WM_CTLCOLOR becomes ON_WM_CTLCOLOR_REFLECT. (To see which messages can be reflected, do the opposite conversion on the macro entries in the table below.)
The above rules [universal, but pay attention to there are three exceptions: The Three Exceptions to the Rule Above Area Follows:
The macro for WM_COMMAND notification is ON_Control_reflect; macro for WM_NOTIFY notification is ON_NOTIFY_REFLECT; macros for the ON_UPDATE_COMMAND_UI notification is ON_UPDATE_COMMAND_UI_REFLECT.
The Macro for WM_COMMAND NOTIFICATIONS IS ON_CONTROL_REFLECT.THE Macro for WM_NOTIFLE REFLECTIONS IS ON_NOTIFY_REFLECT.THE Macro for on_UPDATE_COMMAND_UI REFLECTIONS IS ON_UPDATE_COMMAND_UI_REFLECT.
In the above special circumstances, you must specify the name of the processing member function. In other cases, you must use the standard processing function name. IN Each of the Above Special Cases, You Must Specify The Name of The Handler Member Function. In The Handler Member Function. The meaning of the function parameters. Under or have been pre-written. For example, CTLColor is represented in the document as onctlcolor. Several parameters required by several reflected messages are less than the parameters required by the corresponding function in their parent window. See the official parameters in the documentation in the following table. The meanings of the parameters and return values of the functions are documented under either the function name or the function name with On prepended. For instance, CtlColor is documented in OnCtlColor. Several reflected message handlers need fewer parameters than the similar handlers in a parent window .........................
Map macro entry function prototype ON_CONTROL_REFLECT (wNotifyCode, memberFxn) afx_msg void memberFxn (); ON_NOTIFY_REFLECT (wNotifyCode, memberFxn) afx_msg void memberFxn (NMHDR * pNotifyStruct, LRESULT * result); ON_UPDATE_COMMAND_UI_REFLECT (memberFxn) afx_msg void memberFxn (CCmdUI * pCmdUI); ON_WM_CTLCOLOR_REFLECT () afx_msg HBRUSH CtlColor (CDC * pDC, UINT nCtlColor); ON_WM_DRAWITEM_REFLECT () afx_msg void DrawItem (lPDRAWITEMSTRUCT lpDrawItemStruct); ON_WM_MEASUREITEM_REFLECT () afx_msg void MeasureItem (LPMEASUREITEMSTRUCT lpMeasureItemStruct); ON_WM_DELETEITEM_REFLECT () afx_msg void DeleteItem (lPDELETEITEMSTRUCT lpDeleteItemStruct); ON_WM_COMPAREITEM_REFLECT () afx_msg int CompareItem (lPCOMPAREITEMSTRUCT lpCompareItemStruct); ON_WM_CHARTOITEM_REFLECT () afx_msg int CharToItem (UINT nKey, UINT nIndex); ON_WM_VKEYTOITEM_REFLECT () afx_msg int VKeyToItem (UINT nKey, UINT nIndex); ON_WM_HSCROLL_REFLECT () afx_msg void HScroll (UINT nSBCode, UINT nPo s); ON_WM_VSCROLL_REFLECT () afx_msg void VScroll (UINT nSBCode, UINT nPos); ON_WM_PARENTNOTIFY_REFLECT () afx_msg void ParentNotify (UINT message, LPARAM lParam); ON_NOTIFY_REFLECT ON_CONTROL_REFLECT and a few variants, to allow the parent window and a plurality of controls, such as Objects to deal with a given message.
The on_notify_reflect and on_control_reflect Macros Have Variations That Allow More Than Object (Such as the control and its parent) to handle a given message.
Entry map macro function prototype ON_NOTIFY_REFLECT_EX (wNotifyCode, memberFxn) afx_msg BOOL memberFxn (NMHDR * pNotifyStruct, LRESULT * result); ON_CONTROL_REFLECT_EX (wNotifyCode, memberFxn) afx_msg BOOL memberFxn ();
Processing reflected message: Example of reusable controls Handling Reflected Messages: An Example of A Reusable Control
This simple example creates a reusable control called cyllowedit. The control is almost the same as a conventional editing control, and the difference is that it shows black words in a yellow background. Of course, you can easily add some member functions to display different colors. This simple example creates a reusable control called CYellowEdit. The control works the same as a regular edit control except that it displays black text on a yellow background. It would be easy to add member functions that would allow the CYellowEdit control to display different colors. 1 Refer to the following steps: To try this Example, Do The Following Steps:
Add a dialog box to an existing application, see "Dialog Editor In The Visual C User's Guide".
You must have an existing application to develop reusable controls, if you have no available applications, you may wish to use AppWizard to create a dialog-based application. Create a new dialog box in an existing application. For more information seedialog editor in the Visual C User's Guide.You must have an application in which to develop the reusable control. If you do not have an existing application to use, create a dialog -Based Application useing appwizard.
Wait for VC to load your application, create a new Cyellowedit class based on CEDIT classes using ClassWizard. Cancel the "Add to Component Gallery" option. WITH YOUR PROJECT Loaded Into Visual C , Use Classwizard To Create A New Class Called Cyellowedit Based on CEDIT. Leave The "Add to Component Gallery" box check.
Add three member variables to the Cyellowedit class. The first two is the variable of ColorRef to record text and background colors. The third variable is a brush class CBRUSH variable for drawing the background. The brush variable allows you to create only once, next to it, you can get the brush when the Cyellowedit control is destroyed. Add three member variables to your CYellowEdit class. The first two will be COLORREF variables to hold the text color and the background color. The third will be a CBrush object which will hold the brush for painting the background. The CBrush object allows you to create the brush once, merely referencing it after that, and to destroy the brush automatically when the CYellowEdit control is destroyed in the constructor initializes the member variables:. initialize the member variables by writing the constructor as follows: CYellowEdit :: CYellowEdit () { m_clrtext = RGB (0, 0, 0); m_clrbkgnd = RGB (255, 255, 0); m_brbkgnd.createsolidbrush (m_clrbkgnd);}
Add a process function to the Cyellowedit class for the WM_CTLCOLOR Reflective message using ClassWizard. Note that the number before the message name in the message list you can handle indicates that the message is a message that can be reflected. This is described in "Defining a Message Handler for a Reflected Message in the Visual C Programmer's Guide". ClassWizard will add the following message mapping macro and the corresponding function skeleton:
Using ClassWizard, add a handler for the reflected WM_CTLCOLOR message to your CYellowEdit class. Note that the equal sign in front of the message name in the list of messages you can handle indicates that the message is reflected. This is described inDefining a Message Handler for A Reflected Message In The Visual C Programmer's Guide.classwizard Adds The Following Message-Map Macro and Skeleton Function for you:
ON_WM_CTLCOLOR_REFLECT ()
// Note: Other code will be in between ....
Hbrush Cyellowedit :: CTLCOLOR (CDC * PDC, uint nctlcolor) {// Todo: Change Any Attributes of the DC Here
// Todo: Return A Non-Null Brush if The // Parent's Handler Should Not Be called Return Null;} Instead of the body of the function. The program code is simple, that is, the background color of the text color, text background color, and the rest of the control. Replace the body of the function with the following code The code specifies the text color, the text background color, and the background color for rest of the control.pDC-> SetTextColor (m_clrText);. // textpDC-> SetBkColor (m_clrBkgnd) ; // text bkgndreturn m_brbkgnd; // CTL BKGND
Create an edit control in the dialog box, press the next control key to double-click the edit control and associate it with a member variable. When adding a member variable to the dialog, complete the variable name, and select "Cyellowedit" as the prototype of your variable. Don't forget to set the tab order in your dialog. Also don't forget to add a header file of the Cyellowedit class in your dialog header file.
Create an edit control in your dialog box, then attach it to a member variable by double-clicking the edit control while holding a control key down. In the Add Member Variable dialog box, finish the variable name and choose "Control" for the category ...................................... ..
Compile and run your program, the editing control will display a yellow background. Build and Run your application. The Edit Control Will Have a Yellow Background.
Now you can use Component Gallery to add your Cyellowedit control class to other projects.
You Can Now Use Component Gallery To Add Your Cyellowedit Control Class To Other Projects.