PropertyPageImpl.h 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316
  1. #ifndef __PropertyPageImpl_h_
  2. #define __PropertyPageImpl_h_
  3. /////////////////////////////////////////////////////////////////////////////
  4. // PropertyPageImpl.h | Declaration of the TCPropertyPageImpl class.
  5. #pragma warning(disable: 4786)
  6. #include <vector>
  7. #include <map>
  8. #include <set>
  9. #include <comdef.h>
  10. #include <typeinfo.h>
  11. #include "..\TCLib\AdviseHolder.h"
  12. #include "InsidePropPage.h"
  13. #include "PageEntry.h"
  14. /////////////////////////////////////////////////////////////////////////////
  15. // UI Helper Functions
  16. /////////////////////////////////////////////////////////////////////////////
  17. // Description: Converts a boolean expression to a check box state constant.
  18. //
  19. // Converts the specified boolean expression to a check box state constant.
  20. //
  21. // Parameters:
  22. // bExp - An expression of any type, to be evaluated as a boolean
  23. // expression.
  24. //
  25. // Return Value: *BST_CHECKED* if the /bExp/ is non-zero, otherwise
  26. // *BST_UNCHECKED*.
  27. //
  28. // See Also: Checked_false, VARIANT_TRUE_Checked, VARIANT_TRUE_Unchecked
  29. template <class T>
  30. inline UINT Checked_true(T bExp)
  31. {
  32. return bExp ? BST_CHECKED : BST_UNCHECKED;
  33. }
  34. /////////////////////////////////////////////////////////////////////////////
  35. // Description: Converts a boolean expression to a check box state constant.
  36. //
  37. // Converts the specified boolean expression to a check box state constant.
  38. //
  39. // Parameters:
  40. // bExp - An expression of any type, to be evaluated as a boolean
  41. // expression.
  42. //
  43. // Return Value: *BST_UNCHECKED* if the /bExp/ is non-zero, otherwise
  44. // *BST_CHECKED*.
  45. //
  46. // See Also: Checked_true, VARIANT_TRUE_Checked, VARIANT_TRUE_Unchecked
  47. template <class T>
  48. inline UINT Checked_false(T bExp)
  49. {
  50. return Checked_true(!bExp);
  51. }
  52. /////////////////////////////////////////////////////////////////////////////
  53. // Description: Converts a check box state constant to a *VARIANT_BOOL*.
  54. //
  55. // Converts the specified check box state constant to a *VARIANT_BOOL*.
  56. //
  57. // Parameters:
  58. // nCheck - A check box state constant, *BST_CHECKED* or *BST_UNCHECKED*.
  59. //
  60. // Return Value: *VARIANT_TRUE* if /nCheck/ is equal to *BST_CHECKED*,
  61. // otherwise, *VARIANT_FALSE*.
  62. //
  63. // See Also: VARIANT_TRUE_Unchecked, Checked_true, Checked_false
  64. inline VARIANT_BOOL VARIANT_TRUE_Checked(UINT nCheck)
  65. {
  66. return (nCheck == BST_CHECKED) ? VARIANT_TRUE : VARIANT_FALSE;
  67. }
  68. /////////////////////////////////////////////////////////////////////////////
  69. // Description: Converts a check box state constant to a *VARIANT_BOOL*.
  70. //
  71. // Converts the specified check box state constant to a *VARIANT_BOOL*.
  72. //
  73. // Parameters:
  74. // nCheck - A check box state constant, *BST_CHECKED* or *BST_UNCHECKED*.
  75. //
  76. // Return Value: *VARIANT_TRUE* if /nCheck/ is equal to *BST_UNCHECKED*,
  77. // otherwise, *VARIANT_FALSE*.
  78. //
  79. // See Also: VARIANT_TRUE_Checked, Checked_true, Checked_false
  80. inline VARIANT_BOOL VARIANT_TRUE_Unchecked(UINT nCheck)
  81. {
  82. return (nCheck == BST_UNCHECKED) ? VARIANT_TRUE : VARIANT_FALSE;
  83. }
  84. /////////////////////////////////////////////////////////////////////////////
  85. // Description: Interface map entries to be included in the interface map of
  86. // derived classes.
  87. //
  88. // See Also: TCPropertyPageImpl, CHAIN_MSG_MAP_TCPropertyPageImpl
  89. #define COM_INTERFACE_ENTRIES_TCPropertyPageImpl() \
  90. COM_INTERFACE_ENTRY_IMPL(IPropertyPage) \
  91. COM_INTERFACE_ENTRY(IPropertyPageSite) \
  92. COM_INTERFACE_ENTRY(ITCPropertyFieldToggle) \
  93. COM_INTERFACE_ENTRY(IPropertyNotifySink)
  94. /////////////////////////////////////////////////////////////////////////////
  95. // Description: Message map entries to be included in the message map of
  96. // derived classes.
  97. //
  98. // See Also: TCPropertyPageImpl, COM_INTERFACE_ENTRIES_TCPropertyPageImpl
  99. #define CHAIN_MSG_MAP_TCPropertyPageImpl() \
  100. CHAIN_MSG_MAP(TCPropertyPageImplBase)
  101. /////////////////////////////////////////////////////////////////////////////
  102. // TCPropertyPageImpl provides a consistent implementation of the
  103. // *IPropertyPage* interface. This class extends the ATL
  104. // *IPropertyPageImpl* class and should be used in place of it.
  105. //
  106. // Microsoft first created the *IPropertyPage* interface for use with
  107. // ActiveX Controls (formerly known as OLE Controls or OCX's). Since then,
  108. // the interface has proven to be effective in other scenarios, such as
  109. // Microsoft's DirectShow (formerly known as ActiveMovie), and are also an
  110. // important part of the MMAC Codec Driver Model.
  111. //
  112. // After developing an assortment of property pages, it becomes clear that
  113. // each one has many things in common with all of the others. To simplify
  114. // the creation of these, the TCPropertyPageImpl template class is designed
  115. // to take care of the many common chores of a property page implementation.
  116. // In addition, the class provides a solid framework for the embedding of
  117. // property pages within other pages. This helps to reduce rendundant coding
  118. // and to increase user interface reusability.
  119. //
  120. // For more information on how to use this class, see the documentation for
  121. // the Property Page Field Update Macros and the Embedded Property Page Table
  122. // Macros. Also, the ATL documentation for the *IPropertyPageImpl* class,
  123. // from which this class is derived, may be helpful. Of course, analysis of
  124. // sample code, along with this reference documentation, will prove to be the
  125. // best guide.
  126. //
  127. // TODO: This class should also implement the *IPropertyPage2* interface,
  128. // which adds the *EditProperty* method to specify which field is to receive
  129. // the focus when the property page is activated. This could easily be
  130. // implemented from the information already contained in the entries of the
  131. // property field map.
  132. //
  133. // Parameters:
  134. // T - Your property page class, derived from TCPropertyPageImpl.
  135. //
  136. // See Also: TCPropertyPageBase, Property Page Field Update Macros,
  137. // Embedded Property Page Table Macros
  138. #include <CodecDriver.h>
  139. template <class T>
  140. class ATL_NO_VTABLE TCPropertyPageImpl :
  141. public IPropertyPageImpl<T>,
  142. public IPropertyPageSite,
  143. public IPropertyNotifySink,
  144. public CDialogImpl<T>,
  145. public TCPropertyPageBase,
  146. public IDispatchImpl<ITCPropertyFieldToggle, &IID_ITCPropertyFieldToggle, &LIBID_TCCodecDriver>
  147. {
  148. // Group=Types
  149. public:
  150. typedef TCPropertyPageImpl<T> TCPropertyPageImplBase;
  151. typedef TCPropertyPageImpl<T> Type;
  152. typedef void (Type::*XFieldUpdateProc)(ULONG, IUnknown**);
  153. typedef void (Type::*XFieldApplyProc)(ULONG, IUnknown**);
  154. typedef void (Type::*XFieldUpdateProcEx)(UINT, DISPID, REFIID, ULONG, IUnknown**);
  155. typedef void (Type::*XFieldApplyProcEx)(UINT, DISPID, REFIID, ULONG, IUnknown**);
  156. ///////////////////////////////////////////////////////////////////////////
  157. // Description: Declares the entry in a table of property page fields.
  158. struct XPageFieldEntry
  159. {
  160. UINT idCtrl; // {secret}
  161. DISPID dispid; // {secret}
  162. const IID* piid; // {secret}
  163. XFieldUpdateProc pfnUpdate; // {secret}
  164. XFieldApplyProc pfnApply; // {secret}
  165. XFieldUpdateProcEx pfnUpdateEx; // {secret}
  166. XFieldApplyProcEx pfnApplyEx; // {secret}
  167. };
  168. // Group=Enumerations
  169. public:
  170. // Private window message definitions
  171. enum EMessages
  172. {
  173. wm_OnChanged = WM_APP, // Message sent when a property changes.
  174. };
  175. // Message Map
  176. public:
  177. BEGIN_MSG_MAP(TCPropertyPageImpl<T>)
  178. MESSAGE_HANDLER(wm_OnChanged, OnChangedHandler)
  179. MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialogHandler)
  180. MESSAGE_HANDLER(WM_NCDESTROY, OnNcDestroyHandler)
  181. // Base class message handling
  182. CHAIN_MSG_MAP(IPropertyPageImpl<T>)
  183. END_MSG_MAP()
  184. // Group=Construction / Destruction
  185. public:
  186. TCPropertyPageImpl();
  187. virtual ~TCPropertyPageImpl();
  188. // Group=Attributes
  189. public:
  190. void SetDirty(BOOL bDirty);
  191. void SetDirtyNoApply();
  192. // Group=Diagnostic Overrides
  193. protected:
  194. #ifdef _DEBUG
  195. virtual LPCSTR TypeName()
  196. {
  197. return TCTypeName(T);
  198. }
  199. #endif
  200. // Group=Overrides
  201. protected:
  202. virtual HWND GetPageWindow();
  203. virtual IUnknown* GetPageUnknown();
  204. virtual bool IsObjectKnown(IUnknown* punk);
  205. virtual void UpdateFields(DISPID dispid = DISPID_UNKNOWN);
  206. public:
  207. HWND Create(HWND hWndParent);
  208. void OnApplyFields();
  209. bool OnUpdateFields(DISPID dispid = DISPID_UNKNOWN);
  210. UINT GetPageFieldTable(const XPageFieldEntry** ppTable);
  211. // Group=Message Handlers
  212. public:
  213. LRESULT OnSetDirty(WORD, WORD, HWND, BOOL& bHandled);
  214. LRESULT OnSetDirtyNoApply(WORD, WORD, HWND, BOOL& bHandled);
  215. LRESULT OnInitDialogHandler(UINT, WPARAM, LPARAM, BOOL&);
  216. // Group=IPropertyPage Interface Methods
  217. public:
  218. STDMETHODIMP GetPageInfo(PROPPAGEINFO *pPageInfo);
  219. STDMETHODIMP SetObjects(ULONG cObjects, IUnknown** ppUnk);
  220. STDMETHODIMP Apply();
  221. STDMETHODIMP Help(LPCOLESTR pszHelpDir);
  222. // Group=IPropertyPageSite Interface Methods
  223. public:
  224. STDMETHODIMP OnStatusChange(DWORD dwFlags);
  225. STDMETHODIMP GetLocaleID(LCID* pLocaleID);
  226. STDMETHODIMP GetPageContainer(IUnknown** ppUnk);
  227. STDMETHODIMP TranslateAccelerator(MSG* pMsg);
  228. // Group=IPropertyNotifySink Interface Methods
  229. public:
  230. STDMETHODIMP OnChanged(DISPID dispID);
  231. STDMETHODIMP OnRequestEdit(DISPID dispID);
  232. // Group=ITCPropertyFieldToggle Interface Methods
  233. public:
  234. STDMETHODIMP put_EnableField(DISPID dispid, VARIANT_BOOL bEnable);
  235. STDMETHODIMP get_EnableField(DISPID dispid, VARIANT_BOOL* pbEnable);
  236. STDMETHODIMP put_ShowField(DISPID dispid, VARIANT_BOOL bShow);
  237. STDMETHODIMP get_ShowField(DISPID dispid, VARIANT_BOOL* pbShow);
  238. // Group=Helpers
  239. protected:
  240. void FieldToggle(DISPID dispid, bool bEnableDisable, bool bToggle);
  241. bool GetFieldToggle(DISPID dispid, bool bEnableDisable);
  242. // Group=Enumerations
  243. public:
  244. enum {IDD};
  245. // Group=Data Members
  246. public:
  247. WORD m_IDD;
  248. };
  249. /////////////////////////////////////////////////////////////////////////////
  250. // Group=Construction / Destruction
  251. /////////////////////////////////////////////////////////////////////////////
  252. template <class T>
  253. TCPropertyPageImpl<T>::TCPropertyPageImpl() :
  254. m_IDD(T::IDD)
  255. {
  256. _TRACE1("TCPropertyPageImpl<%hs>::TCPropertyPageImpl()\n", TCTypeName(T));
  257. // Get the derived class pointer
  258. T* pThis = static_cast<T*>(this);
  259. // Get the table of supported interfaces
  260. const XPageFieldEntry* pTable = NULL;
  261. UINT nEntries = pThis->GetPageFieldTable(&pTable);
  262. // Initialize the map of supported interfaces
  263. for (UINT i = 0; i < nEntries; ++i)
  264. {
  265. CUnkVectorMap::value_type value(*pTable[i].piid, CUnkVector());
  266. m_mapInterfaces.insert(value);
  267. }
  268. }
  269. /////////////////////////////////////////////////////////////////////////////
  270. template <class T>
  271. TCPropertyPageImpl<T>::~TCPropertyPageImpl()
  272. {
  273. _TRACE1("TCPropertyPageImpl<%hs>::~TCPropertyPageImpl()\n", TCTypeName(T));
  274. }
  275. /////////////////////////////////////////////////////////////////////////////
  276. // Group=Attributes
  277. /////////////////////////////////////////////////////////////////////////////
  278. // Description: Sets or resets the dirty flag of the property page.
  279. //
  280. // Sets or resets the dirty flag of the property page. When the page is
  281. // updating its fields from the objects (within the UpdateFields method),
  282. // this method returns immediately.
  283. //
  284. // If the dirty flag is changed as a result of this method call, it will call
  285. // the *IPropertyPageSite::OnStatusChage* method of the page's site object,
  286. // passing both the *PROPPAGESTATU_DIRTY* and *PROPPAGESTATUS_VALIDATE* „
  287. // flags. If the dirty flag is to be set /without/ signaling the
  288. // *PROPPAGESTATUS_VALIDATE* flag, see the SetDirtyNoApply method.
  289. //
  290. // Parameters:
  291. // bDirty - When *TRUE*, the page's dirty flag is set. When *FALSE*, the
  292. // page's dirty flag is reset.
  293. //
  294. // See Also: TCPropertyPageImpl::SetDirtyNoApply,
  295. // TCPropertyPageImpl::m_bUpdating
  296. template <class T>
  297. inline void TCPropertyPageImpl<T>::SetDirty(BOOL bDirty)
  298. {
  299. // Do nothing if page is updating
  300. if (m_bUpdating)
  301. return;
  302. // Get the derived class pointer
  303. T* pThis = static_cast<T*>(this);
  304. // Get the current dirty flag
  305. bool bDirtyPrev = !!pThis->m_bDirty;
  306. // Save the new dirty flag
  307. pThis->m_bDirty = bDirty;
  308. // Send a status change to the page site
  309. if (!bDirtyPrev && bDirty)
  310. pThis->m_pPageSite->OnStatusChange(PROPPAGESTATUS_DIRTY |
  311. PROPPAGESTATUS_VALIDATE);
  312. }
  313. /////////////////////////////////////////////////////////////////////////////
  314. // Description: Sets the dirty flag of the property page without indicating
  315. // to the page site that the changes should be applied.
  316. //
  317. // Sets the dirty flag of the property page without indicating to the page
  318. // site that the changes should be applied. When the page is
  319. // updating its fields from the objects (within the UpdateFields method),
  320. // this method returns immediately.
  321. //
  322. // If the dirty flag is changed as a result of this method call, it will call
  323. // the *IPropertyPageSite::OnStatusChage* method of the page's site object,
  324. // passing only the *PROPPAGESTATU_DIRTY* flag. If the
  325. // *PROPPAGESTATUS_VALIDATE* flag is also to be set, see the SetDirty method.
  326. //
  327. // See Also: TCPropertyPageImpl::SetDirty, TCPropertyPageImpl::m_bUpdating
  328. template <class T>
  329. inline void TCPropertyPageImpl<T>::SetDirtyNoApply()
  330. {
  331. // Do nothing if page is updating
  332. if (m_bUpdating)
  333. return;
  334. // Get the derived class pointer
  335. T* pThis = static_cast<T*>(this);
  336. // Get the current dirty flag
  337. bool bDirtyPrev = !!pThis->m_bDirty;
  338. // Save the new dirty flag
  339. pThis->m_bDirty = true;
  340. // Send a status change to the page site
  341. if (!bDirtyPrev)
  342. pThis->m_pPageSite->OnStatusChange(PROPPAGESTATUS_DIRTY);
  343. }
  344. /////////////////////////////////////////////////////////////////////////////
  345. // Group=Overrides
  346. /////////////////////////////////////////////////////////////////////////////
  347. // Description: Creates the property page window.
  348. //
  349. // Creates the property page window. This was overridden from the ATL
  350. // *IPropertyPageImpl* class so that the m_IDD member variable would be used
  351. // instead of the IDD enum value.
  352. //
  353. template <class T>
  354. HWND TCPropertyPageImpl<T>::Create(HWND hWndParent)
  355. {
  356. // Get the derived class pointer
  357. T* pThis = static_cast<T*>(this);
  358. assert(pThis->m_hWnd == NULL);
  359. _Module.AddCreateWndData(&pThis->m_thunk.cd, (CDialogImplBase*)pThis);
  360. HWND hWnd = ::CreateDialogParam(_Module.GetResourceInstance(),
  361. MAKEINTRESOURCE(pThis->m_IDD),
  362. hWndParent,
  363. (DLGPROC)StartDialogProc,
  364. NULL);
  365. assert(pThis->m_hWnd == hWnd);
  366. return hWnd;
  367. }
  368. /////////////////////////////////////////////////////////////////////////////
  369. // Description: Returns the *HWND* of the property page.
  370. //
  371. // Return Value: The *HWND* of the property page.
  372. template <class T>
  373. HWND TCPropertyPageImpl<T>::GetPageWindow()
  374. {
  375. // Get the derived class pointer
  376. T* pThis = static_cast<T*>(this);
  377. return *pThis;
  378. }
  379. /////////////////////////////////////////////////////////////////////////////
  380. // Description: Returns the *IUnknown* of the property page.
  381. //
  382. // Used by the TCPropertyPageBase base class to get the *IUnknown* pointer of
  383. // the most-derived class.
  384. template <class T>
  385. IUnknown* TCPropertyPageImpl<T>::GetPageUnknown()
  386. {
  387. // Get the derived class pointer
  388. T* pThis = static_cast<T*>(this);
  389. return pThis->GetUnknown();
  390. }
  391. /////////////////////////////////////////////////////////////////////////////
  392. // Description: Determines if an object supports an interesting interface.
  393. //
  394. // Determines if the specified object supports an interface needed by the
  395. // Property Page Field Update Macros.
  396. //
  397. // Parameters:
  398. // punk - An *IUnknown* pointer of the object to be tested for a known
  399. // interface.
  400. //
  401. // Return Value: *true* if the object supports an interface specified in the
  402. // property field map. Otherwise, *false*.
  403. //
  404. // See Also: Property Page Field Update Macros
  405. template <class T>
  406. inline bool TCPropertyPageImpl<T>::IsObjectKnown(IUnknown* punk)
  407. {
  408. // Get the derived class pointer
  409. T* pThis = static_cast<T*>(this);
  410. // Get the table of supported interfaces
  411. const XPageFieldEntry* pTable = NULL;
  412. UINT nEntries = pThis->GetPageFieldTable(&pTable);
  413. // Loop thru the supported IID's in the table
  414. typedef std::set<const IID*> CIIDSet;
  415. CIIDSet setPIID;
  416. bool bKnown = false;
  417. for (UINT i = 0; i < nEntries; ++i)
  418. {
  419. // Get the next table entry
  420. const XPageFieldEntry& entry = pTable[i];
  421. // See if we've already tested the entry's IID
  422. if (setPIID.end() == setPIID.find(entry.piid))
  423. {
  424. // QueryInterface for the IID specified by piid
  425. IUnknown* pqi;
  426. if (SUCCEEDED(punk->QueryInterface(*entry.piid, (void**)&pqi)))
  427. {
  428. assert(pqi);
  429. bKnown = true;
  430. // Add the interface pointer to the vector associated with the IID
  431. CUnkVectorMap::iterator it = m_mapInterfaces.find(*entry.piid);
  432. assert(m_mapInterfaces.end() != it);
  433. CUnkVector& vec = it->second;
  434. vec.push_back(pqi);
  435. }
  436. // Add the entry's IID to the set
  437. setPIID.insert(entry.piid);
  438. }
  439. }
  440. return bKnown;
  441. }
  442. /////////////////////////////////////////////////////////////////////////////
  443. // Description: Updates the property page fields from the set of objects
  444. // being viewed/edited.
  445. //
  446. // Updates the property page fields from the set of objects being
  447. // viewed/edited. If /dispid/ is DISPID_UNKNOWN, all properties are updated.
  448. // Otherwise, just the specified property is updated.
  449. //
  450. // Parameters:
  451. // dispid - Specifies the property that needs to be updated. DISPID_UNKNOWN
  452. // specifies that *all* properties are to be updated.
  453. //
  454. // See Also: Property Page Field Update Macros,
  455. // TCPropertyPageImpl::OnUpdateFields
  456. template <class T>
  457. void TCPropertyPageImpl<T>::UpdateFields(DISPID dispid)
  458. {
  459. // Get the derived class pointer
  460. T* pThis = static_cast<T*>(this);
  461. // Update dialog fields from objects
  462. m_bUpdating = true;
  463. __try
  464. {
  465. if (!pThis->OnUpdateFields(dispid))
  466. OnUpdateFields(dispid);
  467. }
  468. __except(1)
  469. {
  470. _TRACE1("TCPropertyPageImpl<%hs>::UpdateFields(): Error! Unhandled exception caught!\n",
  471. TCTypeName(T));
  472. }
  473. m_bUpdating = false;
  474. }
  475. /////////////////////////////////////////////////////////////////////////////
  476. // Description: Updates the property page fields from the set of objects
  477. // being viewed/edited.
  478. //
  479. // Loops thru the entries of the property field map and calls the function
  480. // specified in the entry to update the property specified by /dispid/.
  481. //
  482. // Parameters:
  483. // dispid - Specifies the property that needs to be updated. DISPID_UNKNOWN
  484. // specifies that *all* properties are to be updated.
  485. //
  486. // Return Value: Currently, this method always returns *true*.
  487. //
  488. // See Also: Property Page Field Update Macros,
  489. // TCPropertyPageImpl::UpdateFields, TCPropertyPageImpl::OnApplyFields
  490. template <class T>
  491. bool TCPropertyPageImpl<T>::OnUpdateFields(DISPID dispid)
  492. {
  493. // Get the derived class pointer
  494. T* pThis = static_cast<T*>(this);
  495. // Get the table of supported interfaces
  496. const XPageFieldEntry* pTable = NULL;
  497. UINT nEntries = pThis->GetPageFieldTable(&pTable);
  498. // Loop thru each field entry
  499. for (UINT i = 0; i < nEntries; ++i)
  500. {
  501. // Get the next field entry
  502. const XPageFieldEntry& entry = pTable[i];
  503. if (DISPID_UNKNOWN == dispid || entry.dispid == dispid || !entry.dispid)
  504. {
  505. // Only process if the entry's Update method was specified
  506. if (NULL != entry.pfnUpdate || NULL != entry.pfnUpdateEx)
  507. {
  508. // Get the CUnkVector for the entry's IID
  509. CUnkVectorMap::iterator it = m_mapInterfaces.find(*entry.piid);
  510. CUnkVector& vec = it->second;
  511. assert(m_mapInterfaces.end() != it);
  512. // Call the specified field Update method
  513. __try
  514. {
  515. if (NULL != entry.pfnUpdateEx)
  516. (pThis->*entry.pfnUpdateEx)(entry.idCtrl, dispid, *entry.piid,
  517. vec.size(), vec.begin());
  518. else
  519. (pThis->*entry.pfnUpdate)(vec.size(), vec.begin());
  520. }
  521. __except(1)
  522. {
  523. LPCSTR pszClass = TCTypeName(T);
  524. _TRACE_BEGIN
  525. _TRACE_PART1("TCPropertyPageImpl<%hs>::OnUpdateFields(): ", pszClass);
  526. _TRACE_PART0("Error! Unhandled exception caught!\n");
  527. _TRACE_END
  528. }
  529. }
  530. }
  531. }
  532. // Indicate that we updated the fields
  533. return true;
  534. }
  535. /////////////////////////////////////////////////////////////////////////////
  536. // Description: Applies the property page fields to the set of objects being
  537. // edited.
  538. //
  539. // Applies the property page fields to the set of objects being edited.
  540. // Loops thru the entries of the property field map and calls the function
  541. // specified in the entry to apply the property specified by /dispid/.
  542. //
  543. // See Also: Property Page Field Update Macros,
  544. // TCPropertyPageImpl::OnUpdateFields
  545. template <class T>
  546. inline void TCPropertyPageImpl<T>::OnApplyFields()
  547. {
  548. // Get the derived class pointer
  549. T* pThis = static_cast<T*>(this);
  550. // Get the table of supported interfaces
  551. const XPageFieldEntry* pTable = NULL;
  552. UINT nEntries = pThis->GetPageFieldTable(&pTable);
  553. // Loop thru each field entry
  554. for (UINT i = 0; i < nEntries; ++i)
  555. {
  556. // Get the next field entry
  557. const XPageFieldEntry& entry = pTable[i];
  558. // Only process if the entry's Apply method was specified
  559. if (NULL != entry.pfnApply || NULL != entry.pfnApplyEx)
  560. {
  561. // Get the CUnkVector for the entry's IID
  562. CUnkVectorMap::iterator it = m_mapInterfaces.find(*entry.piid);
  563. CUnkVector& vec = it->second;
  564. assert(m_mapInterfaces.end() != it);
  565. // Call the specified field Apply method
  566. __try
  567. {
  568. if (NULL != entry.pfnApplyEx)
  569. (pThis->*entry.pfnApplyEx)(entry.idCtrl, entry.dispid,
  570. *entry.piid, vec.size(), vec.begin());
  571. else
  572. (pThis->*entry.pfnApply)(vec.size(), vec.begin());
  573. }
  574. __except(1
  575. {
  576. _TRACE_BEGIN
  577. _TRACE_PART1("TCPropertyPageImpl<%hs>::", TCTypeName(T));
  578. _TRACE_PART0("OnApplyFields(): Error! Unhandled exception caught!\n");
  579. _TRACE_END
  580. }
  581. }
  582. }
  583. }
  584. /////////////////////////////////////////////////////////////////////////////
  585. // Description: Gets the property page field map.
  586. //
  587. // Gets the address of, and the number of entries in the property pages's
  588. // field map, as defined by the Property Page Field Update Macros.
  589. //
  590. // Note: This method is automatically overridden by the Property Page Field
  591. // Macros. It is not necessary to override it manually.
  592. //
  593. // Return Value: The number of entries in the property page field map.
  594. //
  595. // See Also: Property Page Field Update Macros
  596. template <class T>
  597. inline UINT TCPropertyPageImpl<T>::GetPageFieldTable(
  598. const TCPropertyPageImpl<T>::XPageFieldEntry** ppTable)
  599. {
  600. // Default does nothing
  601. if (ppTable)
  602. *ppTable = NULL;
  603. return 0;
  604. }
  605. /////////////////////////////////////////////////////////////////////////////
  606. // Group=Message Handlers
  607. /////////////////////////////////////////////////////////////////////////////
  608. // Description: A general message handler that can be used by derived-classes
  609. // to set the dirty flag of the property page.
  610. //
  611. // A general message handler that can be used by derived-classes to set the
  612. // dirty flag of the property page.
  613. //
  614. // See Also: TCPropertyPageImpl::SetDirty
  615. template <class T>
  616. LRESULT TCPropertyPageImpl<T>::OnSetDirty(WORD, WORD, HWND,
  617. BOOL& bHandled)
  618. {
  619. // Get the derived class pointer
  620. T* pThis = static_cast<T*>(this);
  621. // Set the dirty flag of the property page
  622. pThis->SetDirty(TRUE);
  623. // Act like we didn't handle this message
  624. bHandled = FALSE;
  625. return 0;
  626. }
  627. /////////////////////////////////////////////////////////////////////////////
  628. // Description: A general message handler that can be used by derived-classes
  629. // to set the dirty flag of the property page.
  630. //
  631. // A general message handler that can be used by derived-classes to set the
  632. // dirty flag of the property page.
  633. //
  634. // See Also: TCPropertyPageImpl::SetDirtyNoApply
  635. template <class T>
  636. LRESULT TCPropertyPageImpl<T>::OnSetDirtyNoApply(WORD, WORD, HWND,
  637. BOOL& bHandled)
  638. {
  639. // Get the derived class pointer
  640. T* pThis = static_cast<T*>(this);
  641. // Set the dirty flag of the property page
  642. pThis->SetDirtyNoApply();
  643. // Act like we didn't handle this message
  644. bHandled = FALSE;
  645. return 0;
  646. }
  647. /////////////////////////////////////////////////////////////////////////////
  648. // Description: Overridden message handler for WM_INITDIALOG.
  649. //
  650. // Delegates to the TCPropertyPageBase base class.
  651. //
  652. // Return Value: Returns *FALSE* so as to not set the focus to the first
  653. // tabstop control.
  654. //
  655. // See Also: TCPropertyPageBase::OnInitDialogHandler
  656. template <class T>
  657. LRESULT TCPropertyPageImpl<T>::OnInitDialogHandler(UINT, WPARAM,
  658. LPARAM, BOOL&)
  659. {
  660. _TRACE1("TCPropertyPageImpl<%hs>::OnInitDialogHandler()\n", TCTypeName(T));
  661. // Delegate to the base class
  662. TCPropertyPageBase::OnInitDialogHandler(m_nObjects, m_ppUnk);
  663. // Return FALSE so as to not set the focus to the first tabstop control
  664. return FALSE;
  665. }
  666. /////////////////////////////////////////////////////////////////////////////
  667. // Group=IPropertyPage Interface Methods
  668. /////////////////////////////////////////////////////////////////////////////
  669. // Description: Returns information about the property page.
  670. //
  671. // Fills a caller-allocated *PROPPAGEINFO* structure to provide the caller
  672. // with information about the property page.
  673. //
  674. // This was overridden from the ATL *IPropertyPageImpl* class so that the
  675. // m_IDD member variable would be used instead of the IDD enum value.
  676. //
  677. // Parameters:
  678. // pPageInfo - [out] Pointer to the caller-allocated *PROPPAGEINFO* „
  679. // structure in which the property page stores its page information. All
  680. // allocations stored in this structure become the responsibility of the
  681. // caller.
  682. //
  683. // Return Value: This method supports the standard return values
  684. // *E_OUTOFMEMORY* and *E_UNEXPECTED*, as well as the following:
  685. //
  686. // S_OK - The structure was successfully filled.
  687. // E_POINTER - The address in /pPageInfo/ is not valid. For example, it may
  688. // be NULL.
  689. template <class T>
  690. STDMETHODIMP TCPropertyPageImpl<T>::GetPageInfo(PROPPAGEINFO *pPageInfo)
  691. {
  692. _TRACE1("TCPropertyPageImpl<%hs>::GetPageInfo\n", TCTypeName(T));
  693. if (pPageInfo == NULL)
  694. {
  695. _TRACE0("Error : PROPPAGEINFO passed == NULL\n");
  696. return E_POINTER;
  697. }
  698. // Get the derived class pointer
  699. T* pThis = static_cast<T*>(this);
  700. HRSRC hRsrc = FindResource(_Module.GetResourceInstance(),
  701. MAKEINTRESOURCE(pThis->m_IDD), RT_DIALOG);
  702. if (hRsrc == NULL)
  703. {
  704. _TRACE0("Could not find resource template\n");
  705. return E_UNEXPECTED;
  706. }
  707. HGLOBAL hGlob = LoadResource(_Module.GetResourceInstance(), hRsrc);
  708. DLGTEMPLATE* pTemp = (DLGTEMPLATE*)LockResource(hGlob);
  709. if (pTemp == NULL)
  710. {
  711. _TRACE0("Could not load resource template\n");
  712. return E_UNEXPECTED;
  713. }
  714. GetDialogSize(pTemp, &pThis->m_size);
  715. pPageInfo->cb = sizeof(PROPPAGEINFO);
  716. pPageInfo->pszTitle = LoadStringHelper(pThis->m_dwTitleID);
  717. pPageInfo->size = pThis->m_size;
  718. pPageInfo->pszHelpFile = LoadStringHelper(pThis->m_dwHelpFileID);
  719. pPageInfo->pszDocString = LoadStringHelper(pThis->m_dwDocStringID);
  720. pPageInfo->dwHelpContext = pThis->m_dwHelpContext;
  721. return S_OK;
  722. }
  723. /////////////////////////////////////////////////////////////////////////////
  724. // Description: Provides the property page with an array of IUnknown pointers
  725. // for objects associated with this property page.
  726. //
  727. // Delegates to TCPropertyPageBase::SetObjects.
  728. //
  729. // Parameters:
  730. // cObjects - [in] Number of *IUnknown* pointers in the array pointed to
  731. // by /ppUnk/.
  732. // ppUnk - [in] Pointer to an array of *IUnknown* interface pointers where
  733. // each pointer identifies a unique object affected by the property sheet in
  734. // which this (and possibly other) property pages are displayed.
  735. //
  736. // Return Value: This method supports the standard return values *E_FAIL*,
  737. // *E_INVALIDARG*, *E_OUTOFMEMORY*, and *E_UNEXPECTED*, as well as the
  738. // following:
  739. //
  740. // S_OK - The property page successfully saved the pointers it needed.
  741. // E_NOINTERFACE - One of the objects in /ppUnk/ did not support the
  742. // interface expected by this property page, and so this property page
  743. // cannot communicate with it.
  744. // E_POINTER - The address in /ppUnk/ is not valid. For example, it may be
  745. // NULL.
  746. //
  747. // See Also: TCPropertyPageBase::SetObjects
  748. template <class T> STDMETHODIMP
  749. TCPropertyPageImpl<T>::SetObjects(ULONG cObjects, IUnknown** ppUnk)
  750. {
  751. // Delegate to base class
  752. return
  753. TCPropertyPageBase::SetObjects(m_nObjects, m_ppUnk, cObjects, ppUnk);
  754. }
  755. /////////////////////////////////////////////////////////////////////////////
  756. // Description: Applies current property page values to underlying objects
  757. // specified through SetObjects.
  758. //
  759. // Applies the current values to the underlying objects associated with the
  760. // property page as previously passed to SetObjects.
  761. //
  762. //
  763. // Return Value: This method supports the standard return values
  764. // *E_OUTOFMEMORY* and *E_UNEXPECTED*, as well as the following:
  765. //
  766. // S_OK - Changes were successfully applied and the property page is
  767. // current with the underlying objects.
  768. // S_FALSE - Changes were applied, but the property page cannot determine
  769. // if its state is current with the objects.
  770. //
  771. // See Also: TCPropertyPageImpl::SetObjects
  772. template <class T>
  773. STDMETHODIMP TCPropertyPageImpl<T>::Apply()
  774. {
  775. // Get the derived class pointer
  776. T* pThis = static_cast<T*>(this);
  777. // Forward the method to each embedded property page, including groups
  778. RETURN_FAILED(ApplyToInsidePages());
  779. __try
  780. {
  781. // Allow the derived class to apply its changes, assuming page is dirty
  782. // NOTE: This puts the responsibility on the page site to know if the
  783. // property page is dirty.
  784. pThis->OnApplyFields();
  785. // Reset the dirty flag
  786. pThis->SetDirty(FALSE);
  787. // Indicate success
  788. return S_OK;
  789. }
  790. __except(1)
  791. {
  792. _TRACE1("TCPropertyPageImpl<%hs>::Apply(): Error! Unhandled exception caught!\n",
  793. TCTypeName(T));
  794. return RPC_E_SERVERFAULT;
  795. }
  796. }
  797. /////////////////////////////////////////////////////////////////////////////
  798. // Description: Invokes help in response to end-user request.
  799. //
  800. // Parameters:
  801. // pszHelpDir - [in] Pointer to the string under the *HelpDir* key in the
  802. // property page's CLSID information in the registry. If *HelpDir* does not
  803. // exist, this will be the path found in the *InProcServer32* entry minus the
  804. // server file name.
  805. //
  806. // Return Value: This implementation always returns *E_NOTIMPL*, indicating
  807. // that help is provided only through the information in *PROPPAGEINFO*.
  808. //
  809. // See Also: TCPropertyPageImpl::GetPageInfo
  810. template <class T>
  811. STDMETHODIMP TCPropertyPageImpl<T>::Help(LPCOLESTR pszHelpDir)
  812. {
  813. _TRACE2("TCPropertyPageImpl<%hs>::Help(\"%ls\")\n",
  814. TCTypeName(T), pszHelpDir);
  815. return E_NOTIMPL;
  816. }
  817. /////////////////////////////////////////////////////////////////////////////
  818. // Group=IPropertyPageSite Interface Methods
  819. /////////////////////////////////////////////////////////////////////////////
  820. // Description: Indicates that the user has modified property values on the
  821. // property page.
  822. //
  823. // Informs the frame that the property page managed by this site has changed
  824. // its state, that is, one or more property values have been changed in the
  825. // page.
  826. //
  827. // This is a method of the property page's *IPropertyPageSite* „
  828. // implementation, which is provided to any property pages embedded within
  829. // this one.
  830. //
  831. // This implementation sets the dirty flag of this property page and then
  832. // simply delegates to the same method of the property page's
  833. // *IPropertyPageSite*.
  834. //
  835. // Parameters:
  836. // dwFlags - [in] Flags to indicate what changes have occurred.
  837. //
  838. // Return Value: The return value of the delegated method call.
  839. //
  840. // See Also: Embedded Property Page Table Macros
  841. template <class T>
  842. STDMETHODIMP TCPropertyPageImpl<T>::OnStatusChange(DWORD dwFlags)
  843. {
  844. // Check for flags that would indicate that child is dirty
  845. if ((PROPPAGESTATUS_DIRTY | PROPPAGESTATUS_VALIDATE) & dwFlags)
  846. {
  847. // Get the derived class pointer
  848. T* pThis = static_cast<T*>(this);
  849. // Set the dirty flag of this page
  850. if (PROPPAGESTATUS_VALIDATE & dwFlags)
  851. pThis->SetDirty(TRUE);
  852. else
  853. pThis->SetDirtyNoApply();
  854. return S_OK;
  855. }
  856. // Delegate to this page's site
  857. assert(NULL != m_pPageSite);
  858. return m_pPageSite->OnStatusChange(dwFlags);
  859. }
  860. /////////////////////////////////////////////////////////////////////////////
  861. // Description: Returns the locale identifier so the property page can adjust
  862. // itself to country-specific settings.
  863. //
  864. // Returns the locale identifier (an LCID) that a property page can use to
  865. // adjust itself to the language in use and other country-specific settings.
  866. //
  867. // This is a method of the property page's *IPropertyPageSite* „
  868. // implementation, which is provided to any property pages embedded within
  869. // this one.
  870. //
  871. // This implementation simply delegates to the same method of the property
  872. // page's *IPropertyPageSite*.
  873. //
  874. // Parameters:
  875. // pLocaleID - [out] Pointer to locale identifier.
  876. //
  877. // Return Value: The return value of the delegated method call.
  878. //
  879. // See Also: Embedded Property Page Table Macros
  880. template <class T>
  881. STDMETHODIMP TCPropertyPageImpl<T>::GetLocaleID(LCID* pLocaleID)
  882. {
  883. // Delegate to this page's site
  884. assert(NULL != m_pPageSite);
  885. return m_pPageSite->GetLocaleID(pLocaleID);
  886. }
  887. /////////////////////////////////////////////////////////////////////////////
  888. // Description: Returns an *IUnknown* pointer for the object representing the
  889. // entire property frame dialog box that contains all the pages.
  890. //
  891. // This is a method of the property page's *IPropertyPageSite* „
  892. // implementation, which is provided to any property pages embedded within
  893. // this one.
  894. //
  895. // This implementation simply delegates to the same method of the property
  896. // page's *IPropertyPageSite*.
  897. //
  898. // Parameters:
  899. // ppUnk - [out] Address of *IUnknown* pointer variable that receives the
  900. // interface pointer to the container object.
  901. //
  902. // Return Value: The return value of the delegated method call.
  903. //
  904. // See Also: Embedded Property Page Table Macros
  905. template <class T>
  906. STDMETHODIMP TCPropertyPageImpl<T>::GetPageContainer(IUnknown** ppUnk)
  907. {
  908. // Delegate to this page's site
  909. assert(NULL != m_pPageSite);
  910. return m_pPageSite->GetPageContainer(ppUnk);
  911. }
  912. /////////////////////////////////////////////////////////////////////////////
  913. // Description: Passes a keystroke to the property frame for processing.
  914. //
  915. // Instructs the page site to process a keystroke if it desires.
  916. //
  917. // This is a method of the property page's *IPropertyPageSite* „
  918. // implementation, which is provided to any property pages embedded within
  919. // this one.
  920. //
  921. // This implementation simply delegates to the same method of the property
  922. // page's *IPropertyPageSite*.
  923. //
  924. // Parameters:
  925. // pMsg - [in] Pointer to the *MSG* structure to be processed.
  926. //
  927. // Return Value: The return value of the delegated method call.
  928. //
  929. // See Also: Embedded Property Page Table Macros
  930. template <class T>
  931. STDMETHODIMP TCPropertyPageImpl<T>::TranslateAccelerator(MSG* pMsg)
  932. {
  933. // Delegate to this page's site
  934. assert(NULL != m_pPageSite);
  935. return m_pPageSite->TranslateAccelerator(pMsg);
  936. }
  937. /////////////////////////////////////////////////////////////////////////////
  938. // Group=IPropertyNotifySink Interface Methods
  939. /////////////////////////////////////////////////////////////////////////////
  940. // Description: Notifies a sink that a bindable property has changed.
  941. //
  942. // This implementation simply posts a message to the main window of the
  943. // property page, to ensure that the property change notification is handled
  944. // on the main thread, and to return more quickly to the object that fired
  945. // the event.
  946. //
  947. // Parameters:
  948. // dispid - [in] Dispatch identifier of the property that changed, or
  949. // *DISPID_UNKNOWN* if multiple properties have changed.
  950. //
  951. // Return Value: This method always returns *S_OK*.
  952. //
  953. // See Also: Property Page Field Update Macros,
  954. // TCPropertyPageBase::OnChangedHandler,
  955. // TCPropertyPageImpl<T>::OnRequestEdit, TCPropertyPageImpl::wm_OnChanged
  956. template <class T>
  957. STDMETHODIMP TCPropertyPageImpl<T>::OnChanged(DISPID dispid)
  958. {
  959. // Get the derived class pointer
  960. T* pThis = static_cast<T*>(this);
  961. // IPropertyNotifySink should only be connected when window is active
  962. assert((HWND)*pThis);
  963. // Post a message to handle the property change notification
  964. pThis->PostMessage(wm_OnChanged, dispid);
  965. // Indicate success
  966. return S_OK;
  967. }
  968. /////////////////////////////////////////////////////////////////////////////
  969. // Description: Notifies a sink that a requestedit property is about to
  970. // change.
  971. //
  972. // Note: Currently, this implementation always returns *S_OK*, indicating
  973. // that this page does not restrict the changing of any property specified.
  974. //
  975. // TODO: In the future, the specified /dispid/ should be found in a set of
  976. // fields that are marked as dirty. This would assist in ensuring that the
  977. // property does not get modified from more than one instance of the property
  978. // page. This issue becomes even more complex due to the user interface
  979. // interactions with a field. As soon as a user begins to change a field, the
  980. // field should be marked 'dirty' so that another page instance cannot also
  981. // edit the field. This also implies that the OnRequestEdit event is fired
  982. // whenever a user attempt to change a field, which could be a somewhat slow
  983. // process. Things that make you go hmmmmm.
  984. //
  985. // Parameters:
  986. // dispid - [in] Dispatch identifier of the property that is about to
  987. // change or *DISPID_UNKNOWN* if multiple properties are about to change.
  988. //
  989. // Return Value: This method always returns *S_OK*, indicating that the
  990. // specified property or properties are allowed to change.
  991. //
  992. // See Also: Property Page Field Update Macros,
  993. // TCPropertyPageBase::OnChanged
  994. template <class T>
  995. STDMETHODIMP TCPropertyPageImpl<T>::OnRequestEdit(DISPID dispid)
  996. {
  997. // TODO: Lookup the specified DISPID in the set of dirty field DISPIDs
  998. // Indicate success
  999. return S_OK;
  1000. }
  1001. /////////////////////////////////////////////////////////////////////////////
  1002. // Group=ITCPropertyFieldToggle Interface Methods
  1003. /////////////////////////////////////////////////////////////////////////////
  1004. // Description: To disable or enable fields.
  1005. //
  1006. // Parameters:
  1007. // dispid - [in] Dispatch identifier of the field to enable or disable.
  1008. // bEnable - [in] Enable or disable the field.
  1009. //
  1010. // Return Value: This method always returns *S_OK* if the call succeeds.
  1011. //
  1012. // See Also:
  1013. //
  1014. //
  1015. template <class T>
  1016. STDMETHODIMP TCPropertyPageImpl<T>::put_EnableField(DISPID dispid, VARIANT_BOOL bEnable)
  1017. {
  1018. // Get the derived class pointer
  1019. T* pThis = static_cast<T*>(this);
  1020. pThis->FieldToggle(dispid, true, !!bEnable);
  1021. // Indicate success
  1022. return S_OK;
  1023. }
  1024. /////////////////////////////////////////////////////////////////////////////
  1025. // Description: To determine whether or not a field is disabled.
  1026. //
  1027. // Parameters:
  1028. // dispid - [in] Dispatch identifier of the field to check.
  1029. // pbEnable - [out, retval].
  1030. //
  1031. // Return Value: This method always returns *S_OK* if the call succeeds.
  1032. //
  1033. // See Also:
  1034. //
  1035. //
  1036. template <class T>
  1037. STDMETHODIMP TCPropertyPageImpl<T>::get_EnableField(DISPID dispid, VARIANT_BOOL* pbEnable)
  1038. {
  1039. // Get the derived class pointer
  1040. T* pThis = static_cast<T*>(this);
  1041. *pbEnable = pThis->GetFieldToggle(dispid, true);
  1042. // Indicate success
  1043. return S_OK;
  1044. }
  1045. /////////////////////////////////////////////////////////////////////////////
  1046. // Description: To show or hide fields.
  1047. //
  1048. // Parameters:
  1049. // dispid - [in] Dispatch identifier of the field to show or hide.
  1050. // bEnable - [in] Show or hide the field.
  1051. //
  1052. // Return Value: This method always returns *S_OK* if the call succeeds.
  1053. //
  1054. // See Also:
  1055. //
  1056. //
  1057. template <class T>
  1058. STDMETHODIMP TCPropertyPageImpl<T>::put_ShowField(DISPID dispid, VARIANT_BOOL bShow)
  1059. {
  1060. // Get the derived class pointer
  1061. T* pThis = static_cast<T*>(this);
  1062. pThis->FieldToggle(dispid, false, !!bShow);
  1063. // Indicate success
  1064. return S_OK;
  1065. }
  1066. /////////////////////////////////////////////////////////////////////////////
  1067. // Description: To determine whether or not a field is showing.
  1068. //
  1069. // Parameters:
  1070. // dispid - [in] Dispatch identifier of the field to check.
  1071. // pbEnable - [out, retval].
  1072. //
  1073. // Return Value: This method always returns *S_OK* if the call succeeds.
  1074. //
  1075. // See Also:
  1076. //
  1077. //
  1078. template <class T>
  1079. STDMETHODIMP TCPropertyPageImpl<T>::get_ShowField(DISPID dispid, VARIANT_BOOL* pbShow)
  1080. {
  1081. // Get the derived class pointer
  1082. T* pThis = static_cast<T*>(this);
  1083. *pbShow = pThis->GetFieldToggle(dispid, false);
  1084. // Indicate success
  1085. return S_OK;
  1086. }
  1087. /////////////////////////////////////////////////////////////////////////////
  1088. /////////////////////////////////////////////////////////////////////////////
  1089. // Group=Helpers
  1090. /////////////////////////////////////////////////////////////////////////////
  1091. // Description: To toggle fields (enable/disable or show/hide).
  1092. //
  1093. // Parameters:
  1094. // dispid - [in] Dispatch identifier of the field to toggle.
  1095. // bEnableDisable - [in] Is this a enable/disable or show/hide toggle.
  1096. // bToggle - [in] Toggle flag.
  1097. //
  1098. // Return Value: None.
  1099. //
  1100. // See Also:
  1101. //
  1102. //
  1103. template <class T>
  1104. void TCPropertyPageImpl<T>::FieldToggle(DISPID dispid, bool bEnableDisable, bool bToggle)
  1105. {
  1106. // Get the derived class pointer
  1107. T* pThis = static_cast<T*>(this);
  1108. // Get the table of supported interfaces
  1109. const XPageFieldEntry* pTable = NULL;
  1110. UINT nEntries = pThis->GetPageFieldTable(&pTable);
  1111. // Loop thru each field entry
  1112. for (UINT i = 0; i < nEntries; ++i)
  1113. {
  1114. // Get the next field entry
  1115. const XPageFieldEntry& entry = pTable[i];
  1116. if (entry.dispid == dispid)
  1117. {
  1118. // Enable/Disable the window
  1119. HWND hwnd = GetDlgItem(entry.idCtrl);
  1120. if (hwnd)
  1121. {
  1122. if (bEnableDisable)
  1123. ::EnableWindow(hwnd, bToggle);
  1124. else
  1125. ::ShowWindow(hwnd, bToggle ? SW_SHOW : SW_HIDE);
  1126. }
  1127. }
  1128. }
  1129. }
  1130. /////////////////////////////////////////////////////////////////////////////
  1131. // Description: Get the toggle of the field (enable/disable or show/hide).
  1132. //
  1133. // Parameters:
  1134. // dispid - [in] Dispatch identifier of the field to toggle.
  1135. // bEnableDisable - [in] Is this a enable/disable or show/hide toggle.
  1136. //
  1137. // Return Value: Toggle flag.
  1138. //
  1139. // See Also:
  1140. //
  1141. //
  1142. template <class T>
  1143. bool TCPropertyPageImpl<T>::GetFieldToggle(DISPID dispid, bool bEnableDisable)
  1144. {
  1145. // Get the derived class pointer
  1146. T* pThis = static_cast<T*>(this);
  1147. // Get the table of supported interfaces
  1148. const XPageFieldEntry* pTable = NULL;
  1149. UINT nEntries = pThis->GetPageFieldTable(&pTable);
  1150. // Loop thru each field entry
  1151. for (UINT i = 0; i < nEntries; ++i)
  1152. {
  1153. // Get the next field entry
  1154. const XPageFieldEntry& entry = pTable[i];
  1155. if (entry.dispid == dispid)
  1156. {
  1157. // Enable/Disable the window
  1158. HWND hwnd = GetDlgItem(entry.idCtrl);
  1159. if (hwnd)
  1160. {
  1161. if (bEnableDisable)
  1162. return !!::IsWindowEnabled(hwnd);
  1163. else
  1164. return !!::IsWindowVisible(hwnd);
  1165. }
  1166. }
  1167. }
  1168. return true;
  1169. }
  1170. #endif //__PropertyPageImpl_h_