diff options
author | Petr Mrázek <peterix@gmail.com> | 2013-12-02 00:55:24 +0100 |
---|---|---|
committer | Petr Mrázek <peterix@gmail.com> | 2013-12-02 00:55:24 +0100 |
commit | 6aa9bd0f77dcb5128167fae62e32aa5252fe85c6 (patch) | |
tree | 632994a61888929af9289927d338bd19a2b3f32c /mmc_updater/depends/win32cpp/propertysheet.h | |
parent | 613699b3626aea750093ab7eaaeccaa28c0e87c6 (diff) | |
download | MultiMC-6aa9bd0f77dcb5128167fae62e32aa5252fe85c6.tar MultiMC-6aa9bd0f77dcb5128167fae62e32aa5252fe85c6.tar.gz MultiMC-6aa9bd0f77dcb5128167fae62e32aa5252fe85c6.tar.lz MultiMC-6aa9bd0f77dcb5128167fae62e32aa5252fe85c6.tar.xz MultiMC-6aa9bd0f77dcb5128167fae62e32aa5252fe85c6.zip |
Renew the updater branch
Now with some actual consensus on what the updater will do!
Diffstat (limited to 'mmc_updater/depends/win32cpp/propertysheet.h')
-rw-r--r-- | mmc_updater/depends/win32cpp/propertysheet.h | 960 |
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_ |