PropertySheet 选项卡和向导对话框
propertysheet.hpp
#ifndef propertysheetH
#define propertysheetH
#include <windows.h>
#include <commctrl.h>
#include <assert.h>
#include <vector>
#pragma comment (lib, "comctl32.lib")
namespace NSTS {
#define WIZARD_NONE 0
#define WIZARD_HEADERTITLE 1
#define WIZARD_WATERMARK 2
class CPropertyPage {
public:
CPropertyPage (LPCTSTR lpszDlg) {
ZeroMemory (&m_obj, sizeof (m_obj));
m_hSelf = NULL;
m_hHandle = NULL;
m_dwButtons = PSWIZB_NEXT | PSWIZB_BACK; // Just next, unable back, cancel
m_dwStyle = PSP_DEFAULT;
m_lpszDlg = lpszDlg;
assert (m_lpszDlg);
};
CPropertyPage (UINT uDlg) {
ZeroMemory (&m_obj, sizeof (m_obj));
m_hSelf = NULL;
m_hHandle = NULL;
m_dwButtons = PSWIZB_NEXT | PSWIZB_BACK; // Just next, unable back, cancel
m_dwStyle = PSP_DEFAULT;
m_lpszDlg = MAKEINTRESOURCE (uDlg);
assert (m_lpszDlg);
}
~CPropertyPage (void) {};
bool Init (HINSTANCE hInst, bool fWizard = false) {
if (hInst != NULL) {
m_obj.dwSize = sizeof(PROPSHEETPAGE);
m_obj.dwFlags = m_dwStyle;
m_obj.hInstance = hInst;
m_obj.pszTemplate = m_lpszDlg;
m_obj.pfnDlgProc = PageProc;
m_obj.lParam = (LPARAM)this;
m_obj.pfnCallback = NULL;
if (fWizard) {
m_hHandle = CreatePropertySheetPage (&m_obj);
return (m_hHandle != NULL);
}
return true;
}
return false;
};
HPROPSHEETPAGE GetHandle (void) const { return m_hHandle; };
PROPSHEETPAGE GetObj (void) const { return m_obj; };
DWORD GetStyle (void) const { return m_dwStyle; };
void SetStyle (DWORD dwStyle) { m_dwStyle = dwStyle; };
public:
void UseHelpButton (bool fEnable = true) {
if (fEnable) {
m_dwStyle |= PSP_HASHELP;
} else {
m_dwStyle &= ~PSP_HASHELP;
}
};
void EnableBackButton (bool fEnable = true) {
if (fEnable) {
m_dwButtons |= PSWIZB_BACK;
} else {
m_dwButtons &= ~PSWIZB_BACK;
}
assert (m_hSelf);
PropSheet_SetWizButtons (GetParent (m_hSelf), m_dwButtons);
};
void EnableNextButton (bool fEnable = true) {
if (fEnable) {
m_dwButtons |= PSWIZB_NEXT;
} else {
m_dwButtons &= ~PSWIZB_NEXT;
}
assert (m_hSelf);
PropSheet_SetWizButtons (GetParent (m_hSelf), m_dwButtons);
};
void EnableFinishButton (bool fEnable = true) {
m_dwButtons &= ~PSWIZB_FINISH;
m_dwButtons &= ~PSWIZB_DISABLEDFINISH;
if (fEnable) {
m_dwButtons |= PSWIZB_FINISH;
} else {
m_dwButtons &= ~PSWIZB_DISABLEDFINISH;
}
assert (m_hSelf);
PropSheet_SetWizButtons (GetParent (m_hSelf), m_dwButtons);
};
/***/
void SetIcon (UINT uId) {
return SetIcon (MAKEINTRESOURCE (uId));
};
void SetIcon (LPCTSTR lpszIcon) {
m_dwStyle |= PSP_USEICONID;
m_obj.pszIcon = lpszIcon;
};
void SetTitle (LPCTSTR lpszTitle) {
m_dwStyle |= PSP_USETITLE;
m_obj.pszTitle = lpszTitle;
};
void SetHeaderTitle (LPCTSTR lpszHeader) {
m_dwStyle |= PSP_USEHEADERTITLE;
m_obj.pszHeaderTitle = lpszHeader;
};
void SetSubHeaderTitle (LPCTSTR lpszSubHeader) {
m_dwStyle |= PSP_USEHEADERSUBTITLE;
m_obj.pszHeaderSubTitle = lpszSubHeader;
};
void SetHwnd (HWND hwnd) { m_hSelf = hwnd; };
HWND GetSelf (void) const { return m_hSelf; };
public:
virtual void OnInitDialog (void) {};
virtual void OnSetFocus (void) {
PropSheet_Changed (GetParent (m_hSelf), m_hSelf);
};
virtual void OnKillFocus (void) {};
virtual void OnCancel (void) {};
virtual void OnHelp (void) {};
virtual bool OnOk (void) { return true; };
virtual bool OnApply (void) { return true; };
virtual bool OnBack (void) { return true; };
virtual bool OnNext (void) { return true; };
virtual bool OnFinish (void) { return true; };
virtual void OnCommand (WPARAM wParam, LPARAM lParam) {};
virtual void OnNotify (WPARAM wParam, LPARAM lParam) {};
private:
static INT_PTR CALLBACK PageProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam) {
CPropertyPage* ppp = NULL;
ppp = (CPropertyPage*)GetWindowLong (hwnd, GWL_USERDATA);
switch (uMsg) {
case WM_INITDIALOG:
ppp = (CPropertyPage*)((PROPSHEETPAGE*)lParam)->lParam;
assert (ppp);
ppp->SetHwnd (hwnd);
ppp->EnableBackButton (false);
ppp->OnInitDialog ();
SetWindowLong (hwnd, GWL_USERDATA, (LONG)ppp);
break;
case WM_COMMAND:
ppp->OnCommand (wParam, lParam);
return TRUE;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code) {
case PSN_SETACTIVE:
assert (ppp);
ppp->OnSetFocus ();
return TRUE;
case PSN_KILLACTIVE:
assert (ppp);
ppp->OnKillFocus ();
return TRUE;
case PSN_APPLY:
if (((LPPSHNOTIFY) lParam)->lParam) {
assert (ppp);
if (!ppp->OnOk ()) {
SetWindowLong (hwnd, DWL_MSGRESULT, PSNRET_INVALID);
}
} else {
assert (ppp);
if (!ppp->OnApply ()) {
SetWindowLong (hwnd, DWL_MSGRESULT, PSNRET_INVALID);
}
}
return TRUE;
case PSN_HELP:
assert (ppp);
ppp->OnHelp ();
return TRUE;
case PSN_WIZBACK:
assert (ppp);
if (!ppp->OnBack ()) {
SetWindowLong (hwnd, DWL_MSGRESULT, (LONG)-1);
}
return TRUE;
case PSN_WIZNEXT:
assert (ppp);
if (!ppp->OnNext ()) {
SetWindowLong (hwnd, DWL_MSGRESULT, (LONG)-1);
}
return TRUE;
case PSN_WIZFINISH:
assert (ppp);
SetWindowLong (hwnd, DWL_MSGRESULT, ppp->OnFinish () ? (LONG)FALSE : (LONG)TRUE);
return TRUE;
case PSN_RESET:
assert (ppp);
ppp->OnCancel ();
return TRUE;
}
ppp->OnNotify (wParam, lParam);
break;
}
return FALSE;
};
private:
HWND m_hSelf;
PROPSHEETPAGE m_obj;
HPROPSHEETPAGE m_hHandle;
DWORD m_dwStyle;
DWORD m_dwButtons;
LPCTSTR m_lpszDlg;
};
/////////////////////////////////////////////////////
//
class CPropertySheet {
public:
CPropertySheet (HINSTANCE hInst, HWND hParent, bool fWizard = false) {
assert (hParent);
ZeroMemory (&m_sheet, sizeof (PROPSHEETHEADER));
m_vctPages.clear ();
m_phpage = NULL;
m_ppsp = NULL;
m_dwStyle = PSH_DEFAULT | PSH_NOAPPLYNOW;
m_sheet.dwSize = sizeof(PROPSHEETHEADER);
m_sheet.hwndParent = hParent;
m_sheet.hInstance = hInst;
m_sheet.nStartPage = 0;
m_sheet.pfnCallback = NULL;
m_fWizard = fWizard;
m_fUseNeedButton = false;
m_iUseWhich = WIZARD_NONE;
};
~CPropertySheet (void) {
if (m_phpage) delete [] m_phpage;
if (m_ppsp) delete [] m_ppsp;
};
bool Init (void) {
if (m_phpage) {
delete [] m_phpage;
m_phpage = NULL;
}
if (m_ppsp) {
delete [] m_ppsp;
m_ppsp = NULL;
}
m_sheet.dwFlags = m_dwStyle;
m_sheet.nPages = m_vctPages.size ();
for (int iPage = 0; iPage < m_sheet.nPages; ++iPage) {
if (m_fWizard && m_iUseWhich == WIZARD_WATERMARK) {
m_vctPages [iPage]->SetStyle (m_vctPages [iPage]->GetStyle () | PSP_HIDEHEADER);
}
if (m_fUseNeedButton) {
m_vctPages [iPage]->UseHelpButton ();
}
/*** init */
m_vctPages [iPage]->Init (m_sheet.hInstance, m_fWizard);
}
if (!m_fWizard) {
m_sheet.dwFlags = m_dwStyle | PSH_PROPSHEETPAGE;
m_ppsp = new PROPSHEETPAGE [m_sheet.nPages];
for (int i = 0; i < m_sheet.nPages; ++i) {
m_ppsp [i] = m_vctPages [i]->GetObj ();
}
m_sheet.ppsp = m_ppsp;
} else {
if (m_iUseWhich != 0) {
m_sheet.dwFlags = m_dwStyle | PSH_WIZARD97;
} else {
m_sheet.dwFlags = m_dwStyle | PSH_WIZARD;
}
m_phpage = new HPROPSHEETPAGE [m_sheet.nPages];
for (int i = 0; i < m_sheet.nPages; ++i) {
m_phpage [i] = m_vctPages [i]->GetHandle ();
}
m_sheet.phpage = m_phpage;
}
return true;
};
bool AddPage (CPropertyPage* ppp) {
if (ppp == NULL) return false;
m_vctPages.push_back (ppp);
return true;
};
void Display (void) {
Init ();
PropertySheet (&m_sheet);
};
void UseHelpButton (bool fUse = true) {
if (fUse) {
m_dwStyle |= PSH_HASHELP;
m_fUseNeedButton = true;
} else {
m_dwStyle &= ~PSH_HASHELP;
}
};
void UseApplyButton (bool fUse = true) {
if (!fUse) {
m_dwStyle |= PSH_NOAPPLYNOW;
} else {
m_dwStyle &= ~PSH_NOAPPLYNOW;
}
};
void UseHeader (bool fUse = true) {
m_iUseWhich = fUse ? WIZARD_HEADERTITLE : m_iUseWhich & ~WIZARD_HEADERTITLE;
};
void SetIcon (UINT uId) {
return SetIcon (MAKEINTRESOURCE (uId));
};
void SetIcon (LPCTSTR lpszIcon) {
m_dwStyle |= PSH_USEICONID;
m_sheet.pszIcon = lpszIcon;
};
void SetIcon (HICON hIcon) {
m_dwStyle |= PSH_USEHICON;
m_sheet.hIcon = hIcon;
};
void SetTitle (LPCTSTR lpszTitle) {
m_dwStyle |= PSH_PROPTITLE;
m_sheet.pszCaption = lpszTitle;
};
void SetWatermarkBmp (UINT uId) {
return SetWatermarkBmp (MAKEINTRESOURCE (uId));
};
void SetWatermarkBmp (LPCTSTR lpszWater) {
m_dwStyle |= PSH_WATERMARK;
m_sheet.pszbmWatermark = lpszWater;
m_iUseWhich = WIZARD_WATERMARK;
};
void SetWatermarkBmp (HBITMAP hBmp) {
m_dwStyle |= PSH_USEHBMWATERMARK;
m_sheet.hbmWatermark = hBmp;
m_iUseWhich = WIZARD_WATERMARK;
};
void SetHeaderBmp (UINT uId) {
return SetHeaderBmp (MAKEINTRESOURCE (uId));
};
void SetHeaderBmp (LPCTSTR lpszHeader) {
m_sheet.pszbmHeader = lpszHeader;
m_iUseWhich = WIZARD_HEADERTITLE;
};
void SetHeaderBmp (HBITMAP hBmp) {
m_dwStyle |= PSH_USEHBMHEADER;
m_sheet.hbmHeader = hBmp;
m_iUseWhich = WIZARD_HEADERTITLE;
};
private:
PROPSHEETHEADER m_sheet;
PROPSHEETPAGE* m_ppsp;
HPROPSHEETPAGE* m_phpage;
std::vector <CPropertyPage*> m_vctPages;
DWORD m_dwStyle;
int m_iUseWhich;
bool m_fWizard;
bool m_fUseNeedButton;
};
}
#endif // H
Usage:
#include <windows.h>
#include "resource.h"
#include "propertysheet.hpp"
class CMyPage1 : public NSTS::CPropertyPage {
public:
CMyPage1 (LPCTSTR lpszDlg) : NSTS::CPropertyPage (lpszDlg) {};
CMyPage1 (UINT uDlg) : NSTS::CPropertyPage (uDlg) {};
virtual void OnSetFocus (void) {
EnableNextButton ();
EnableBackButton (false);
};
virtual void OnCommand (WPARAM wParam, LPARAM lParam) {
switch (LOWORD (wParam)) {
case IDC_BUTTON1:
MessageBox (GetSelf (), TEXT ("TOUCH ME."), TEXT ("PAGE1"), MB_OK);
break;
}
};
virtual bool OnNext (void) {
return false;
};
};
class CMyPage2 : public NSTS::CPropertyPage {
public:
CMyPage2 (LPCTSTR lpszDlg) : NSTS::CPropertyPage (lpszDlg) {};
CMyPage2 (UINT uDlg) : NSTS::CPropertyPage (uDlg) {};
virtual void OnSetFocus (void) {
EnableBackButton ();
EnableFinishButton ();
};
};
NSTS::CPropertySheet *ps;;
NSTS::CPropertyPage *pg1, *pg2;
HINSTANCE g_hInst;
INT_PTR CALLBACK DialogProc(
HWND hwndDlg, // handle to dialog box
UINT uMsg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
switch (uMsg) {
case WM_INITDIALOG:
{
pg1 = new CMyPage1 (IDD_PAGE1);
pg1->SetTitle (TEXT ("TITLE1"));
pg1->SetIcon (IDI_ICON1);
pg2 = new CMyPage2 (IDD_PAGE2);
pg2->SetTitle (TEXT ("TITLE2"));
pg2->SetIcon (IDI_ICON1);
ps = new NSTS::CPropertySheet (g_hInst, hwndDlg, true);
ps->AddPage (pg1);
ps->AddPage (pg2);
ps->SetIcon (IDI_ICON1);
//#define TEST_HEADER
#ifdef TEST_HEADER
pg1->SetHeaderTitle (TEXT ("HEADER1"));
pg1->SetSubHeaderTitle (TEXT ("SUB HEADER1"));
pg2->SetHeaderTitle (TEXT ("HEADER2"));
pg2->SetSubHeaderTitle (TEXT ("SUB HEADER2"));
ps->UseHeader ();
#else
//ps->SetWatermarkBmp (IDB_BITMAP1);
//ps->UseHelpButton ();
//ps->UseApplyButton ();
#endif
}
break;
case WM_COMMAND:
switch (LOWORD (wParam)) {
case IDOK:
{
ps->Display ();
return TRUE;
}
case IDCANCEL:
EndDialog (hwndDlg, 0);
return TRUE;
}
}
return FALSE;
}
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line
int nCmdShow // show state
)
{
g_hInst = hInstance;
return DialogBox (hInstance, MAKEINTRESOURCE (IDD_MAIN), NULL, DialogProc);
}
/** 注 */
bool OnOk
bool OnApply
bool OnNext
bool OnBack
bool OnFinish
返回真,则是正常,返回假,则不正常,不允许用户进行下一步操作。
如 OnNext 如果返回 false, 则不允许进入下一页.