Click here to Skip to main content
11,581,852 members (72,592 online)
Click here to Skip to main content

Windows Message Handling - Part 4

, 25 Apr 2003 463.3K 5.5K 224
Rate this:
Please Sign up or sign in to vote.
Reflected Messages, MFC and SDK Subclassing
  • MFC Subclassing source files
  • SDK Subclassing source files

    Introduction

    Subclassing is a technique that allows an application to intercept and process messages sent or posted to a particular window before the window has a chance to process them. This is typically done by replacing the Window Procedure for a window with application-defined window procedure. I will devide this article into 3:

    1. Subclassing in SDK programs,
    2. Subclassing in MFC programs,
    3. Reflected messages

    Why subclass?

    Sometimes you want to take the functionality of a control and modify it slightly. One example is replacing the menu in an edit control, Another is adding a context menu when you press on a button. One of the most common questions I encounter is "How do I screen out characters from an edit control?". I will show the solution to this from an MFC approach and from an SDK approach, while I try to explain Subclassing.

    The need for subclassing comes from the fact that the code for the Windows controls is within Windows, meaning you cannot edit the code. Although you cannot edit the code of the control itself, you intercept the messages sent to it, and handle them your self. You do so by subclassing the control. Subclassing involves replacing the Message Handlers of the control, and passing any unprocessed message to the controls Message Handler.

    SDK Subclassing

    Although the Message Procedure for the control is located within windows, you can retrieve a pointer to it by using the GetWindowLong function with the GWL_WNDPROC identifier. Likewise, you can call SetWindowLong and specify a new Window Procedure for the control. This process is called Subclassing, and allows you to hook into a window/control and intercept any message it gets. Subclassing is the Windows term for replacing the Window Procedure of a window with a different Window Procedure and calling the old Window Procedure for default (superclass) functionality. Remember DefWindowProc()? instead of calling DefWindowProc for default Message Handling you use the old Window Procedure as the default Message Handler.

    Implementing SDK Subclassing

    So, lets try to solve the classic question "How do I screen out characters from an edit control?", or "How do I create a letter-only edit control?"

    First lets analyze how an edit control works:

    An edit control is a window. It's window procedure lies within windows. Among other things, whenever it gets a WM_CHAR message it adds the character to the text it contains. Now that we know that, we can simply subclass the edit control, and intercept the WM_CHAR messages. Whenever the WM_CHAR message is a letter or a key like space bar or backspace we'll pass the message to the edit control. If it isn't one of the above, we'll just "Swallow" the message, blocking it from reaching the Edit Control.

    The first step to subclassing is to add a global/static WNDPROC variable that will store the address of the edit control's Window Procedure.

    WNDPROC g_OldEdit;

    The second step is to create a new Window Procedure for the edit control:

    LRESULT CALLBACK NewEditProc (HWND hwnd, UINT message, 
                                 WPARAM wParam, LPARAM lParam)
    {
              
    	TCHAR chCharCode;
    	switch (message)
    	{
    	case WM_CHAR:
    		chCharCode = (TCHAR) wParam;
    		if(chCharCode > 0x20 && !IsCharAlpha(chCharCode))
    			return 0;
    		break;
    	}
    	return CallWindowProc (g_OldEdit, hwnd, message, wParam, lParam);
    }

    The IsCharAlpha function determines whether a character is an alphabetic character. This determination is based on the semantics of the language selected by the user during setup or by using Control Panel.

    More interesting is the CallWindowProc function. The CallWindowProc function passes message information to the specified Window Procedure. A call to CallWindowProc will allow you to call the old Window Procedure with any message you receive, thus providing default message handling

    The third step is to replace the Window Procedure for the edit control, and to store the old one in g_OldEdit. For example, if you want to subclass an edit control that resides in a dialog (hDlg) and has the ID of IDC_EDIT1 you would use the following code:

    hwnd hWndEdit = GetDlgItem(hDlg, IDC_EDIT1);<BR>//Replace the Window Procedure and Store the Old Window Procedure
    g_OldEdit = (WNDPROC)SetWindowLong(hWndEdit, GWL_WNDPROC, (LONG)NewEditProc);
    

    The control is now subclassed. Any message to the edit control will first go through the NewEditProc Window Procedure, which will decide if the message should go to the edit control's Window Procedure .

    MFC Subclassing

    Subclassing in both MFC and SDK programs is done by replacing the message handlers of a control. It is rather easy to subclass in a MFC program. First you inherit your class from a class that encapsulates the functionality of a the control. In ClassWizard, click on "Add Class", then "New". For the base class, choose the MFC Control class you are deriving from, in our case, CEdit.

    Using MFC relieves you from having to call the old Message Handlers, since MFC will take care of it for you.
    The second step is to add Message Handlers to your new class. If you handle a message and you want the control's message handler to get a shot at it, you should call the base class member function the corresponds with the message. this is the subclassed WM_CHAR handler:

    void CLetterEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
    {
    	if(nChar <= 0x20 || IsCharAlpha((TCHAR)nChar))<BR>        {
              //Call base class member, which will call <BR>          //the control's message handler
    	      CEdit::OnChar(nChar, nRepCnt, nFlags);
    	      //If not, the message is blocked<BR>        }
    }

    The third and final stage is to associate the window with an instance of our new class. In a dialog this is done simply by using ClassWizard to create a control member variable of your class in the window's parent, and associate it with the control.

    In a non-dialog parent you should add a member variable instance of your control to it, and call one of the two CWnd Subclassing functions: CWnd::SubclassWindow or CWnd::SubclassDlgItem. Both routines attach a CWnd object to an existing Windows HWND. SubclassWindow takes the HWND directly, and SubclassDlgItem is a helper that takes a control ID and the parent window (usually a dialog). SubclassDlgItem is designed for attaching C++ objects to dialog controls created from a dialog template.

    Further Reading

    For a more in depth treatment of MFC subclassing see Chris Maunder's article: "Create your own controls - the art of subclassing".

    Reflected Messages - MFC 4.0+

    When you subclass a control, besides handling the message it receives, in MFC you can also handle the notifications it sends to it's parent window. This technique is called Message Reflecting. Windows controls often send notifications to their parents, for example, a Button will send a WM_COMMAND message telling it's parent it has been clicked. Usually it is the parent's job to handle these messages, but MFC will also allow you to handle them in the control itself. In ClassWizard these messages appear with an "=" sign before them, indicating they are Reflected Messages. You handle them just like any other message. The macros for these messages are similar to the regular messages, but have _REFLECT added to the end of the macro. For example, ON_NOTIFY() becomes ON_NOTIFY_REFLECT().

    Further Reading

    For a more in depth treatment of MFC reflected messages see the MFC technical notes:

    • TN014: Custom Controls
    • TN062: Message Reflection for Windows Controls
  • License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here

    Share

    About the Author

    Daniel Kopitchinski
    Web Developer
    Israel Israel
    No Biography provided

    You may also be interested in...

    Comments and Discussions

     
    QuestionNice explanation Pin
    ydramkumar20-Jan-12 6:22
    memberydramkumar20-Jan-12 6:22 
    GeneralMy vote of 5 Pin
    PrinceSinghMukul29-Nov-11 0:51
    memberPrinceSinghMukul29-Nov-11 0:51 
    QuestionDialog and Enter Button Pin
    zumba zumba22-Aug-08 4:11
    memberzumba zumba22-Aug-08 4:11 
    AnswerRe: Dialog and Enter Button Pin
    Paul Ong30-Aug-08 1:47
    memberPaul Ong30-Aug-08 1:47 
    QuestionHow can I put the subclass proc in one class? Pin
    neviton19-Sep-07 11:37
    memberneviton19-Sep-07 11:37 
    Generalgood Pin
    helehop13-Sep-07 17:51
    memberhelehop13-Sep-07 17:51 
    GeneralGOOD Pin
    wzh1983122112-Dec-06 3:41
    memberwzh1983122112-Dec-06 3:41 
    Questionhow to subclass a non MFC control Like Flash ActiveX control in a MFC dialoge? Pin
    haitham hamed housin9-Jun-06 11:47
    memberhaitham hamed housin9-Jun-06 11:47 
    Generalgood ,, and time consuming ... Pin
    yooooooooooooo5-Jun-06 21:54
    memberyooooooooooooo5-Jun-06 21:54 
    GeneralWM_MOUSEWHEEL in subclassed Pin
    mikepc25-Feb-06 8:01
    membermikepc25-Feb-06 8:01 
    GeneralFinding the name of the subclass Pin
    Alex Evans19-Feb-05 18:14
    memberAlex Evans19-Feb-05 18:14 
    GeneralNotify Messages Pin
    John Ulvr26-Nov-04 7:57
    memberJohn Ulvr26-Nov-04 7:57 
    Generalconsole app messaging ... Pin
    dharani6-Sep-04 3:08
    memberdharani6-Sep-04 3:08 
    QuestionHow to Dynamically subclass Controls in a dialog whose code i cannot change. Pin
    verinder_bindra18-May-04 10:19
    memberverinder_bindra18-May-04 10:19 
    GeneralGreat Article Pin
    ZeroEpoch17-May-04 8:11
    memberZeroEpoch17-May-04 8:11 
    Generalintercept the wm_char message Pin
    percyvimal21-Oct-03 22:07
    memberpercyvimal21-Oct-03 22:07 
    GeneralSubClassing CBitmapButton in SDK Pin
    Vikas Mishra21-Sep-03 21:59
    sussVikas Mishra21-Sep-03 21:59 
    GeneralGood explanation of Message reflection Pin
    Snakebyte9-Aug-03 8:19
    memberSnakebyte9-Aug-03 8:19 
    GeneralAdding controls to a CView Pin
    Dave_B20-Jul-03 17:36
    memberDave_B20-Jul-03 17:36 
    Questioncan u give this samples in c# Pin
    hejun28-Dec-02 1:04
    memberhejun28-Dec-02 1:04 
    Generalvery good Pin
    yary19-Dec-02 2:00
    memberyary19-Dec-02 2:00 
    GeneralGood articles Pin
    clio18-Jul-02 8:54
    memberclio18-Jul-02 8:54 
    Questionhow 2 link 2 dialoge in sdi Pin
    soso29-Apr-02 10:50
    membersoso29-Apr-02 10:50 
    AnswerRe: how 2 link 2 dialoge in sdi Pin
    V.Sen...9-Aug-07 2:41
    memberV.Sen...9-Aug-07 2:41 
    GeneralThis doesn't work Pin
    Anonymous13-Mar-02 11:26
    memberAnonymous13-Mar-02 11:26 
    GeneralRe: This doesn't work Pin
    OddArne11-Feb-03 10:32
    memberOddArne11-Feb-03 10:32 
    GeneralAccess to Browser in a hidden window. Pin
    Pat O'Neil2-Jan-02 12:55
    memberPat O'Neil2-Jan-02 12:55 
    GeneralWinHelp Pin
    pilso3-Dec-01 7:17
    memberpilso3-Dec-01 7:17 
    QuestionWhere do I have to put the code? Pin
    Valeria3-Dec-01 6:45
    memberValeria3-Dec-01 6:45 
    GeneralTwo comments on your article.. Pin
    Arno van Loenen29-Oct-01 5:28
    memberArno van Loenen29-Oct-01 5:28 
    GeneralRe: Two comments on your article.. Pin
    Anonymous15-Feb-02 3:59
    memberAnonymous15-Feb-02 3:59 
    GeneralSlight problem Pin
    Anonymous16-Oct-01 17:42
    memberAnonymous16-Oct-01 17:42 
    GeneralRe: Slight problem Pin
    dub17-Oct-01 4:32
    memberdub17-Oct-01 4:32 
    GeneralSubclassWindow is a macro and a CWnd method... Pin
    Doug Brower11-Apr-01 2:51
    memberDoug Brower11-Apr-01 2:51 
    GeneralRe: SubclassWindow is a macro and a CWnd method... Pin
    Anonymous19-Jun-01 23:39
    memberAnonymous19-Jun-01 23:39 
    GeneralMFC and SDK Pin
    Derek6-Sep-00 0:04
    sussDerek6-Sep-00 0:04 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

    | Advertise | Privacy | Terms of Use | Mobile
    Web04 | 2.8.150603.1 | Last Updated 26 Apr 2003
    Article Copyright 2000 by Daniel Kopitchinski
    Everything else Copyright © CodeProject, 1999-2015
    Layout: fixed | fluid