Click here to Skip to main content
15,868,292 members
Articles / Desktop Programming / MFC
Article

Double Subclassing (Runtime Form Editor)

Rate me:
Please Sign up or sign in to vote.
4.83/5 (18 votes)
21 May 20034 min read 90K   1.4K   44   18
An article that describes a way to subclass controls that are already subclassed (double), The example includes a runtime form editor

Introduction

This article explains how a to subclass already subclassed controls. It includes a simple Runtime form editor.

Image 1

Image 2

Introduction

I had a project in the company I work in that needed different forms for different customers, so the team decided to create a runtime form editor that can enable editing the forms for each customer. In order to do that I needed a way to control all the Controls on a formview or on a dialog; enabling me to resize the controls, move them, or hide them. I wanted to subclass the Controls on a dialog/formview in order to control them, however the major problem was that most controls were already subclassed. I wrote a class (CDblSubclassWnd) that can subclass controls even if they are already subclassed.

Explanation

The way it works is, the messages first go into a function called PreWndProc and then they continue to the original WndProc of the Control, and after it finishes from there it goes into a function called PostWndProc.

Image 3

The class is simple to use. The demo in the article contains a very simple form editor that allows you to simply move the controls on the form while you are in edit mode. Using the class is very simple. You have three methods of the class CDblSubclassWnd that you will work with. All methods are static

  • The first thing to do is give to the class two pointers to functions, that the CDblSubclassWnd class will call to pass by the messages of the subclassed controls.

    The method signature is:

    static void SetDblSubclassWndProc(
                    DBLSUBCLASS_WNDPROC *pPREPointer = NULL, 
                    DBLSUBCLASS_WNDPROC *pPOSTPointer = NULL
                );
    The first parameter would be a pointer to the function (PreWndProc) that will be called prior to passing on the message to the main WndProc of the control (or another Proc if it is subclassed). This function would give you the option of changing messages before they reach their control. The second parameter would be a pointer to the function that will be called after the control processed the message (PostWndProc) You can use this to inspect the values changed (or returned) by the Control.

    The DBLSUBCLASS_WNDPROC function pointer is defined as such:

    typedef LRESULT CALLBACK DBLSUBCLASS_WNDPROC(
                                 CWnd*,
                                 HWND,
                                 UINT,
                                 WPARAM,
                                 LPARAM,
                                 bool &
                             );

    The first parameter is a pointer to the Control Window class that the current message belongs to. The second parameter is the Handle to the Window. The third parameter (UINT) is the Message Number itself, and the following two parameters (WPARAM, LPARAM) are the two parameters that are passed with every Window Message, their meaning depend on the actual message. The last parameter (a reference to a bool) is used to indicate whether you want the DblSubclassed Engine to discontinue routing the message and return the return value returned by one of your two functions (

    pPREPointer, 
    pPOSTPointer
    ). To explain this point more by an example, if you have a button and you clicked on this button, the clicking message BN_CLICKED would first go to the PRE function pointer you assigned, if you do not want this message to continue to the WndProc of the control, you can stop this by setting the the boolean (last parameter to the function DBLSUBCLASS_WNDPROC) to false, this way the message will be dropped and will not reach the control.

  • Now that you have your PreWndProc and PostWndProc set, it is time to actually call the methods to subclass the Controls.
    void CDblSubclassWnd::SubclassChildsRecurs(
                  HWND hWnd, 
                  DBLSUBCLASS_RECURSIVECALLBACKPROC *pFunc
              )
    You call this method giving it (for example) the handle to the dialog you are working in. The function will traverse all the Controls on the dialog and for each control will call the function pointed to by the second parameter of the function, DBLSUBCLASS_RECURSIVECALLBACKPROC. This function will be called by the engine for each control that is going to be subclassed, its job is to decide whether the control is to be subclassed or not.

    For example, if you want to subclass all the Buttons on your dialog and not all the controls, in your RecursiveCallBack function, you would test for the control for being a button or not (control's class) and you would return true only for the button controls. The RecursiveCallBack simply takes a HWND parameter (to do your testing on the control) and returns a boolean value to indicate whether to subclass the specified control or not.

  • After you subclass the controls the messages will start flowing into your PRE and POST WindowProc assigned in the call to SetDblSubclassWndProc (in the first step). When you want to end this effect, then you unsubclass the doubly subclassed controls by using UnSubclassChildsRecurs. Its use is straight forward, you give it the Handle to the main window (the dialog in our example) and it will go through the Controls belonging to it and unsubclass all the Controls that were subclassed before.

I hope you will find this article useful to you.

History

Date Posted: May 22, 2003

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


Written By
Technical Lead
Lebanon Lebanon
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionResizing Pin
xJorDyx6-May-08 8:51
xJorDyx6-May-08 8:51 
Generalsubclassing an MFC instance Pin
ivan françois11-Apr-06 3:33
ivan françois11-Apr-06 3:33 
GeneralRe: subclassing an MFC instance Pin
Ralph Varjabedian11-Apr-06 3:44
Ralph Varjabedian11-Apr-06 3:44 
GeneralRe: subclassing an MFC instance Pin
ivan françois11-Apr-06 6:10
ivan françois11-Apr-06 6:10 
You are right.
You have to enter into the target process.
To do it my preferred way is to set up a global hook.

THEN you are allowed to subclass.

In fact, what I am not able to do is to get the WM_MOUSEMOVE messages of Acrobat Reader.
I am definitely able to subclass the HWNDs of Acrobat.

Actually, after a few investigations, I don't know if this problem is related to MFC. I would say this problem is specific to Acrobat.

Ivan
GeneralThe name of the subclass Pin
Alex Evans19-Feb-05 18:17
Alex Evans19-Feb-05 18:17 
Generalstyle change @ Runtime Pin
Member 87460425-Jun-04 8:02
Member 87460425-Jun-04 8:02 
QuestionHow to resize Pin
THilker31-Jul-03 21:37
THilker31-Jul-03 21:37 
QuestionHow about a VC++ 6.0 sample? Pin
WREY2-Jun-03 6:45
WREY2-Jun-03 6:45 
AnswerRe: How about a VC++ 6.0 sample? Pin
Ralph Varjabedian2-Jun-03 6:49
Ralph Varjabedian2-Jun-03 6:49 
GeneralGroupBox Pin
RaidenIlias26-May-03 2:33
RaidenIlias26-May-03 2:33 
GeneralRe: GroupBox Pin
Ralph Varjabedian26-May-03 8:32
Ralph Varjabedian26-May-03 8:32 
GeneralRe: GroupBox Pin
Synetech31-May-05 17:02
Synetech31-May-05 17:02 
GeneralRe: GroupBox Pin
Lewandowski21-Dec-11 1:27
Lewandowski21-Dec-11 1:27 
GeneralExcellent! Pin
TW22-May-03 23:00
TW22-May-03 23:00 
GeneralRe: Excellent! Pin
Ralph Varjabedian23-May-03 7:56
Ralph Varjabedian23-May-03 7:56 
GeneralRe: Excellent! Pin
TW26-Jun-03 0:34
TW26-Jun-03 0:34 
GeneralFYI Pin
Todd C. Wilson22-May-03 16:33
Todd C. Wilson22-May-03 16:33 
GeneralRe: FYI Pin
Ralph Varjabedian23-May-03 7:54
Ralph Varjabedian23-May-03 7:54 

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

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