123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- #ifndef __PageEntry_h__
- #define __PageEntry_h__
- /////////////////////////////////////////////////////////////////////////////
- // PageEntry.h | Declaration of the XInsidePageEntry and XInsidePage classes
- // used solely by the TCPropertyPageImpl class.
- //
- // Originally, I tried embedding these within the TCPropertyPageImpl class,
- // but since it is a template class, the compiler messages were to too
- // unbearable to read.
- //
- /////////////////////////////////////////////////////////////////////////////
- // XInsidePageEntry declares the format of one entry in a table of embedded
- // property pages. This structure is used soley by the TCPropertyPageBase
- // class. See the Embedded Property Page Table Macros for more information
- // about the purpose of each structure member.
- //
- // Originally, this structure was embedded within the TCPropertyPageImpl
- // class, but since it is a template class, the compiler messages were to too
- // unbearable to read.
- //
- // TODO: Now that the embedded property page features of TCPropertyPageImpl
- // have been moved into the non-template TCPropertyPageBase class, this
- // structure should perhaps be moved there.
- //
- // See Also: Embedded Property Page Table Macros, TCPropertyPageBase,
- // TCPropertyPageImpl
- struct XInsidePageEntry
- {
- UINT idPosCtrl; // {secret}
- const CLSID* pclsid; // {secret}
- DWORD dwData; // {secret}
- LPCTSTR pszText; // {secret}
- bool bVisible : 1; // {secret}
- bool bSizeToCtrl : 1; // {secret}
- bool bAlwaysApply : 1; // {secret}
- };
- /////////////////////////////////////////////////////////////////////////////
- // XInsidePage is a derivation of TCInsidePropPage that simply adds a pointer
- // to the table entry structure. This class is used solely by the
- // TCPropertyPageBase class.
- //
- // Originally, this class was embedded within the TCPropertyPageImpl class,
- // but since it is a template class, the compiler messages were to too
- // unbearable to read.
- //
- // TODO: Now that the embedded property page features of TCPropertyPageImpl
- // have been moved into the non-template TCPropertyPageBase class, this
- // class should perhaps be moved there.
- //
- // See Also: TCPropertyPageBase, TCPropertyPageImpl, TCInsidePropPage,
- // XInsidePageEntry, Embedded Property Page Table Macros
- class XInsidePage : public TCInsidePropPage
- {
- // Construction
- public:
- XInsidePage(const XInsidePageEntry* pEntry);
- // Group=Data Members
- public:
- // A pointer to the table entry used to create this property page.
- const XInsidePageEntry* m_pEntry;
- };
- /////////////////////////////////////////////////////////////////////////////
- // Group=Construction
- /////////////////////////////////////////////////////////////////////////////
- // {group:Construction}
- //
- // Constructs an instance of the object by copying the specified table entry
- // pointer.
- //
- // Parameters:
- // pEntry - A pointer to the table entry used to create this property page.
- //
- // See Also: XInsidePage::m_pEntry
- inline XInsidePage::XInsidePage(const XInsidePageEntry* pEntry)
- : m_pEntry(pEntry)
- {
- }
- /////////////////////////////////////////////////////////////////////////////
- // Group=
- /////////////////////////////////////////////////////////////////////////////
- // {tag:Embedded Property Page Table Macros}
- // Macro Group: Embedded Property Page Table Macros
- //
- // Declaration:
- // #define BEGIN_INSIDE_PAGE_MAP()
- // #define ALT_INSIDE_PAGE_MAP(pageMapID)
- // #define INSIDE_PAGE_ENTRY_EX(id, clsid, dw, bVis, bSize, bApply)
- // #define INSIDE_PAGE_ENTRY_EX_TEXT(id, clsid, dw, bVis, bSize, bApply, t)
- // #define INSIDE_PAGE_ENTRY_EX_STRID(id, clsid, dw, bVis, bSize, bApply, t)
- // #define INSIDE_PAGE_ENTRY(id, clsid, dw)
- // #define INSIDE_PAGE_ENTRY_TEXT(id, clsid, dw, t)
- // #define INSIDE_PAGE_ENTRY_STRID(id, clsid, dw, t)
- // #define INSIDE_PAGEGROUP_ENTRY(id, clsid, dw, bApply)
- // #define INSIDE_PAGEGROUP_ENTRY_TEXT(id, clsid, dw, t, bApply)
- // #define INSIDE_PAGEGROUP_ENTRY_STRID(id, clsid, dw, t, bApply)
- // #define END_INSIDE_PAGE_MAP()
- //
- // Parameters:
- // pageMapID - A non-zero identifier for the next section of the map. See
- // the remarks for how this would be used.
- // id - The child window identifier in the property page's main dialog that
- // represents the control used to position the embedded property page.
- // clsid - The *CLSID* of the embedded property page component object.
- // dw - A DWORD (32-bit) value to associate with the embedded property
- // page.
- // bVis - Specifies the embedded property page's initial visibility.
- // *true* to make the page initially visible, otherwise *false*.
- // bSize - When *true*, the embedded property page will be made the same
- // size as the control specified in /id/. Otherwise, *false* specifies that
- // the page will be the size indicated by its
- // *IPropertyPage::GetPageInfo* method.
- // bApply - When *true*, specifies that the embedded property page's
- // *IPropertyPage::Apply* method should be called whenever the outer page's
- // changes are applied, /even/ /if/ /no/ /changes/ /were/ /detected/ /in/ „
- // /the/ /embedded/ /page/. When *false*, the embedded property page's Apply
- // method will only be called when changes have been detected.
- // t - A text string to associate with the embedded property page.
- //
- // Remarks: These macros provide a simple mechanism for defining a map
- // (table) of property pages that are to be embedded within another property
- // page. Use these macros within the declaration of classes derived from
- // TCPropertyPageImpl.
- //
- // BEGIN_INSIDE_PAGE_MAP and END_INSIDE_PAGE_MAP define the beginning and end
- // of the table.
- //
- // The INSIDE_PAGE_ENTRY group of macros declare a single property page to be
- // embedded within the outer page. See the parameters for the variations.
- //
- // The INSIDE_PAGEGROUP_ENTRY macros declare a single property page
- // /within/ /a/ /mutually/ /exclusive/ /group/ of property pages that all
- // share the same position in the outer property page. This is useful, for
- // example, when some other control on the outer property page (such as a
- // combo box or group of radio buttons) manages the visibility of the pages
- // of this group, based on its current selection. When these macros are used,
- // the /id/ parameter is used to identify the positioning control and also
- // serves as the group's identifier.
- //
- // For both of the above sets of macros, the /dw/ and /t/ parameters may be
- // used for any application-defined purpose.
- //
- // The ALT_INSIDE_PAGE_MAP macro is used when more than one set of embedded
- // property pages needs to be defined. This macro is for advanced use only
- // and should not be used without a full understanding of its implementation.
- // This macro is not needed for most property pages.
- //
- // See Also: TCPropertyPageImpl, TCInsidePropPage::Create,
- // Property Page Field Update Macros
- #define Embedded_Property_Page_Table_Macros
- // {partof:Embedded_Property_Page_Table_Macros}
- #define BEGIN_INSIDE_PAGE_MAP() \
- public: \
- virtual UINT GetInsidePageTable(const XInsidePageEntry** ppTable, \
- UINT iTable) \
- { \
- switch (iTable) \
- { \
- case 0: \
- { \
- static const XInsidePageEntry table[] = \
- {
- // {partof:Embedded_Property_Page_Table_Macros}
- #define ALT_INSIDE_PAGE_MAP(pageMapID) \
- {0, NULL, 0, NULL, false, false, false} \
- }; \
- if (ppTable) \
- *ppTable = table; \
- return sizeofArray(table) - 1; \
- } \
- case pageMapID: \
- { \
- static const XInsidePageEntry table[] = \
- {
- // {partof:Embedded_Property_Page_Table_Macros}
- #define INSIDE_PAGE_ENTRY_EX(id, clsid, dw, bVis, bSize, bApply) \
- {id, &clsid, DWORD(dw), NULL, bVis, bSize, bApply},
- // {partof:Embedded_Property_Page_Table_Macros}
- #define INSIDE_PAGE_ENTRY_EX_TEXT(id, clsid, dw, bVis, bSize, bApply, t) \
- {id, &clsid, DWORD(dw), TEXT(t), bVis, bSize, bApply},
- // {partof:Embedded_Property_Page_Table_Macros}
- #define INSIDE_PAGE_ENTRY_EX_STRID(id, clsid, dw, bVis, bSize, bApply, t) \
- {id, &clsid, DWORD(dw), MAKEINTRESOURCE(t), bVis, bSize, bApply},
- // {partof:Embedded_Property_Page_Table_Macros}
- #define INSIDE_PAGE_ENTRY(id, clsid, dw) \
- INSIDE_PAGE_ENTRY_EX(id, clsid, dw, true, true, true)
- // {partof:Embedded_Property_Page_Table_Macros}
- #define INSIDE_PAGE_ENTRY_TEXT(id, clsid, dw, t) \
- INSIDE_PAGE_ENTRY_EX_TEXT(id, clsid, dw, t, true, true, true)
- // {partof:Embedded_Property_Page_Table_Macros}
- #define INSIDE_PAGE_ENTRY_STRID(id, clsid, dw, t) \
- INSIDE_PAGE_ENTRY_EX_STRID(id, clsid, dw, t, true, true, true)
- // {partof:Embedded_Property_Page_Table_Macros}
- #define INSIDE_PAGEGROUP_ENTRY(id, clsid, dw, bApply) \
- INSIDE_PAGE_ENTRY_EX(id, clsid, dw, false, true, bApply)
- // {partof:Embedded_Property_Page_Table_Macros}
- #define INSIDE_PAGEGROUP_ENTRY_TEXT(id, clsid, dw, t, bApply) \
- INSIDE_PAGE_ENTRY_EX_TEXT(id, clsid, dw, t, false, true, bApply)
- // {partof:Embedded_Property_Page_Table_Macros}
- #define INSIDE_PAGEGROUP_ENTRY_STRID(id, clsid, dw, t, bApply) \
- INSIDE_PAGE_ENTRY_EX_STRID(id, clsid, dw, t, false, true, bApply)
- // {partof:Embedded_Property_Page_Table_Macros}
- #define END_INSIDE_PAGE_MAP() \
- {0, NULL, 0, NULL, false, false, false} \
- }; \
- if (ppTable) \
- *ppTable = table; \
- return sizeofArray(table) - 1; \
- } \
- } \
- _TRACE1("Invalid inside property page map ID (%i)\n", iTable); \
- assert(FALSE); \
- if (ppTable) \
- *ppTable = NULL; \
- return 0; \
- }
- /////////////////////////////////////////////////////////////////////////////
- // {tag:Property Page Field Update Macros}
- // Macro Group: Property Page Field Update Macros
- //
- // Declaration:
- // #define BEGIN_PAGE_FIELD_MAP()
- // #define PAGE_FIELD_ENTRY_EX(idCtrl, dispid, iid, fnUpdate, fnApply)
- // #define PAGE_FIELD_ENTRY_EX_RO(idCtrl, dispid, iid, fnUpdate)
- // #define PAGE_FIELD_ENTRY(idCtrl, dispid, iid_name, fnName)
- // #define PAGE_FIELD_ENTRY_RO(idCtrl, dispid, iid_name, fnName)
- // #define PAGE_INTERFACE_ENTRY_OLD(iid_name)
- // #define PAGE_INTERFACE_ENTRY(iid_name, fnName)
- // #define PAGE_INTERFACE_ENTRY_RO(iid_name, fnName)
- // #define END_PAGE_FIELD_MAP()
- //
- // Parameters:
- // idCtrl - Identifier of a control on the property page used to display and/or
- // edit this field.
- // dispid - Dispatch identifier of this field.
- // iid - The *IID* (interface identifier) of the interface on which the
- // specified /dispid/ identifies this field.
- // iid_name - Same as /iid/, but without the *IID_* prefix.
- // fnUpdate - The name of the member function called to update the property
- // page child window(s) with the value of the field.
- // fnApply - The name of the member function called to apply the changes
- // made to the property page child windows(s) to the object.
- // fnName - The base name of the *Update* and *Apply* handler member
- // functions, as described in /fnUpdate/ and /fnApply/. This base name is
- // prefixed with *Apply* and *Update* to refer to the two functions.
- //
- // Remarks: These macros provide a simple mechanism for mapping the fields
- // (properties) of an interface to functions that update the user interface
- // with the field value and apply user interface changes to the field value.
- // Use these macros within the declaration of classes derived from
- // TCPropertyPageImpl.
- //
- // BEGIN_PAGE_FIELD_MAP and END_PAGE_FIELD_MAP define the beginning and end
- // of the table.
- //
- // The PAGE_FIELD_ENTRY macros associate a field with the functions used to
- // update the UI with the field value and apply the UI changes to the field
- // value. Although, the /idCtrl/ parameter is also associated with the field,
- // it currently does not get used by the base class.
- //
- // The *Update* and *Apply* handler member functions that you declare in your
- // class should be prototyped as follows:
- //
- // void UpdateProc(ULONG cObjects, IUnknown** ppunkObjects);
- // void ApplyProc(ULONG cObjects, IUnknown** ppunkObjects);
- //
- // Note: The macros that have *EX* in their names use the following
- // /extended/ function prototypes. Use these macros (and prototypes) when the
- // *Update* and *Apply* handlers need more information about which field is to
- // be updated or applied.
- //
- // void UpdateProcEx(UINT id, DISPID dispid, REFIID riid,
- // ULONG cObjects, IUnknown** ppunkObject);
- // void ApplyProcEx(UINT id, DISPID dispid, REFIID riid,
- // ULONG cObjects, IUnknown** ppunkObject);
- //
- // Although the normal and extended prototypes shown above specify arrays of
- // *IUnknown* pointers, the pointers have already been QI'd for the IID
- // specified in the /iid/ or /iid_name/ parameter. So, the *Update* and
- // *Apply* handlers need not *QueryInterface* them again. Instead, your
- // prototypes should specify an array of the /actual/ interface name pointers,
- // as in the following example:
- //
- // // Property Page Field Map
- // public:
- // BEGIN_PAGE_FIELD_MAP()
- // PAGE_FIELD_ENTRY(IDC_AllowIt, DISPID_AllowIt, IMyFace, AllowIt)
- // END_PAGE_FIELD_MAP()
- // …
- // // Property Field Exchange
- // protected:
- // void UpdateAllowIt(ULONG cObjects, IMyFace** ppObjects);
- // void ApplyAllowIt(ULONG cObjects, IMyFace** ppObjects);
- //
- // In most property pages, the *Update* and *Apply* handlers should be the
- // only place in code that either initializes (Update) or saves (Apply)
- // property values. This is supported in the TCPropertyPageImpl base class.
- // For example, when the property page is about to first become visible, the
- // base class handles the *WM_INITDIALOG* message by calling the
- // *Update* handler for each field entry in the map. It also does this when
- // the *IPropertyPage::SetObjects* method is called, once the page is already
- // visible. This allows the code that connects an object property to a user
- // interface element to only be coded in one place.
- //
- // Note: This mechanism also gets reused if the object being edited by the
- // property page supports the *IPropertyNotifySink* connection point. For
- // such objects, when notification of a property change is received, the
- // *Update* method is called to reflect the change in the user interface.
- //
- // TODO: The intention of this design may not fully be realized. For example,
- // the *Update* and *Apply* handlers should not need to be concerned with
- // exception handling. The base class should handle exceptions at its level.
- // This may be in place now, but it should be reviewed to ensure that
- // exceptions are being handled in such a way.
- //
- // The PAGE_INTERFACE_ENTRY macros represent a carry-over from the original
- // implementation of the TCPropertyPageImpl base class, which was
- // /interface/ based rather than /field/ based. New code should (probably)
- // not use these macros. Use the PAGE_FIELD_ENTRY macros instead.
- //
- // All the macro variants that end with *RO* should be used when a field is
- // /read-only/. This simplifies programming by not having to declare and
- // implement an *Apply* handler that does nothing.
- //
- // See Also: TCPropertyPageImpl, Embedded Property Page Table Macros
- #define Property_Page_Field_Update_Macros
- // {partof:Property_Page_Field_Update_Macros}
- #define BEGIN_PAGE_FIELD_MAP() \
- public: \
- UINT GetPageFieldTable(const XPageFieldEntry** ppTable) \
- { \
- static const XPageFieldEntry table[] = \
- {
- // {partof:Property_Page_Field_Update_Macros}
- #define PAGE_FIELD_ENTRY_EX(id, dispid, iid, fnUpdate, fnApply) \
- {id, dispid, &iid, NULL, NULL, fnUpdate, fnApply},
- // {partof:Property_Page_Field_Update_Macros}
- #define PAGE_FIELD_ENTRY_EX_RO(id, dispid, iid, fnUpdate) \
- {id, dispid, &iid, NULL, NULL, fnUpdate, NULL},
- // {partof:Property_Page_Field_Update_Macros}
- #define PAGE_FIELD_ENTRY(id, dispid, iid_name, name) \
- {id, dispid, &IID_##iid_name, XFieldUpdateProc(Update##name), \
- XFieldApplyProc(Apply##name), NULL, NULL},
- // {partof:Property_Page_Field_Update_Macros}
- #define PAGE_FIELD_ENTRY_RO(id, dispid, iid_name, name) \
- {id, dispid, &IID_##iid_name, XFieldUpdateProc(Update##name), NULL, \
- NULL, NULL},
- // {partof:Property_Page_Field_Update_Macros}
- #define PAGE_INTERFACE_ENTRY_OLD(iid_name) \
- {0, 0, &IID_##iid_name, NULL, NULL, NULL, NULL},
- // {partof:Property_Page_Field_Update_Macros}
- #define PAGE_INTERFACE_ENTRY(iid_name, name) \
- {0, 0, &IID_##iid_name, XFieldUpdateProc(Update##name), \
- XFieldApplyProc(Apply##name), NULL, NULL},
- // {partof:Property_Page_Field_Update_Macros}
- #define PAGE_INTERFACE_ENTRY_RO(iid_name, name) \
- {0, 0, &IID_##iid_name, XFieldUpdateProc(Update##name), NULL},
- // {partof:Property_Page_Field_Update_Macros}
- #define END_PAGE_FIELD_MAP() \
- {0, 0, NULL, NULL, NULL} \
- }; \
- if (ppTable) \
- *ppTable = table; \
- return sizeofArray(table) - 1; \
- }
- /////////////////////////////////////////////////////////////////////////////
- #endif // !__PageEntry_h__
|