Setting Extended Styles of Controls, Dialogs, Dialog Bars, and Property Pages at Runtime

The Problem

If you want to have the fancy extended styles for controls and dialogs for applications that run under Windows 95 or Windows NT 4 the VC resource editor creates a DIALOGEX resource instead of a DIALOG resource for you. But there are several reasons why you would not want a DIALOGEX resource and where you would instead want to change the extended style bits at runtime from code:

  1. You might be targetting a Win16 and a Win32 based variant of your application that uses one single .rc file. The Win16 resource compiler cannot compile resource scripts with DIALOGEX resources.
  2. You might want to use the Platform SDK’s DlgEdit tool that cannot deal with dialogs or controls that have extended style bits.
  3. You might be targetting Win32s and you want to use a single binary for Win32s, Windows 95 and Windows NT. Unforunately, Win32s cannot handle DIALOGEX templates so you simply would want to set the extended style bits at runtime after having detected that the underlying Win32 platform is not Win32s.
  4. You simply want to change the extended style bits at runtime in certain situations for some reason.

You might be asking: “Why not use ModifyStyleEx in the dialogs WM_INITDIALOG handler?”. The answer is, that ModifyStyleEx does not work well with all extended style bits. It does so for example with WS_EX_APPWINDOW, WS_EX_CONTEXTHELP or WS_EX_CONTROLPARENT but not with WS_EX_CLIENTEDGE, WS_EX_STATICEDGE or WS_EX_DLGMODALFRAME.

The Solution

I have written three classes (CBaseDialog, CBaseBar, CBasePage) that derive directly from CDialog, CDialogBar and CPropertyPage. CBaseDialog and CBaseDialogBar automatically detect if they are going to be used with a DIALOGEX template and if so, make a copy of that template in global memory. If they are going to be used with a DIALOG template these classes create a DIALOGEX template in global memory that is built from the DIALOG template. With this DIALOGEX template at hand these classes can easily manipulate the extended style bits of the dialog and its controls in memory by use of the member functions

void SetControlExtendedStyle(int, DWORD); //Sets a control’s
//extended style bits
void RemoveControlExtendedStyle(int, DWORD); //Removes a control’s
//extended style bits

void SetExtendedStyles(DWORD dwExStyle); //Sets the dialog’s
//extended style bits
void RemoveExtendedStyles(DWORD dwExStyle); //Removes the dialog’s
//extended style bits

prior to the call to the DoModal or Create member functions.

CBasePage has the same member functions but works differently: Because CPropertyPage cannot deal with DIALOGEX resources anyway (MFC will ASSERT if you do so), CBasePage is making a copy of its associated DIALOG template in global memory and modifies the extended styles in this copy before the page is created by its property sheet. Note that this will only work on Windows NT 4. Windows 95 will not reflect the changes you make in a DIALOG template (that’s why I choose to convert the DIALOG template to a DIALOGEX template for the CBaseDialog and CBaseBar classes – to make it work on Windows 95, too). But an application running on Windows 95 will still benefit from this: On older versions of the comctl32.dll you get a first-chance-exception when using a standard property page because there is no write access to the resource it is using unless you explicitly advise the linker to create a writable resources section. This can be harmful if you protect the creation of a property page by exception handling code. With CBasePage this will not be a problem since the global memory this class uses is writable.

The behaviour of all classes on Win32s is that of their base classes: They will simply bypass all that code that creates copies of the dialog resources in memory and instead use the standard dialog creation functions MFC provides. Thus, you can take the executable that is contained in the sample zip file and run it successfully on Win32s, Windows 9x, Windows NT 3.51 and Windows NT 4.0.

How to Use the Classes

The files needed to use the three classes are: basebar.cpp,basebar.h, basedlg.cpp,basedlg.h, basepage.cpp,basepage.h, dialext.cpp,dialext.h. Simply derive your own classes from these classes and change the extended style bits before you call the classes’ Create or DoModal member function (in the case of the CBasePage class, before you call the property sheet’s DoModal member function). A good place to do so is typically the derived classes’ constructors. If you want to get detailed TRACE output for the conversion of DIALOG templates to DIALOGEX templates you can set the preprocessor DESCRIPTIVE in file dialext.cpp to 1, but note that this will slow down debugging dramatically.

Last updated: 02 August 1998, Reposted to Site July 23, 2004 by author’s request

For download, unzip with directory preservation. When using VC 4.x rename extstyle.vc4 to extstyle.mak.

More by Author

Must Read