PageEntry.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. #ifndef __PageEntry_h__
  2. #define __PageEntry_h__
  3. /////////////////////////////////////////////////////////////////////////////
  4. // PageEntry.h | Declaration of the XInsidePageEntry and XInsidePage classes
  5. // used solely by the TCPropertyPageImpl class.
  6. //
  7. // Originally, I tried embedding these within the TCPropertyPageImpl class,
  8. // but since it is a template class, the compiler messages were to too
  9. // unbearable to read.
  10. //
  11. /////////////////////////////////////////////////////////////////////////////
  12. // XInsidePageEntry declares the format of one entry in a table of embedded
  13. // property pages. This structure is used soley by the TCPropertyPageBase
  14. // class. See the Embedded Property Page Table Macros for more information
  15. // about the purpose of each structure member.
  16. //
  17. // Originally, this structure was embedded within the TCPropertyPageImpl
  18. // class, but since it is a template class, the compiler messages were to too
  19. // unbearable to read.
  20. //
  21. // TODO: Now that the embedded property page features of TCPropertyPageImpl
  22. // have been moved into the non-template TCPropertyPageBase class, this
  23. // structure should perhaps be moved there.
  24. //
  25. // See Also: Embedded Property Page Table Macros, TCPropertyPageBase,
  26. // TCPropertyPageImpl
  27. struct XInsidePageEntry
  28. {
  29. UINT idPosCtrl; // {secret}
  30. const CLSID* pclsid; // {secret}
  31. DWORD dwData; // {secret}
  32. LPCTSTR pszText; // {secret}
  33. bool bVisible : 1; // {secret}
  34. bool bSizeToCtrl : 1; // {secret}
  35. bool bAlwaysApply : 1; // {secret}
  36. };
  37. /////////////////////////////////////////////////////////////////////////////
  38. // XInsidePage is a derivation of TCInsidePropPage that simply adds a pointer
  39. // to the table entry structure. This class is used solely by the
  40. // TCPropertyPageBase class.
  41. //
  42. // Originally, this class was embedded within the TCPropertyPageImpl class,
  43. // but since it is a template class, the compiler messages were to too
  44. // unbearable to read.
  45. //
  46. // TODO: Now that the embedded property page features of TCPropertyPageImpl
  47. // have been moved into the non-template TCPropertyPageBase class, this
  48. // class should perhaps be moved there.
  49. //
  50. // See Also: TCPropertyPageBase, TCPropertyPageImpl, TCInsidePropPage,
  51. // XInsidePageEntry, Embedded Property Page Table Macros
  52. class XInsidePage : public TCInsidePropPage
  53. {
  54. // Construction
  55. public:
  56. XInsidePage(const XInsidePageEntry* pEntry);
  57. // Group=Data Members
  58. public:
  59. // A pointer to the table entry used to create this property page.
  60. const XInsidePageEntry* m_pEntry;
  61. };
  62. /////////////////////////////////////////////////////////////////////////////
  63. // Group=Construction
  64. /////////////////////////////////////////////////////////////////////////////
  65. // {group:Construction}
  66. //
  67. // Constructs an instance of the object by copying the specified table entry
  68. // pointer.
  69. //
  70. // Parameters:
  71. // pEntry - A pointer to the table entry used to create this property page.
  72. //
  73. // See Also: XInsidePage::m_pEntry
  74. inline XInsidePage::XInsidePage(const XInsidePageEntry* pEntry)
  75. : m_pEntry(pEntry)
  76. {
  77. }
  78. /////////////////////////////////////////////////////////////////////////////
  79. // Group=
  80. /////////////////////////////////////////////////////////////////////////////
  81. // {tag:Embedded Property Page Table Macros}
  82. // Macro Group: Embedded Property Page Table Macros
  83. //
  84. // Declaration:
  85. // #define BEGIN_INSIDE_PAGE_MAP()
  86. // #define ALT_INSIDE_PAGE_MAP(pageMapID)
  87. // #define INSIDE_PAGE_ENTRY_EX(id, clsid, dw, bVis, bSize, bApply)
  88. // #define INSIDE_PAGE_ENTRY_EX_TEXT(id, clsid, dw, bVis, bSize, bApply, t)
  89. // #define INSIDE_PAGE_ENTRY_EX_STRID(id, clsid, dw, bVis, bSize, bApply, t)
  90. // #define INSIDE_PAGE_ENTRY(id, clsid, dw)
  91. // #define INSIDE_PAGE_ENTRY_TEXT(id, clsid, dw, t)
  92. // #define INSIDE_PAGE_ENTRY_STRID(id, clsid, dw, t)
  93. // #define INSIDE_PAGEGROUP_ENTRY(id, clsid, dw, bApply)
  94. // #define INSIDE_PAGEGROUP_ENTRY_TEXT(id, clsid, dw, t, bApply)
  95. // #define INSIDE_PAGEGROUP_ENTRY_STRID(id, clsid, dw, t, bApply)
  96. // #define END_INSIDE_PAGE_MAP()
  97. //
  98. // Parameters:
  99. // pageMapID - A non-zero identifier for the next section of the map. See
  100. // the remarks for how this would be used.
  101. // id - The child window identifier in the property page's main dialog that
  102. // represents the control used to position the embedded property page.
  103. // clsid - The *CLSID* of the embedded property page component object.
  104. // dw - A DWORD (32-bit) value to associate with the embedded property
  105. // page.
  106. // bVis - Specifies the embedded property page's initial visibility.
  107. // *true* to make the page initially visible, otherwise *false*.
  108. // bSize - When *true*, the embedded property page will be made the same
  109. // size as the control specified in /id/. Otherwise, *false* specifies that
  110. // the page will be the size indicated by its
  111. // *IPropertyPage::GetPageInfo* method.
  112. // bApply - When *true*, specifies that the embedded property page's
  113. // *IPropertyPage::Apply* method should be called whenever the outer page's
  114. // changes are applied, /even/ /if/ /no/ /changes/ /were/ /detected/ /in/ „
  115. // /the/ /embedded/ /page/. When *false*, the embedded property page's Apply
  116. // method will only be called when changes have been detected.
  117. // t - A text string to associate with the embedded property page.
  118. //
  119. // Remarks: These macros provide a simple mechanism for defining a map
  120. // (table) of property pages that are to be embedded within another property
  121. // page. Use these macros within the declaration of classes derived from
  122. // TCPropertyPageImpl.
  123. //
  124. // BEGIN_INSIDE_PAGE_MAP and END_INSIDE_PAGE_MAP define the beginning and end
  125. // of the table.
  126. //
  127. // The INSIDE_PAGE_ENTRY group of macros declare a single property page to be
  128. // embedded within the outer page. See the parameters for the variations.
  129. //
  130. // The INSIDE_PAGEGROUP_ENTRY macros declare a single property page
  131. // /within/ /a/ /mutually/ /exclusive/ /group/ of property pages that all
  132. // share the same position in the outer property page. This is useful, for
  133. // example, when some other control on the outer property page (such as a
  134. // combo box or group of radio buttons) manages the visibility of the pages
  135. // of this group, based on its current selection. When these macros are used,
  136. // the /id/ parameter is used to identify the positioning control and also
  137. // serves as the group's identifier.
  138. //
  139. // For both of the above sets of macros, the /dw/ and /t/ parameters may be
  140. // used for any application-defined purpose.
  141. //
  142. // The ALT_INSIDE_PAGE_MAP macro is used when more than one set of embedded
  143. // property pages needs to be defined. This macro is for advanced use only
  144. // and should not be used without a full understanding of its implementation.
  145. // This macro is not needed for most property pages.
  146. //
  147. // See Also: TCPropertyPageImpl, TCInsidePropPage::Create,
  148. // Property Page Field Update Macros
  149. #define Embedded_Property_Page_Table_Macros
  150. // {partof:Embedded_Property_Page_Table_Macros}
  151. #define BEGIN_INSIDE_PAGE_MAP() \
  152. public: \
  153. virtual UINT GetInsidePageTable(const XInsidePageEntry** ppTable, \
  154. UINT iTable) \
  155. { \
  156. switch (iTable) \
  157. { \
  158. case 0: \
  159. { \
  160. static const XInsidePageEntry table[] = \
  161. {
  162. // {partof:Embedded_Property_Page_Table_Macros}
  163. #define ALT_INSIDE_PAGE_MAP(pageMapID) \
  164. {0, NULL, 0, NULL, false, false, false} \
  165. }; \
  166. if (ppTable) \
  167. *ppTable = table; \
  168. return sizeofArray(table) - 1; \
  169. } \
  170. case pageMapID: \
  171. { \
  172. static const XInsidePageEntry table[] = \
  173. {
  174. // {partof:Embedded_Property_Page_Table_Macros}
  175. #define INSIDE_PAGE_ENTRY_EX(id, clsid, dw, bVis, bSize, bApply) \
  176. {id, &clsid, DWORD(dw), NULL, bVis, bSize, bApply},
  177. // {partof:Embedded_Property_Page_Table_Macros}
  178. #define INSIDE_PAGE_ENTRY_EX_TEXT(id, clsid, dw, bVis, bSize, bApply, t) \
  179. {id, &clsid, DWORD(dw), TEXT(t), bVis, bSize, bApply},
  180. // {partof:Embedded_Property_Page_Table_Macros}
  181. #define INSIDE_PAGE_ENTRY_EX_STRID(id, clsid, dw, bVis, bSize, bApply, t) \
  182. {id, &clsid, DWORD(dw), MAKEINTRESOURCE(t), bVis, bSize, bApply},
  183. // {partof:Embedded_Property_Page_Table_Macros}
  184. #define INSIDE_PAGE_ENTRY(id, clsid, dw) \
  185. INSIDE_PAGE_ENTRY_EX(id, clsid, dw, true, true, true)
  186. // {partof:Embedded_Property_Page_Table_Macros}
  187. #define INSIDE_PAGE_ENTRY_TEXT(id, clsid, dw, t) \
  188. INSIDE_PAGE_ENTRY_EX_TEXT(id, clsid, dw, t, true, true, true)
  189. // {partof:Embedded_Property_Page_Table_Macros}
  190. #define INSIDE_PAGE_ENTRY_STRID(id, clsid, dw, t) \
  191. INSIDE_PAGE_ENTRY_EX_STRID(id, clsid, dw, t, true, true, true)
  192. // {partof:Embedded_Property_Page_Table_Macros}
  193. #define INSIDE_PAGEGROUP_ENTRY(id, clsid, dw, bApply) \
  194. INSIDE_PAGE_ENTRY_EX(id, clsid, dw, false, true, bApply)
  195. // {partof:Embedded_Property_Page_Table_Macros}
  196. #define INSIDE_PAGEGROUP_ENTRY_TEXT(id, clsid, dw, t, bApply) \
  197. INSIDE_PAGE_ENTRY_EX_TEXT(id, clsid, dw, t, false, true, bApply)
  198. // {partof:Embedded_Property_Page_Table_Macros}
  199. #define INSIDE_PAGEGROUP_ENTRY_STRID(id, clsid, dw, t, bApply) \
  200. INSIDE_PAGE_ENTRY_EX_STRID(id, clsid, dw, t, false, true, bApply)
  201. // {partof:Embedded_Property_Page_Table_Macros}
  202. #define END_INSIDE_PAGE_MAP() \
  203. {0, NULL, 0, NULL, false, false, false} \
  204. }; \
  205. if (ppTable) \
  206. *ppTable = table; \
  207. return sizeofArray(table) - 1; \
  208. } \
  209. } \
  210. _TRACE1("Invalid inside property page map ID (%i)\n", iTable); \
  211. assert(FALSE); \
  212. if (ppTable) \
  213. *ppTable = NULL; \
  214. return 0; \
  215. }
  216. /////////////////////////////////////////////////////////////////////////////
  217. // {tag:Property Page Field Update Macros}
  218. // Macro Group: Property Page Field Update Macros
  219. //
  220. // Declaration:
  221. // #define BEGIN_PAGE_FIELD_MAP()
  222. // #define PAGE_FIELD_ENTRY_EX(idCtrl, dispid, iid, fnUpdate, fnApply)
  223. // #define PAGE_FIELD_ENTRY_EX_RO(idCtrl, dispid, iid, fnUpdate)
  224. // #define PAGE_FIELD_ENTRY(idCtrl, dispid, iid_name, fnName)
  225. // #define PAGE_FIELD_ENTRY_RO(idCtrl, dispid, iid_name, fnName)
  226. // #define PAGE_INTERFACE_ENTRY_OLD(iid_name)
  227. // #define PAGE_INTERFACE_ENTRY(iid_name, fnName)
  228. // #define PAGE_INTERFACE_ENTRY_RO(iid_name, fnName)
  229. // #define END_PAGE_FIELD_MAP()
  230. //
  231. // Parameters:
  232. // idCtrl - Identifier of a control on the property page used to display and/or
  233. // edit this field.
  234. // dispid - Dispatch identifier of this field.
  235. // iid - The *IID* (interface identifier) of the interface on which the
  236. // specified /dispid/ identifies this field.
  237. // iid_name - Same as /iid/, but without the *IID_* prefix.
  238. // fnUpdate - The name of the member function called to update the property
  239. // page child window(s) with the value of the field.
  240. // fnApply - The name of the member function called to apply the changes
  241. // made to the property page child windows(s) to the object.
  242. // fnName - The base name of the *Update* and *Apply* handler member
  243. // functions, as described in /fnUpdate/ and /fnApply/. This base name is
  244. // prefixed with *Apply* and *Update* to refer to the two functions.
  245. //
  246. // Remarks: These macros provide a simple mechanism for mapping the fields
  247. // (properties) of an interface to functions that update the user interface
  248. // with the field value and apply user interface changes to the field value.
  249. // Use these macros within the declaration of classes derived from
  250. // TCPropertyPageImpl.
  251. //
  252. // BEGIN_PAGE_FIELD_MAP and END_PAGE_FIELD_MAP define the beginning and end
  253. // of the table.
  254. //
  255. // The PAGE_FIELD_ENTRY macros associate a field with the functions used to
  256. // update the UI with the field value and apply the UI changes to the field
  257. // value. Although, the /idCtrl/ parameter is also associated with the field,
  258. // it currently does not get used by the base class.
  259. //
  260. // The *Update* and *Apply* handler member functions that you declare in your
  261. // class should be prototyped as follows:
  262. //
  263. // void UpdateProc(ULONG cObjects, IUnknown** ppunkObjects);
  264. // void ApplyProc(ULONG cObjects, IUnknown** ppunkObjects);
  265. //
  266. // Note: The macros that have *EX* in their names use the following
  267. // /extended/ function prototypes. Use these macros (and prototypes) when the
  268. // *Update* and *Apply* handlers need more information about which field is to
  269. // be updated or applied.
  270. //
  271. // void UpdateProcEx(UINT id, DISPID dispid, REFIID riid,
  272. // ULONG cObjects, IUnknown** ppunkObject);
  273. // void ApplyProcEx(UINT id, DISPID dispid, REFIID riid,
  274. // ULONG cObjects, IUnknown** ppunkObject);
  275. //
  276. // Although the normal and extended prototypes shown above specify arrays of
  277. // *IUnknown* pointers, the pointers have already been QI'd for the IID
  278. // specified in the /iid/ or /iid_name/ parameter. So, the *Update* and
  279. // *Apply* handlers need not *QueryInterface* them again. Instead, your
  280. // prototypes should specify an array of the /actual/ interface name pointers,
  281. // as in the following example:
  282. //
  283. // // Property Page Field Map
  284. // public:
  285. // BEGIN_PAGE_FIELD_MAP()
  286. // PAGE_FIELD_ENTRY(IDC_AllowIt, DISPID_AllowIt, IMyFace, AllowIt)
  287. // END_PAGE_FIELD_MAP()
  288. // …
  289. // // Property Field Exchange
  290. // protected:
  291. // void UpdateAllowIt(ULONG cObjects, IMyFace** ppObjects);
  292. // void ApplyAllowIt(ULONG cObjects, IMyFace** ppObjects);
  293. //
  294. // In most property pages, the *Update* and *Apply* handlers should be the
  295. // only place in code that either initializes (Update) or saves (Apply)
  296. // property values. This is supported in the TCPropertyPageImpl base class.
  297. // For example, when the property page is about to first become visible, the
  298. // base class handles the *WM_INITDIALOG* message by calling the
  299. // *Update* handler for each field entry in the map. It also does this when
  300. // the *IPropertyPage::SetObjects* method is called, once the page is already
  301. // visible. This allows the code that connects an object property to a user
  302. // interface element to only be coded in one place.
  303. //
  304. // Note: This mechanism also gets reused if the object being edited by the
  305. // property page supports the *IPropertyNotifySink* connection point. For
  306. // such objects, when notification of a property change is received, the
  307. // *Update* method is called to reflect the change in the user interface.
  308. //
  309. // TODO: The intention of this design may not fully be realized. For example,
  310. // the *Update* and *Apply* handlers should not need to be concerned with
  311. // exception handling. The base class should handle exceptions at its level.
  312. // This may be in place now, but it should be reviewed to ensure that
  313. // exceptions are being handled in such a way.
  314. //
  315. // The PAGE_INTERFACE_ENTRY macros represent a carry-over from the original
  316. // implementation of the TCPropertyPageImpl base class, which was
  317. // /interface/ based rather than /field/ based. New code should (probably)
  318. // not use these macros. Use the PAGE_FIELD_ENTRY macros instead.
  319. //
  320. // All the macro variants that end with *RO* should be used when a field is
  321. // /read-only/. This simplifies programming by not having to declare and
  322. // implement an *Apply* handler that does nothing.
  323. //
  324. // See Also: TCPropertyPageImpl, Embedded Property Page Table Macros
  325. #define Property_Page_Field_Update_Macros
  326. // {partof:Property_Page_Field_Update_Macros}
  327. #define BEGIN_PAGE_FIELD_MAP() \
  328. public: \
  329. UINT GetPageFieldTable(const XPageFieldEntry** ppTable) \
  330. { \
  331. static const XPageFieldEntry table[] = \
  332. {
  333. // {partof:Property_Page_Field_Update_Macros}
  334. #define PAGE_FIELD_ENTRY_EX(id, dispid, iid, fnUpdate, fnApply) \
  335. {id, dispid, &iid, NULL, NULL, fnUpdate, fnApply},
  336. // {partof:Property_Page_Field_Update_Macros}
  337. #define PAGE_FIELD_ENTRY_EX_RO(id, dispid, iid, fnUpdate) \
  338. {id, dispid, &iid, NULL, NULL, fnUpdate, NULL},
  339. // {partof:Property_Page_Field_Update_Macros}
  340. #define PAGE_FIELD_ENTRY(id, dispid, iid_name, name) \
  341. {id, dispid, &IID_##iid_name, XFieldUpdateProc(Update##name), \
  342. XFieldApplyProc(Apply##name), NULL, NULL},
  343. // {partof:Property_Page_Field_Update_Macros}
  344. #define PAGE_FIELD_ENTRY_RO(id, dispid, iid_name, name) \
  345. {id, dispid, &IID_##iid_name, XFieldUpdateProc(Update##name), NULL, \
  346. NULL, NULL},
  347. // {partof:Property_Page_Field_Update_Macros}
  348. #define PAGE_INTERFACE_ENTRY_OLD(iid_name) \
  349. {0, 0, &IID_##iid_name, NULL, NULL, NULL, NULL},
  350. // {partof:Property_Page_Field_Update_Macros}
  351. #define PAGE_INTERFACE_ENTRY(iid_name, name) \
  352. {0, 0, &IID_##iid_name, XFieldUpdateProc(Update##name), \
  353. XFieldApplyProc(Apply##name), NULL, NULL},
  354. // {partof:Property_Page_Field_Update_Macros}
  355. #define PAGE_INTERFACE_ENTRY_RO(iid_name, name) \
  356. {0, 0, &IID_##iid_name, XFieldUpdateProc(Update##name), NULL},
  357. // {partof:Property_Page_Field_Update_Macros}
  358. #define END_PAGE_FIELD_MAP() \
  359. {0, 0, NULL, NULL, NULL} \
  360. }; \
  361. if (ppTable) \
  362. *ppTable = table; \
  363. return sizeofArray(table) - 1; \
  364. }
  365. /////////////////////////////////////////////////////////////////////////////
  366. #endif // !__PageEntry_h__