Renew the updater branch
Now with some actual consensus on what the updater will do!
This commit is contained in:
960
mmc_updater/depends/win32cpp/propertysheet.h
Normal file
960
mmc_updater/depends/win32cpp/propertysheet.h
Normal file
@ -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_
|
Reference in New Issue
Block a user