00001 /****************************************************************************** 00002 00003 Header File: Property Page.H 00004 00005 This defines the C++ class used to encapsulate property pages. This class 00006 has a static method for the dialog procedure, which automatically caches the 00007 "this" pointer for the class in the DWL_USER field of the windows internal 00008 structure for the dialog used for the property page. This hand-off is 00009 accomplished by setting the lParam field of the PROPSHEETPAGE structure to 00010 the "this" pointer. It also saves the dialog handle in a protected member 00011 for easy access from derived classes. 00012 00013 To create a C++ class for any specific property sheet, derive the class 00014 from this class, providing the dialog ID and instance handle needed to get 00015 the resource in the m_psp member. 00016 00017 The dialog procedure then provides virtual functions for Windows messages 00018 of interest. I've added these as needed. If I were going to a truly 00019 universal class of this sort, I'd just as well go to MFC, and save the 00020 debugging time, so this approach seems reasonable to me. 00021 00022 Copyright (c) 1996 by Microsoft Corporation 00023 00024 A Pretty Penny Enterprises Production 00025 00026 Change History: 00027 00028 11-01-96 [email protected] original version 00029 00030 ******************************************************************************/ 00031 00032 #if !defined(PROPERTY_PAGE) 00033 00034 #define PROPERTY_PAGE 00035 00036 // CPropertyPage class- abstracts a property page for us 00037 00038 class CPropertyPage { 00039 00040 // Basic dialog procedure for all derived classes 00041 00042 static BOOL CALLBACK DialogProc(HWND hwndPage, UINT uMsg, WPARAM wp, 00043 LPARAM lp); 00044 00045 // These elements should be protected (only available to derived classes) 00046 00047 protected: 00048 PROPSHEETPAGE m_psp; 00049 HWND m_hwnd, m_hwndSheet; 00050 HPROPSHEETPAGE m_hpsp; 00051 00052 BOOL m_bChanged; 00053 00054 public: 00055 00056 CPropertyPage(); // Default Constructor 00057 virtual ~CPropertyPage() {} 00058 00059 HPROPSHEETPAGE Handle(); // Calls CreatePropertySheetPage, if needed 00060 00061 VOID EnableApplyButton() { 00062 SendMessage(m_hwndSheet, PSM_CHANGED, (WPARAM) m_hwnd, 0); 00063 } 00064 00065 VOID DisableApplyButton() { 00066 SendMessage(m_hwndSheet, PSM_UNCHANGED, (WPARAM) m_hwnd, 0); 00067 } 00068 00069 BOOL SettingChanged() { 00070 return m_bChanged; 00071 } 00072 00073 VOID SettingChanged(BOOL b) { 00074 m_bChanged = b; 00075 } 00076 00077 // virtual functions- these get redefined on an as needed basis for 00078 // any specialized handling desired by any derived classes. 00079 00080 // The default handling allows one to initially display the sheet with 00081 // no coding beyond the constructor for the derived class 00082 00083 virtual BOOL OnCommand(WORD wNotifyCode, WORD wid, HWND hwndCtl) { 00084 return FALSE; 00085 } 00086 00087 virtual BOOL OnNotify(int idCtrl, LPNMHDR pnmh) { 00088 return FALSE; 00089 } 00090 00091 virtual BOOL OnInit() { return TRUE; } 00092 00093 virtual BOOL OnDestroy() { return FALSE; } 00094 00095 virtual BOOL OnHelp(LPHELPINFO pHelp) { return TRUE; } 00096 virtual BOOL OnContextMenu(HWND hwnd) { return TRUE; } 00097 }; 00098 00099 /****************************************************************************** 00100 00101 Shell Extension property page class 00102 00103 Noteworthy details: 00104 00105 These pages are displayed by the shell. The thread of execution is such that 00106 we create the page, then return to the shell. The shell will then attempt to 00107 unload the extension. It will query CanDllUnloadNow to do this. Since 00108 freeing the library frees the page template and dialog procedure, we can't 00109 allow this to happen while any instances of this class exist. 00110 00111 However, the shell doesn't know this is a class, so it won't destroy it. 00112 00113 What I've done is build a circular chain of all of the instances of this 00114 class, anchored in a private static class member. A public static method 00115 (OKToClose) then walks the chain. If an instance's window handle is no 00116 longer valid, then the shell has finished with it, and we delete it. The 00117 criterion for closing then becomes not finding a valid handle (so we don't 00118 delay unloading by any lazy evaluation, such as requiring an empty chain 00119 on entry). 00120 00121 All Property pages displayed by a property sheet extension should be derived 00122 from this class. 00123 00124 While a mechanism is provided by property sheets for a reference count 00125 maintenance mechanism, this mechanism will not call any class destructor- 00126 this could lead to memory leaks, which is why I've chosen this method. 00127 00128 ******************************************************************************/ 00129 00130 class CShellExtensionPage: public CPropertyPage { 00131 00132 static CShellExtensionPage *m_pcsepAnchor; // Anchor the chain of these 00133 00134 CShellExtensionPage *m_pcsepPrevious, *m_pcsepNext; 00135 00136 public: 00137 00138 CShellExtensionPage(); 00139 ~CShellExtensionPage(); 00140 00141 static BOOL OKToClose(); 00142 }; 00143 00144 00145 #endif // Keep us from getting multiply defined