summaryrefslogtreecommitdiffstats
path: root/mmc_updater/depends/win32cpp/propertysheet.h
diff options
context:
space:
mode:
Diffstat (limited to 'mmc_updater/depends/win32cpp/propertysheet.h')
-rw-r--r--mmc_updater/depends/win32cpp/propertysheet.h960
1 files changed, 960 insertions, 0 deletions
diff --git a/mmc_updater/depends/win32cpp/propertysheet.h b/mmc_updater/depends/win32cpp/propertysheet.h
new file mode 100644
index 00000000..4048942c
--- /dev/null
+++ b/mmc_updater/depends/win32cpp/propertysheet.h
@@ -0,0 +1,960 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// propertysheet.h
+// Declaration of the following classes:
+// CPropertyPage and CPropertySheet
+
+// These classes add support for property sheets to Win32++. A property sheet
+// will have one or more property pages. These pages are much like dialogs
+// which are presented within a tabbed dialog or within a wizard. The data
+// on a property page can be validated before the next page is presented.
+// Property sheets have three modes of use: Modal, Modeless, and Wizard.
+//
+// Refer to the PropertySheet demo program for an example of how propert sheets
+// can be used.
+
+
+#ifndef _WIN32XX_PROPERTYSHEET_H_
+#define _WIN32XX_PROPERTYSHEET_H_
+
+#include "dialog.h"
+
+#define ID_APPLY_NOW 0x3021
+#define ID_WIZBACK 0x3023
+#define ID_WIZNEXT 0x3024
+#define ID_WIZFINISH 0x3025
+#define ID_HELP 0xE146
+
+#ifndef PROPSHEETHEADER_V1_SIZE
+ #define PROPSHEETHEADER_V1_SIZE 40
+#endif
+
+namespace Win32xx
+{
+ class CPropertyPage;
+ typedef Shared_Ptr<CPropertyPage> PropertyPagePtr;
+
+ class CPropertyPage : public CWnd
+ {
+ public:
+ CPropertyPage (UINT nIDTemplate, LPCTSTR szTitle = NULL);
+ virtual ~CPropertyPage() {}
+
+ virtual INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual INT_PTR DialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual int OnApply();
+ virtual void OnCancel();
+ virtual void OnHelp();
+ virtual BOOL OnInitDialog();
+ virtual BOOL OnKillActive();
+ virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);
+ virtual int OnOK();
+ virtual BOOL OnQueryCancel();
+ virtual BOOL OnQuerySiblings(WPARAM wParam, LPARAM lParam);
+ virtual int OnSetActive();
+ virtual int OnWizardBack();
+ virtual INT_PTR OnWizardFinish();
+ virtual int OnWizardNext();
+ virtual BOOL PreTranslateMessage(MSG* pMsg);
+
+ static UINT CALLBACK StaticPropSheetPageProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp);
+ static INT_PTR CALLBACK StaticDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ void CancelToClose() const;
+ PROPSHEETPAGE GetPSP() const {return m_PSP;}
+ BOOL IsButtonEnabled(int iButton) const;
+ LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam) const;
+ void SetModified(BOOL bChanged) const;
+ void SetTitle(LPCTSTR szTitle);
+ void SetWizardButtons(DWORD dwFlags) const;
+
+ protected:
+ PROPSHEETPAGE m_PSP;
+
+ private:
+ CPropertyPage(const CPropertyPage&); // Disable copy construction
+ CPropertyPage& operator = (const CPropertyPage&); // Disable assignment operator
+
+ tString m_Title;
+ };
+
+ class CPropertySheet : public CWnd
+ {
+ public:
+ CPropertySheet(UINT nIDCaption, CWnd* pParent = NULL);
+ CPropertySheet(LPCTSTR pszCaption = NULL, CWnd* pParent = NULL);
+ virtual ~CPropertySheet() {}
+
+ // Operations
+ virtual CPropertyPage* AddPage(CPropertyPage* pPage);
+ virtual HWND Create(CWnd* pParent = 0);
+ virtual INT_PTR CreatePropertySheet(LPCPROPSHEETHEADER ppsph);
+ virtual void DestroyButton(int iButton);
+ virtual void Destroy();
+ virtual int DoModal();
+ virtual void RemovePage(CPropertyPage* pPage);
+
+ // State functions
+ BOOL IsModeless() const;
+ BOOL IsWizard() const;
+
+ //Attributes
+ CPropertyPage* GetActivePage() const;
+ int GetPageCount() const;
+ int GetPageIndex(CPropertyPage* pPage) const;
+ HWND GetTabControl() const;
+ virtual BOOL SetActivePage(int nPage);
+ virtual BOOL SetActivePage(CPropertyPage* pPage);
+ virtual void SetIcon(UINT idIcon);
+ virtual void SetTitle(LPCTSTR szTitle);
+ virtual void SetWizardMode(BOOL bWizard);
+
+ protected:
+ virtual BOOL PreTranslateMessage(MSG* pMsg);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CPropertySheet(const CPropertySheet&); // Disable copy construction
+ CPropertySheet& operator = (const CPropertySheet&); // Disable assignment operator
+ void BuildPageArray();
+ static void CALLBACK Callback(HWND hwnd, UINT uMsg, LPARAM lParam);
+
+ tString m_Title;
+ std::vector<PropertyPagePtr> m_vPages; // vector of CPropertyPage
+ std::vector<PROPSHEETPAGE> m_vPSP; // vector of PROPSHEETPAGE
+ BOOL m_bInitialUpdate;
+ PROPSHEETHEADER m_PSH;
+ };
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
+
+namespace Win32xx
+{
+
+ //////////////////////////////////////////
+ // Definitions for the CPropertyPage class
+ //
+ inline CPropertyPage::CPropertyPage(UINT nIDTemplate, LPCTSTR szTitle /* = NULL*/)
+ {
+ ZeroMemory(&m_PSP, sizeof(PROPSHEETPAGE));
+ SetTitle(szTitle);
+
+ m_PSP.dwSize = sizeof(PROPSHEETPAGE);
+ m_PSP.dwFlags |= PSP_USECALLBACK;
+ m_PSP.hInstance = GetApp()->GetResourceHandle();
+ m_PSP.pszTemplate = MAKEINTRESOURCE(nIDTemplate);
+ m_PSP.pszTitle = m_Title.c_str();
+ m_PSP.pfnDlgProc = (DLGPROC)CPropertyPage::StaticDialogProc;
+ m_PSP.lParam = (LPARAM)this;
+ m_PSP.pfnCallback = CPropertyPage::StaticPropSheetPageProc;
+ }
+
+ inline void CPropertyPage::CancelToClose() const
+ // Disables the Cancel button and changes the text of the OK button to "Close."
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(PSM_CANCELTOCLOSE, 0L, 0L);
+ }
+
+
+ inline INT_PTR CPropertyPage::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ // Override this function in your class derrived from CPropertyPage if you wish to handle messages
+ // A typical function might look like this:
+
+ // switch (uMsg)
+ // {
+ // case MESSAGE1: // Some Win32 API message
+ // OnMessage1(); // A user defined function
+ // break; // Also do default processing
+ // case MESSAGE2:
+ // OnMessage2();
+ // return x; // Don't do default processing, but instead return
+ // // a value recommended by the Win32 API documentation
+ // }
+
+ // Always pass unhandled messages on to DialogProcDefault
+ return DialogProcDefault(uMsg, wParam, lParam);
+ }
+
+ inline INT_PTR CPropertyPage::DialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ // All DialogProc functions should pass unhandled messages to this function
+ {
+ LRESULT lr = 0L;
+
+ switch (uMsg)
+ {
+ case UWM_CLEANUPTEMPS:
+ {
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ pTLSData->vTmpWnds.clear();
+ }
+ break;
+
+ case WM_INITDIALOG:
+ return OnInitDialog();
+
+ case PSM_QUERYSIBLINGS:
+ return (BOOL)OnQuerySiblings(wParam, lParam);
+
+ case WM_COMMAND:
+ {
+ // Refelect this message if it's from a control
+ CWnd* pWnd = GetApp()->GetCWndFromMap((HWND)lParam);
+ if (pWnd != NULL)
+ lr = pWnd->OnCommand(wParam, lParam);
+
+ // Handle user commands
+ if (!lr)
+ lr = OnCommand(wParam, lParam);
+
+ if (lr) return 0L;
+ }
+ break;
+
+ case WM_NOTIFY:
+ {
+ // Do Notification reflection if it came from a CWnd object
+ HWND hwndFrom = ((LPNMHDR)lParam)->hwndFrom;
+ CWnd* pWndFrom = GetApp()->GetCWndFromMap(hwndFrom);
+
+ if (pWndFrom != NULL)
+ lr = pWndFrom->OnNotifyReflect(wParam, lParam);
+ else
+ {
+ // Some controls (eg ListView) have child windows.
+ // Reflect those notifications too.
+ CWnd* pWndFromParent = GetApp()->GetCWndFromMap(::GetParent(hwndFrom));
+ if (pWndFromParent != NULL)
+ lr = pWndFromParent->OnNotifyReflect(wParam, lParam);
+ }
+
+ // Handle user notifications
+ if (!lr) lr = OnNotify(wParam, lParam);
+
+ // Set the return code for notifications
+ if (IsWindow())
+ SetWindowLongPtr(DWLP_MSGRESULT, (LONG_PTR)lr);
+
+ return (BOOL)lr;
+ }
+
+ case WM_PAINT:
+ {
+ if (::GetUpdateRect(m_hWnd, NULL, FALSE))
+ {
+ CPaintDC dc(this);
+ OnDraw(&dc);
+ }
+ else
+ // RedrawWindow can require repainting without an update rect
+ {
+ CClientDC dc(this);
+ OnDraw(&dc);
+ }
+
+ break;
+ }
+
+ case WM_ERASEBKGND:
+ {
+ CDC dc((HDC)wParam);
+ BOOL bResult = OnEraseBkgnd(&dc);
+ dc.Detach();
+ if (bResult) return TRUE;
+ }
+ break;
+
+ // A set of messages to be reflected back to the control that generated them
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORSTATIC:
+ case WM_DRAWITEM:
+ case WM_MEASUREITEM:
+ case WM_DELETEITEM:
+ case WM_COMPAREITEM:
+ case WM_CHARTOITEM:
+ case WM_VKEYTOITEM:
+ case WM_HSCROLL:
+ case WM_VSCROLL:
+ case WM_PARENTNOTIFY:
+ return MessageReflect(m_hWnd, uMsg, wParam, lParam);
+
+ } // switch(uMsg)
+ return FALSE;
+
+ } // INT_PTR CALLBACK CPropertyPage::DialogProc(...)
+
+ inline BOOL CPropertyPage::IsButtonEnabled(int iButton) const
+ {
+ assert(::IsWindow(m_hWnd));
+ return GetParent()->GetDlgItem(iButton)->IsWindowEnabled();
+ }
+
+ inline int CPropertyPage::OnApply()
+ {
+ // This function is called for each page when the Apply button is pressed
+ // Override this function in your derived class if required.
+
+ // The possible return values are:
+ // PSNRET_NOERROR. The changes made to this page are valid and have been applied
+ // PSNRET_INVALID. The property sheet will not be destroyed, and focus will be returned to this page.
+ // PSNRET_INVALID_NOCHANGEPAGE. The property sheet will not be destroyed, and focus will be returned;
+
+ return PSNRET_NOERROR;
+ }
+
+ inline void CPropertyPage::OnCancel()
+ {
+ // This function is called for each page when the Cancel button is pressed
+ // Override this function in your derived class if required.
+ }
+
+ inline void CPropertyPage::OnHelp()
+ {
+ // This function is called in response to the PSN_HELP notification.
+ SendMessage(m_hWnd, WM_COMMAND, ID_HELP, 0L);
+ }
+
+ inline BOOL CPropertyPage::OnQueryCancel()
+ {
+ // Called when the cancel button is pressed, and before the cancel has taken place
+ // Returns TRUE to prevent the cancel operation, or FALSE to allow it.
+
+ return FALSE; // Allow cancel to proceed
+ }
+
+ inline BOOL CPropertyPage::OnQuerySiblings(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ // Responds to a query request from the Property Sheet.
+ // The values for wParam and lParam are the ones set by
+ // the CPropertySheet::QuerySiblings call
+
+ // return FALSE to allow other siblings to be queried, or
+ // return TRUE to stop query at this page.
+
+ return FALSE;
+ }
+
+ inline BOOL CPropertyPage::OnInitDialog()
+ {
+ // Called when the property page is created
+ // Override this function in your derived class if required.
+
+ return TRUE; // Pass Keyboard control to handle in WPARAM
+ }
+
+ inline BOOL CPropertyPage::OnKillActive()
+ {
+ // This is called in response to a PSN_KILLACTIVE notification, which
+ // is sent whenever the OK or Apply button is pressed.
+ // It provides an opportunity to validate the page contents before it's closed.
+ // Return TRUE to prevent the page from losing the activation, or FALSE to allow it.
+
+ return FALSE;
+ }
+
+ inline int CPropertyPage::OnOK()
+ {
+ // Called for each page when the OK button is pressed
+ // Override this function in your derived class if required.
+
+ // The possible return values are:
+ // PSNRET_NOERROR. The changes made to this page are valid and have been applied
+ // PSNRET_INVALID. The property sheet will not be destroyed, and focus will be returned to this page.
+ // PSNRET_INVALID_NOCHANGEPAGE. The property sheet will not be destroyed, and focus will be returned;
+
+ return PSNRET_NOERROR;
+ }
+
+ inline LRESULT CPropertyPage::OnNotify(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ LPPSHNOTIFY pNotify = (LPPSHNOTIFY)lParam;
+ switch(pNotify->hdr.code)
+ {
+ case PSN_SETACTIVE:
+ return OnSetActive();
+ case PSN_KILLACTIVE:
+ return OnKillActive();
+ case PSN_APPLY:
+ if (pNotify->lParam)
+ return OnOK();
+ else
+ return OnApply();
+ case PSN_RESET:
+ OnCancel();
+ return FALSE;
+ case PSN_QUERYCANCEL:
+ return OnQueryCancel();
+ case PSN_WIZNEXT:
+ return OnWizardNext();
+ case PSN_WIZBACK:
+ return OnWizardBack();
+ case PSN_WIZFINISH:
+ return OnWizardFinish();
+ case PSN_HELP:
+ OnHelp();
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ inline int CPropertyPage::OnSetActive()
+ {
+ // Called when a page becomes active
+ // Override this function in your derived class if required.
+
+ // Returns zero to accept the activation, or -1 to activate the next or the previous page (depending
+ // on whether the user clicked the Next or Back button). To set the activation to a particular page,
+ // return the resource identifier of the page.
+
+ return 0;
+ }
+
+ inline int CPropertyPage::OnWizardBack()
+ {
+ // This function is called when the Back button is pressed on a wizard page
+ // Override this function in your derived class if required.
+
+ // Returns 0 to allow the wizard to go to the previous page. Returns -1 to prevent the wizard
+ // from changing pages. To display a particular page, return its dialog resource identifier.
+
+ return 0;
+ }
+
+ inline INT_PTR CPropertyPage::OnWizardFinish()
+ {
+ // This function is called when the Finish button is pressed on a wizard page
+ // Override this function in your derived class if required.
+
+ // Return Value:
+ // Return non-zero to prevent the wizard from finishing.
+ // Version 5.80. and later. Return a window handle to prevent the wizard from finishing. The wizard will set the focus to that window. The window must be owned by the wizard page.
+ // Return 0 to allow the wizard to finish.
+
+ return 0; // Allow wizard to finish
+ }
+
+ inline int CPropertyPage::OnWizardNext()
+ {
+ // This function is called when the Next button is pressed on a wizard page
+ // Override this function in your derived class if required.
+
+ // Return 0 to allow the wizard to go to the next page. Return -1 to prevent the wizard from
+ // changing pages. To display a particular page, return its dialog resource identifier.
+
+ return 0;
+ }
+
+ inline BOOL CPropertyPage::PreTranslateMessage(MSG* pMsg)
+ {
+ // allow the tab control to translate keyboard input
+ if (pMsg->message == WM_KEYDOWN && GetAsyncKeyState(VK_CONTROL) < 0 &&
+ (pMsg->wParam == VK_TAB || pMsg->wParam == VK_PRIOR || pMsg->wParam == VK_NEXT))
+ {
+ CWnd* pWndParent = GetParent();
+ if (pWndParent->SendMessage(PSM_ISDIALOGMESSAGE, 0L, (LPARAM)pMsg))
+ return TRUE;
+ }
+
+ // allow the dialog to translate keyboard input
+ if ((pMsg->message >= WM_KEYFIRST) && (pMsg->message <= WM_KEYLAST))
+ {
+ if (IsDialogMessage(pMsg))
+ return TRUE;
+ }
+
+ return CWnd::PreTranslateMessage(pMsg);
+ }
+
+ inline LRESULT CPropertyPage::QuerySiblings(WPARAM wParam, LPARAM lParam) const
+ {
+ // Sent to a property sheet, which then forwards the message to each of its pages.
+ // Set wParam and lParam to values you want passed to the property pages.
+ // Returns the nonzero value from a page in the property sheet, or zero if no page returns a nonzero value.
+
+ assert(::IsWindow(m_hWnd));
+ return GetParent()->SendMessage(PSM_QUERYSIBLINGS, wParam, lParam);
+ }
+
+ inline void CPropertyPage::SetModified(BOOL bChanged) const
+ {
+ // The property sheet will enable the Apply button if bChanged is TRUE.
+
+ assert(::IsWindow(m_hWnd));
+
+ if (bChanged)
+ GetParent()->SendMessage(PSM_CHANGED, (WPARAM)m_hWnd, 0L);
+ else
+ GetParent()->SendMessage(PSM_UNCHANGED, (WPARAM)m_hWnd, 0L);
+ }
+
+ inline void CPropertyPage::SetTitle(LPCTSTR szTitle)
+ {
+ if (szTitle)
+ {
+ m_Title = szTitle;
+ m_PSP.dwFlags |= PSP_USETITLE;
+ }
+ else
+ {
+ m_Title.erase();
+ m_PSP.dwFlags &= ~PSP_USETITLE;
+ }
+
+ m_PSP.pszTitle = m_Title.c_str();
+ }
+
+ inline void CPropertyPage::SetWizardButtons(DWORD dwFlags) const
+ {
+ // dwFlags: A value that specifies which wizard buttons are enabled. You can combine one or more of the following flags.
+ // PSWIZB_BACK Enable the Back button. If this flag is not set, the Back button is displayed as disabled.
+ // PSWIZB_DISABLEDFINISH Display a disabled Finish button.
+ // PSWIZB_FINISH Display an enabled Finish button.
+ // PSWIZB_NEXT Enable the Next button. If this flag is not set, the Next button is displayed as disabled.
+
+ assert (::IsWindow(m_hWnd));
+ PropSheet_SetWizButtons(::GetParent(m_hWnd), dwFlags);
+ }
+
+ inline UINT CALLBACK CPropertyPage::StaticPropSheetPageProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
+ {
+ assert( GetApp() );
+ UNREFERENCED_PARAMETER(hwnd);
+
+ // Note: the hwnd is always NULL
+
+ switch (uMsg)
+ {
+ case PSPCB_CREATE:
+ {
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ assert(pTLSData);
+
+ // Store the CPropertyPage pointer in Thread Local Storage
+ pTLSData->pCWnd = (CWnd*)ppsp->lParam;
+ }
+ break;
+ }
+
+ return TRUE;
+ }
+
+ inline INT_PTR CALLBACK CPropertyPage::StaticDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ assert( GetApp() );
+
+ // Find matching CWnd pointer for this HWND
+ CPropertyPage* pPage = (CPropertyPage*)GetApp()->GetCWndFromMap(hwndDlg);
+ if (0 == pPage)
+ {
+ // matching CWnd pointer not found, so add it to HWNDMap now
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ pPage = (CPropertyPage*)pTLSData->pCWnd;
+
+ // Set the hWnd members and call DialogProc for this message
+ pPage->m_hWnd = hwndDlg;
+ pPage->AddToMap();
+ }
+
+ return pPage->DialogProc(uMsg, wParam, lParam);
+ }
+
+
+ ///////////////////////////////////////////
+ // Definitions for the CPropertySheet class
+ //
+ inline CPropertySheet::CPropertySheet(UINT nIDCaption, CWnd* pParent /* = NULL*/)
+ {
+ ZeroMemory(&m_PSH, sizeof (PROPSHEETHEADER));
+ SetTitle(LoadString(nIDCaption));
+ m_bInitialUpdate = FALSE;
+
+#ifdef _WIN32_WCE
+ m_PSH.dwSize = sizeof(PROPSHEETHEADER);
+#else
+ if (GetComCtlVersion() >= 471)
+ m_PSH.dwSize = sizeof(PROPSHEETHEADER);
+ else
+ m_PSH.dwSize = PROPSHEETHEADER_V1_SIZE;
+#endif
+
+ m_PSH.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK;
+ m_PSH.hwndParent = pParent? pParent->GetHwnd() : 0;
+ m_PSH.hInstance = GetApp()->GetInstanceHandle();
+ m_PSH.pfnCallback = (PFNPROPSHEETCALLBACK)CPropertySheet::Callback;
+ }
+
+ inline CPropertySheet::CPropertySheet(LPCTSTR pszCaption /*= NULL*/, CWnd* pParent /* = NULL*/)
+ {
+ ZeroMemory(&m_PSH, sizeof (PROPSHEETHEADER));
+ SetTitle(pszCaption);
+ m_bInitialUpdate = FALSE;
+
+#ifdef _WIN32_WCE
+ m_PSH.dwSize = PROPSHEETHEADER_V1_SIZE;
+#else
+ if (GetComCtlVersion() >= 471)
+ m_PSH.dwSize = sizeof(PROPSHEETHEADER);
+ else
+ m_PSH.dwSize = PROPSHEETHEADER_V1_SIZE;
+#endif
+
+ m_PSH.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK;
+ m_PSH.hwndParent = pParent? pParent->GetHwnd() : 0;;
+ m_PSH.hInstance = GetApp()->GetInstanceHandle();
+ m_PSH.pfnCallback = (PFNPROPSHEETCALLBACK)CPropertySheet::Callback;
+ }
+
+ inline CPropertyPage* CPropertySheet::AddPage(CPropertyPage* pPage)
+ // Adds a Property Page to the Property Sheet
+ {
+ assert(NULL != pPage);
+
+ m_vPages.push_back(PropertyPagePtr(pPage));
+
+ if (m_hWnd)
+ {
+ // property sheet already exists, so add page to it
+ PROPSHEETPAGE psp = pPage->GetPSP();
+ HPROPSHEETPAGE hpsp = ::CreatePropertySheetPage(&psp);
+ PropSheet_AddPage(m_hWnd, hpsp);
+ }
+
+ m_PSH.nPages = (int)m_vPages.size();
+
+ return pPage;
+ }
+
+ inline void CPropertySheet::BuildPageArray()
+ // Builds the PROPSHEETPAGE array
+ {
+ m_vPSP.clear();
+ std::vector<PropertyPagePtr>::iterator iter;
+ for (iter = m_vPages.begin(); iter < m_vPages.end(); ++iter)
+ m_vPSP.push_back((*iter)->GetPSP());
+
+ PROPSHEETPAGE* pPSPArray = &m_vPSP.front(); // Array of PROPSHEETPAGE
+ m_PSH.ppsp = pPSPArray;
+ }
+
+ inline void CALLBACK CPropertySheet::Callback(HWND hwnd, UINT uMsg, LPARAM lParam)
+ {
+ assert( GetApp() );
+
+ switch(uMsg)
+ {
+ //called before the dialog is created, hwnd = NULL, lParam points to dialog resource
+ case PSCB_PRECREATE:
+ {
+ LPDLGTEMPLATE lpTemplate = (LPDLGTEMPLATE)lParam;
+
+ if(!(lpTemplate->style & WS_SYSMENU))
+ {
+ lpTemplate->style |= WS_SYSMENU;
+ }
+ }
+ break;
+
+ //called after the dialog is created
+ case PSCB_INITIALIZED:
+ {
+ // Retrieve pointer to CWnd object from Thread Local Storage
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ assert(pTLSData);
+
+ CPropertySheet* w = (CPropertySheet*)pTLSData->pCWnd;
+ assert(w);
+
+ w->Attach(hwnd);
+ w->OnCreate();
+ }
+ break;
+ }
+ }
+
+
+ inline HWND CPropertySheet::Create(CWnd* pParent /*= 0*/)
+ // Creates a modeless Property Sheet
+ {
+ assert( GetApp() );
+
+ if (pParent)
+ {
+ m_PSH.hwndParent = pParent->GetHwnd();
+ }
+
+ BuildPageArray();
+ PROPSHEETPAGE* pPSPArray = &m_vPSP.front();
+ m_PSH.ppsp = pPSPArray;
+
+ // Create a modeless Property Sheet
+ m_PSH.dwFlags &= ~PSH_WIZARD;
+ m_PSH.dwFlags |= PSH_MODELESS;
+ HWND hWnd = (HWND)CreatePropertySheet(&m_PSH);
+
+ return hWnd;
+ }
+
+ inline INT_PTR CPropertySheet::CreatePropertySheet(LPCPROPSHEETHEADER ppsph)
+ {
+ assert( GetApp() );
+
+ INT_PTR ipResult = 0;
+
+ // Only one window per CWnd instance allowed
+ assert(!::IsWindow(m_hWnd));
+
+ // Ensure this thread has the TLS index set
+ TLSData* pTLSData = GetApp()->SetTlsIndex();
+
+ // Store the 'this' pointer in Thread Local Storage
+ pTLSData->pCWnd = this;
+
+ // Create the property sheet
+ ipResult = PropertySheet(ppsph);
+
+ return ipResult;
+ }
+
+ inline void CPropertySheet::DestroyButton(int IDButton)
+ {
+ assert(::IsWindow(m_hWnd));
+
+ HWND hwndButton = ::GetDlgItem(m_hWnd, IDButton);
+ if (hwndButton != NULL)
+ {
+ // Hide and disable the button
+ ::ShowWindow(hwndButton, SW_HIDE);
+ ::EnableWindow(hwndButton, FALSE);
+ }
+ }
+
+ inline void CPropertySheet::Destroy()
+ {
+ CWnd::Destroy();
+ m_vPages.clear();
+ }
+
+ inline int CPropertySheet::DoModal()
+ {
+ assert( GetApp() );
+
+ BuildPageArray();
+ PROPSHEETPAGE* pPSPArray = &m_vPSP.front();
+ m_PSH.ppsp = pPSPArray;
+
+ // Create the Property Sheet
+ int nResult = (int)CreatePropertySheet(&m_PSH);
+
+ m_vPages.clear();
+
+ return nResult;
+ }
+
+ inline CPropertyPage* CPropertySheet::GetActivePage() const
+ {
+ assert(::IsWindow(m_hWnd));
+
+ CPropertyPage* pPage = NULL;
+ if (m_hWnd != NULL)
+ {
+ HWND hPage = (HWND)SendMessage(PSM_GETCURRENTPAGEHWND, 0L, 0L);
+ pPage = (CPropertyPage*)FromHandle(hPage);
+ }
+
+ return pPage;
+ }
+
+ inline int CPropertySheet::GetPageCount() const
+ // Returns the number of Property Pages in this Property Sheet
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)m_vPages.size();
+ }
+
+ inline int CPropertySheet::GetPageIndex(CPropertyPage* pPage) const
+ {
+ assert(::IsWindow(m_hWnd));
+
+ for (int i = 0; i < GetPageCount(); i++)
+ {
+ if (m_vPages[i].get() == pPage)
+ return i;
+ }
+ return -1;
+ }
+
+ inline HWND CPropertySheet::GetTabControl() const
+ // Returns the handle to the Property Sheet's tab control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HWND)SendMessage(PSM_GETTABCONTROL, 0L, 0L);
+ }
+
+ inline BOOL CPropertySheet::IsModeless() const
+ {
+ return (m_PSH.dwFlags & PSH_MODELESS);
+ }
+
+ inline BOOL CPropertySheet::IsWizard() const
+ {
+ return (m_PSH.dwFlags & PSH_WIZARD);
+ }
+
+ inline void CPropertySheet::RemovePage(CPropertyPage* pPage)
+ // Removes a Property Page from the Property Sheet
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int nPage = GetPageIndex(pPage);
+ if (m_hWnd != NULL)
+ SendMessage(m_hWnd, PSM_REMOVEPAGE, nPage, 0L);
+
+ m_vPages.erase(m_vPages.begin() + nPage, m_vPages.begin() + nPage+1);
+ m_PSH.nPages = (int)m_vPages.size();
+ }
+
+ inline BOOL CPropertySheet::PreTranslateMessage(MSG* pMsg)
+ {
+ // allow sheet to translate Ctrl+Tab, Shift+Ctrl+Tab, Ctrl+PageUp, and Ctrl+PageDown
+ if (pMsg->message == WM_KEYDOWN && GetAsyncKeyState(VK_CONTROL) < 0 &&
+ (pMsg->wParam == VK_TAB || pMsg->wParam == VK_PRIOR || pMsg->wParam == VK_NEXT))
+ {
+ if (SendMessage(PSM_ISDIALOGMESSAGE, 0L, (LPARAM)pMsg))
+ return TRUE;
+ }
+
+ // allow the dialog to translate keyboard input
+ if ((pMsg->message >= WM_KEYFIRST) && (pMsg->message <= WM_KEYLAST))
+ {
+ return GetActivePage()->PreTranslateMessage(pMsg);
+ }
+
+ return CWnd::PreTranslateMessage(pMsg);
+ }
+
+ inline BOOL CPropertySheet::SetActivePage(int nPage)
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(m_hWnd, PSM_SETCURSEL, nPage, 0L);
+ }
+
+ inline BOOL CPropertySheet::SetActivePage(CPropertyPage* pPage)
+ {
+ assert(::IsWindow(m_hWnd));
+ int nPage = GetPageIndex(pPage);
+ if ((nPage >= 0))
+ return SetActivePage(nPage);
+
+ return FALSE;
+ }
+
+ inline void CPropertySheet::SetIcon(UINT idIcon)
+ {
+ m_PSH.pszIcon = MAKEINTRESOURCE(idIcon);
+ m_PSH.dwFlags |= PSH_USEICONID;
+ }
+
+ inline void CPropertySheet::SetTitle(LPCTSTR szTitle)
+ {
+ if (szTitle)
+ m_Title = szTitle;
+ else
+ m_Title.erase();
+
+ m_PSH.pszCaption = m_Title.c_str();
+ }
+
+ inline void CPropertySheet::SetWizardMode(BOOL bWizard)
+ {
+ if (bWizard)
+ m_PSH.dwFlags |= PSH_WIZARD;
+ else
+ m_PSH.dwFlags &= ~PSH_WIZARD;
+ }
+
+ inline LRESULT CPropertySheet::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+
+ case WM_WINDOWPOSCHANGED:
+ {
+ LPWINDOWPOS lpWinPos = (LPWINDOWPOS)lParam;
+ if (lpWinPos->flags & SWP_SHOWWINDOW)
+ {
+ if (!m_bInitialUpdate)
+ // The first window positioning with the window visible
+ OnInitialUpdate();
+ m_bInitialUpdate = TRUE;
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ m_bInitialUpdate = FALSE;
+ break;
+
+ case WM_SYSCOMMAND:
+ if ((SC_CLOSE == wParam) && (m_PSH.dwFlags & PSH_MODELESS))
+ {
+ Destroy();
+ return 0L;
+ }
+ break;
+ }
+
+ // pass unhandled messages on for default processing
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+}
+
+#endif // _WIN32XX_PROPERTYSHEET_H_