It is well known that the common controls classes have to be registered using the InitCommonControlsEx() function before using any of those controls in a Win32 application. (Ofcourse, in WindowsXp this is not required if a manifest file is used).
According to the MSDN documentation, the effect of each call to InitCommonControlsEx() is cumulative. That is, if InitCommonControlsEx() is called with the ICC_UPDOWN_CLASS flag, then is later called with the ICC_HOTKEY_CLASS flag, the result is that both the up-down and hot key common control classes are registered and available to the application.
Having said that, one of the problems custom control designers always face is - "how do we guarantee that InitCommonControlsEx() is called before our custom control is used?"
Obviously, we cannot hope the user of our control to take care of it because he/she may not be aware of which class of controls are required and are to be registered for our custom control. The following class CInitCommonControls comes handy in such situations. Using this class is pretty simple and straightforward in that all one has to do is just declare the CInitCommonControls as a baseclass for the custom control class, as shown below.
Usage:class CPropertyGrid : CInitCommonControls<ICC_LISTVIEW_CLASSES> { public: DECLARE_WND_CLASS_EX(NULL, CS_DBLCLKS, COLOR_WINDOW) ///... };
The class CInitCommonControls is a templated class that accepts a DWORD as the template argument. The value of this template argument would be used in the dwICC field of INITCOMMONCONTROLSEX structure in the call to InitCommonControlsEx(). Thus the value of this template argument could be any combination of ICC_ANIMATE_CLASS, ICC_TAB_CLASSES etc. values defined in the documentation. More than one value could be combined using the bitwise OR operator | as CInitCommonControls <ICC_TREEVIEW_CLASSES | ICC_DATE_CLASSES>.
The class can be placed in a header file, say InitCommonControls.h (available for download as InitCommonControls_h.zip), and can be included in any application. The contents of InitCommonControls.h file are as shown below.
#ifndef __INITCOMMONCONTROLS_H__83716747_6B45_4c0a_8B18_81C4751EA455_ #define __INITCOMMONCONTROLS_H__83716747_6B45_4c0a_8B18_81C4751EA455_ #include <commctrl.h> #pragma comment(lib, "comctl32.lib") /// <Summary> /// Helper Class to ensure the initialization of Common Controls Library. /// Add this as a Base Class for Your Control Class to Initialize the Common Control Library Automatically. /// /// Since this Class uses a local static variable in the constructor for the Library Initialization, /// the InitCommonControlsEx() is called only once per App for all the derived class objects. /// /// Being a base class - this guarantees that the library is initialized before any derived class /// functions are invoked. /// /// In case your control has multiple base classes, try to make the CInitCommonControls as the /// first base class followed by the others. This ensures that InitCommonControlsEx() is called /// before any other dependent functions in other base classes are invoked. /// </Summary> /// /// <remarks> /// Usage: /// /// class MyControlClass: CInitCommonControls<ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES> /// { /// //... /// } /// </remarks> template <DWORD dwICC = ICC_WIN95_CLASSES> class CInitCommonControls { protected: /// Protected Constructor inline CInitCommonControls(void) { /// /// Helper Structure to Call the InitCommonControlsEx() function /// static struct _tagInitCommonControls { _tagInitCommonControls() { INITCOMMONCONTROLSEX icce; icce.dwSize = sizeof(INITCOMMONCONTROLSEX); icce.dwICC = dwICC; // Use the Template Argument for the Library Initialization InitCommonControlsEx(&icce); } } DummyInitCommonControls; // Static Local Variable Gets initialized only once (for the first Object) } /// Protected Destructor inline ~CInitCommonControls() { } }; #endif
Please note that in case of multiple base classes, it is a good idea to make the CInitCommonControls as the first base class followed by the others. This is to make sure that InitCommonControlsEx() is called before any other dependent functions in other base classes are invoked.