ATL s Property Page Classes

[Previous] [Next]

Visual Studio provides a wizard for creating property pages in your ATL project. To create a property page, just select New ATL Object from the Insert menu in Visual C++. The ATL Object Wizard generates a C++ class for you that implements the functions and interfaces necessary for the class to behave as a property page. In addition to generating a C++ class that implements the correct property page interfaces, the ATL Object Wizard makes the property page class part of the project, adding it to the IDL file within the coclass section. The Object Wizard also adds the property page to the object map so that DllGetClassObject can find the property page classes. Finally, the Object Wizard adds a new Registry script (so that the DLL makes the correct Registry entries when the control is registered).

ATL's property page classes are composed of several ATL templates: CComObjectRootEx (to implement IUnknown), CComCoClass (the class object for the property page), IPropertyPageImpl (for implementing IPropertyPage), and CDialogImpl (for implementing the dialog box-specific behavior).

ATL's property pages are relatively simple beasts. They really only implement one interface—IPropertyPage. The following code shows the IPropertyPage interface:

 interface IPropertyPage : public IUnknown {     HRESULT SetPageSite(IPropertyPageSite *pPageSite) = 0;     HRESULT Activate(HWND hWndParent,         LPCRECT pRect,         BOOL bModal) = 0;     HRESULT Deactivate( void) = 0;     HRESULT GetPageInfo(PROPPAGEINFO *pPageInfo) = 0;     HRESULT SetObjects(ULONG cObjects,         IUnknown **ppUnk) = 0;     HRESULT Show(UINT nCmdShow) = 0;     HRESULT Move(LPCRECT pRect) = 0;     HRESULT IsPageDirty( void) = 0;     HRESULT Apply( void) = 0;     HRESULT Help(LPCOLESTR pszHelpDir) = 0;     HRESULT TranslateAccelerator(MSG *pMsg) = 0; }; 

Client code uses this interface to manage the property page. For example, if the property page lives inside the frame created by OleCreatePropertyFrame, the property frame uses the interface to perform operations such as applying the new properties when the property frame's Apply button is pushed.

ATL and the Properties Verb

Let's examine how ATL implements the properties verb. A control shows its property pages in response to the client issuing the properties verb, which it does by calling IOleObject::DoVerb using the number defined by OLEIVERB_PROPERTIES. After the client asks the control to show its property dialog box through IOleObject::DoVerb, control ends up in CComControlBase:: DoVerbProperties, which simply calls OleCreatePropertyFrame, passing in its own IUnknown pointer and the list of property page GUIDs. OleCreatePropertyFrame takes the list of GUIDs, calling CoCreateInstance on each one to create the property pages and arrange them within the dialog frame. OleCreatePropertyFrame uses each property page's IPropertyPage interface to manage the property page.

ATL Property Maps

Understanding how OleCreatePropertyFrame works begs the next question—where does the list of property pages come from? ATL generates lists of property pages through its property maps, which are macros that help manage property pages. Whenever you add a new property page to an ATL-based control, you need to set up the list of property pages through these macros. Five macros implement property pages: BEGIN_PROPERTY_MAP, PROP_PAGE, PROP_ENTRY, PROP_ENTRY_EX, and END_PROPERTY_MAP. These macros are shown here:

 struct ATL_PROPMAP_ENTRY {     LPCOLESTR szDesc;     DISPID dispid;     const CLSID* pclsidPropPage;     const IID* piidDispatch; }; #define BEGIN_PROPERTY_MAP(theClass) \     typedef _ATL_PROP_NOTIFY_EVENT_CLASS \     _ _ATL_PROP_NOTIFY_EVENT_CLASS; \     static ATL_PROPMAP_ENTRY* GetPropertyMap()\     {\         static ATL_PROPMAP_ENTRY pPropMap[] = \         { #define PROP_PAGE(clsid) \             {NULL, NULL, &clsid, &IID_NULL}, #define PROP_ENTRY(szDesc, dispid, clsid) \             {OLESTR(szDesc), dispid, &clsid, &IID_IDispatch}, #define PROP_ENTRY_EX(szDesc, dispid, clsid, iidDispatch) \             {OLESTR(szDesc), dispid, &clsid, &iidDispatch}, #define END_PROPERTY_MAP() \             {NULL, 0, NULL, &IID_NULL} \         }; \         return pPropMap; \     } 

When you decide to add property pages to a COM class using ATL's property map macros, the ATL documentation tells you to put the macros into your class's header file. For example, the following code adds property pages to the CATLMsgTrafficCtl class and associates the various properties with the pages:

 class CATLMsgTrafficCtl :      // Inheritance list  {          BEGIN_PROP_MAP(CATLMsgTrafficCtl)         PROP_ENTRY("BackColor", DISPID_BACKCOLOR, CLSID_StockColorPage)         PROP_ENTRY("GraphLineColor", 4, CLSID_StockColorPage)         PROP_DATA_ENTRY("_cx",, VT_UI4)         PROP_DATA_ENTRY("_cy",, VT_UI4)         PROP_ENTRY("Interval", 3, CLSID_MainPropPage)         PROP_PAGE(CLSID_StockColorPage)     END_PROP_MAP()      }; 

ATL's property map macros set up the list of GUIDs representing property pages. Remember that property pages are just COM objects. Notice that the code above shows a structure named ATL_PROPMAP_ENTRY and that BEGIN_PROPERTY_MAP declares a static variable of this structure. The PROP_PAGE macro simply inserts a GUID into the list of property pages. PROP_ENTRY inserts a property page GUID into the list and associates a specific control property with the property page. The final macro, PROP_ENTRY_EX, lets you associate a certain dual interface to a property page.

Now let's see how ATL's property pages work with tools such as Visual Basic and Visual C++.

Inside Atl
Inside ATL (Programming Languages/C)
ISBN: 1572318589
EAN: 2147483647
Year: 1998
Pages: 127 © 2008-2017.
If you may any questions please contact us: