Subclassing Dialogs and Property Pages

Home
Back To Tips Page

One of the limits of the ClassWizard is its inability to handle various useful forms of subclassing. In particular, it does not intrinsically allow you to subclass from a subclass, or specify a subclassed subclass as a variable. For example, I have a class called CSmartDropdown which does dynamic resizing of combo boxes. I have a subclass CIDCombo which is a subclass of CSmartDropdown which handles the issues of combo box initialization in a better fashion than the resources.

The two classes CIDCombo and CSmartDropdown were merged in the CIDCombo class I publish on my Web site.

In fact, I often work with a CGraphicsCombo class which is a subclass of CIDCombo, but supports owner-draw bitmap images, or CColorCombo which is a subclass of CGraphicsCombo that displays some selected colors. So I often work several levels of derivation down, and the ClassWizard makes this inconvenient.

But if you want to subclass a dialog or property page, it gets even worse. Consider the case where you have a combo box which appears on every property page, or on every dialog, and a few buttons that have the same behavior. It seems silly to create a set of independent dialogs that handle this, yet there is no support in ClassWizard that helps you.

Fortunately, it is not hard to change this. You just have to know the Magic Incantations. Here they be!

First, create a dialog with the common controls that are shared by all the subclasses you plan to create. This dialog will not actually be used (although it could be, I'm not that ambitious here...), but it is used to create all the handlers. You will find in the .h file a declaration of the constructor:

CMyDialog(CWnd * parent = NULL);

Change this to read

CMyDialog(CWnd * parent = NULL) { ASSERT(FALSE); } // never create!

Add a new constructor:

CMyDialog(UINT id, CWnd * parent = NULL);

Go into the .cpp file and modify the constructor code. It reads

CMyDialog::CMyDialog(CWnd * parent /* = NULL */)
        : CDialog(CMyDialog::IDD, parent)
    {
     ...
    }

Change this to read

CMyDialog::CMyDialog(UINT id, CWnd * parent /* = NULL */)
        : CDialog(id, parent)
    {
     ...
    }

Now when you create a new dialog which is a subclass, just create the dialog as you normally would. Now comes the tedious part that ClassWizard should have done for you (send email to the Microsoft Wish site if you think ClassWizard should support this!)

Go into the .h file for your new class and change all instances of CDialog to CMyDialog

Go into the .cpp file for your new class and change all instances of CDialog to CMyDialog

That's it. You're done. When you create a subclassed dialog, you still have to copy the common controls from your master dialog template into the child dialogs (note that Microsoft could have made this easy, by simply inheriting the controls during dialog construction; a subclassed dialog would open the resource of each enclosing parent and include all the controls from that class into the current dialog, which is fairly trivial to implement). 

You can do exactly the same technique to subclass a CPropertyPage-derived class.

[Dividing Line Image]

The views expressed in these essays are those of the author, and in no way represent, nor are they endorsed by, Microsoft.

Send mail to newcomer@flounder.com with questions or comments about this web site.
Copyright 2000, The Joseph M. Newcomer Co. All Rights Reserved.
Last modified: May 14, 2011