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:

Subclassing in SDK programs,

Subclassing in MFC programs,

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:

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:

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:

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

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.

Hi All
I have created MFC dialog application. When I press enter, application is terminated. Application should NOT be closed when I press enter. How can I fix this thing?
I will be looking for your response.
Thanks

I try to put the subclass procedure inside one class but this give me two problems:
1 - Declaring the subclass procedure as static I cant access the class members.
2 - Declaring the subclass procedure as non-static I cant pass the subclass procedure to the Win32 SetWindowLong function.

I have read your four articals carefully
I am very happy that I can read this kind of articals
I learn many things about the message
message handler ;user_message define; subclassing.........
Thank you very much

I have a controll subclassed from a STATIC, whever I step through the code in a debug session – MSVC 6.0 / The IDE “Knows the name of my derived class, but calling GetClassName or GetRunTimeClass returns the base class, NOT the one I am after – is there a way for me to test for it programatically?

I have a dialog class, which I want to have notify its parent when the user selects a different item. I thought I would use the WM_NOTIFY message, but I can't seem to figure out how to define a unique code for it... What should I use to define a unique notify code (can I just use WM_APP + x??)

I am trying to send my own message and parse it from within my console application in vc++ . But its not work ing .. my code is below
UINT CONN = RegisterWindowMessage(TEXT("CONNECT"));
HWND GetConsoleHWND();

How can i subclass a dialog button controls which is in a 3rd party dll. All i want is replace the buttons in dialog from standard CButton to My versions of buttons which are derived from CButtons. Also I want to change the Bkg color of Text/Dialog in the dialog.

i have to hook the keyboard and get keydown event and which key is pressed and then intercept the wm_char message which is generated for that keydown event and change that particular character and translate that to my own character and that character is an extended ascii character.
Sir i have designed a font file and i included lot of new characters in the font file to accomadate more characters which Tamil language have.I can easily manage to access the 52 characeters in A_Z and a-z using normal keyboard ,but i have included 200 characters .I am not using unicode for i am not using opentype font but only true type font.the remaining characters are in other ascii range .Is it possibe to display them by changing the wm_char message.?
if so how is it possible ?
Do anybody know how to hook the message and intercept keyboard messages and change the character system wide.
The problem i have is i have to intercept all key events and track the wm_char message generated by that keydown event and send to any application which is having the current focus.
For example if a user is typing in word and if he selects my font then he should be able to type in that or if he chose notepad or photoshop then he should be able to type in that application and using my application they should be able to get access to those extended ascii characters.

I have an app with a CView-derived class used for other purposes (call it MyCView), and I want to provide another MyCView-derived class which hosts a Windows control (eg a grid control). All works fine in a CFormView, but can't really use that in my app. So the question is - how do you add a control to a regular CView?

I set up a sample MFC Wizard generated app, and added code to the OnInitialUpdate.
I've seen similar things in articles and eventually tried this...

where m_TheListCtrl is just a regular CListCtrl.
The problem is that it ASSERTs in CWnd::SubclassWindow with this TRACE message...

Error: Trying to use SubclassWindow with incorrect CWnd derived class.
hWnd = $30ABE (nIDC=$0082) is not a CListCtrl.

Can anyone tell me what the correct procedure is for Subclassing a control and hooking it up in a CView rather than a CFormView? Is the above on the right track? Can I then just add the DDX etc support?

I saw a programm calling WinHelp with HELP_CONTEXTMENU and a pointer to a list of ID-Pairs. One ID for the Control and the other for the help to this control. For the OK and Cancel Button there were no ID' s in this list and nevertheless some help popups. Maybe they are definde by the System. But where does the WinHelp function get them from?

Dealing with SDK:
Where do I have to put the LRESULT CALLBACK procedure? And where the SetWindowLong call?
The context:
I'm working on a IE toolbar developed with http://www.codeproject.com/atl/ietoolbartutorial.asp the as a template.
I'd like to subclass the deskband object (in the project called "StockBar") in order to (try) to manage a chevron notification message. Is it possible in the way you showed for the edit control?
Do I have to put the code inside the StockBar class?
Thanks in advance.

Two comments though:
1) It might be handy to identify the projects in Visual Studio related to the MFC / SDK variants for newcomers : the SDK variant is obtained by a 'Win32 Application' the other by the 'MFC appwizard (exe)'

2)
Quote: The need for subclassing comes from the fact that the code for the Windows controls is within Windows, meaning you cannot edit the code.

Correction:
The need for subclassing comes from the desire to reuse existing classes, only changing / extending them where necessary, saving you a lot of implementation headaches . The 'base' class really deserves it existence being a good default for several different subclasses ! Even if you had the source code of a base class, modifying it directly would be no good, since this of course prevents usefull subclassing into other subclasses later on (your modified class would be too specialized !).

As an interesting side note: you _do_ have the source code of MFC available btw if you installed Visual Studio ! Just look in your Visual Studio folders. I would only recommend using them for demystifying MFC though.

D:\projects\db(166) : error C2440: 'type cast' : cannot convert from 'long (__stdcall CVLBinaryBotDlg::*)(struct HWND__ *,unsigned int,unsigned int,long)' to 'long'
Conversion is a valid standard conversion, which can be performed implicitly or by use of static_cast, C-style cast or function-style cast

this will stop the compiler going into windowsx.h
and get rid of that error. It was a pain for me as I wanted to use WFC in a
particular project and that error kept saying not enough actual parameters to
macro.