前回は通常のプロパティシートを作成しましたが、
CPropertySheetImplクラスのメンバ関数であるSetWizardMode()
を呼び出すことによってウィザードタイプのプロパティシートを作成することができます。
CPropertyPage<IDD_PROPPAGE_VERSION> page;
CPropertySheet sheet;
sheet.AddPage(page);
sheet.SetWizardMode(); // ウィザードモードに設定
sheet.DoModal();
|
まず、前回作成したプロパティページ用のダイアログリソースIDD_PROPPAGE_VERSION
を指定してプロパティページを作成し、それをプロパティシートに追加します。
そしてSetWizardMode()によってウィザードモードにします。
また、ダイアログリソースのタイトル文字列がウィザードのタイトルとして表示されます。
このように、ウィザードモードのプロパティシートの作成は通常のプロパティシートの場合とあまり変わりありません。
ところで、上の例では[完了]ボタンがありません。
また、プロパティページ上のコントロールがある条件を満たした場合だけ
[次へ]ボタンを有効にしたいということがあるでしょう。
そのような場合は、CPropertyPageImplクラスから派生させた独自のプロパティーページクラスを作成し、
その中でSetWizardButtons()を呼び出してボタンの状態を設定します。
次に示すのは、CPropertySheetImplクラスやCPropertyPageImplクラスから派生クラスを作成し、
独自のウィザードモードプロパティシートを作成する例です。
まずプロジェクトにプロパティページ用のダイアログリソースを2つ追加し、
それぞれIDをIDD_PROPPAGE_CUSTOMとIDD_PROPPAGE_FINISHに変更します。
1つ目のダイアログリソース(ID:IDD_PROPPAGE_CUSTOM)にはIDがIDC_CHECK_NEXT
のチェックボックスを追加します。
次に、CustomWizard.hというヘッダファイルを用意し、
そこにCCustomPage、CFinishPageというプロパティページクラスと、
CCustomWizardというプロパティシートクラスを定義します。
// CustomWizard.h内
class CCustomPage : public CPropertyPageImpl<CCustomPage>
{
CButton m_button_topmost;
public:
enum { IDD = IDD_PROPPAGE_CUSTOM };
// コンストラクタ
CCustomPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL)
: CPropertyPageImpl<CCustomPage>(title)
{}
BEGIN_MSG_MAP_EX(CCustomPage)
MSG_WM_INITDIALOG(OnInitDialog)
COMMAND_ID_HANDLER_EX(IDC_CHECK_NEXT, OnCheckNext)
CHAIN_MSG_MAP(CPropertyPageImpl<CCustomPage>)
END_MSG_MAP()
LRESULT OnInitDialog(HWND hWnd, LPARAM lParam){
m_button_topmost = GetDlgItem(IDC_CHECK_NEXT);
return TRUE;
}
void OnCheckNext(UINT uNotifyCode, int nID, HWND hWndCtl){
OnSetActive();
}
BOOL OnSetActive(){
// チェックボックスがチェックされている場合は[次へ]ボタンを有効にし、
// そうでなければ無効にする。[戻る]ボタンは常に無効。
SetWizardButtons(m_button_topmost.GetCheck() ? PSWIZB_NEXT : 0);
return TRUE;
}
};
class CFinishPage : public CPropertyPageImpl<CFinishPage>
{
public:
enum { IDD = IDD_PROPPAGE_FINISH };
// コンストラクタ
CFinishPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL)
: CPropertyPageImpl<CFinishPage>(title)
{}
BEGIN_MSG_MAP_EX(CFinishPage)
CHAIN_MSG_MAP(CPropertyPageImpl<CFinishPage>)
END_MSG_MAP()
BOOL OnSetActive(){
// [戻る]ボタンと[完了]ボタンを有効にする。
// なお、[次へ]ボタンは[完了]ボタンに置き換えられる。
SetWizardButtons(PSWIZB_BACK | PSWIZB_FINISH);
return TRUE;
}
};
class CCustomWizard : public CPropertySheetImpl<CCustomWizard>
{
public:
CCustomPage m_pageCustom;
CFinishPage m_pageFinish;
// コンストラクタ
CCustomWizard(ATL::_U_STRINGorID title = (LPCTSTR)NULL,
UINT uStartPage = 0, HWND hWndParent = NULL)
: CPropertySheetImpl<CCustomWizard>(title, uStartPage, hWndParent)
{
SetWizardMode(); // ウィザードモードに設定
AddPage(m_pageCustom);
AddPage(m_pageFinish);
}
BEGIN_MSG_MAP_EX(CCustomWizard)
CHAIN_MSG_MAP(CPropertySheetImpl<CCustomWizard>)
END_MSG_MAP()
};
|
CCustomPageクラスはウィザードの1ページ目を表します。
このプロパティページにはチェックボックスが一つあり、
チェックを入れるとSetWizardButtons(PSWIZB_NEXT)が呼び出されて[次へ]ボタンが有効になります。
なお、OnSetActive()はプロパティページがアクティブになるたびに呼び出されますが、
プロパティページが最初に表示されたときはチェックボックスはチェックされていないので、
SetWizardButtons(0)が呼び出されて[戻る]ボタンも[次へ]ボタンも無効になります。
CFinishPageクラスはウィザードの2ページ目を表します。
このプロパティページはスタティックコントロールでメッセージを表示しているだけです。
なお、このページがウィザードの最後なのでOnSetActive()では
PSWIZB_FINISHを指定してSetWizardButtons()を呼び出すことにより、
[次へ]ボタンを[完了]ボタンに変更しています。
このように、[次へ]ボタンと[完了]ボタンは共通のボタンを使用します。
CCustomWizardクラスは上記の2つのプロパティページクラスのインスタンスをメンバ変数に持ち、
コンストラクタでAddPage()を呼び出すことによって追加しています。
また、コンストラクタではSetWizardMode()を呼び出してプロパティシートをウィザードモードにしています。
次に示すのは、CCustomWizardクラスを使用する例です。
// stdafx.h内
#include <atlbase.h>
#include <atlapp.h>
extern CAppModule _Module;
#include <atlwin.h>
#include <atlcrack.h>
#include <atlmisc.h>
#include <atlctrls.h>
#include <atldlgs.h> // コモンダイアログを使用するため
|
// maindlg.h内
class CMainDlg : public CDialogImpl<CMainDlg>
{
public:
enum { IDD = IDD_MAINDLG };
// メッセージマップ
BEGIN_MSG_MAP_EX(CMainDlg)
MSG_WM_INITDIALOG(OnInitDialog)
COMMAND_ID_HANDLER_EX(IDC_BUTTON_OPENDLG, OnButtonOpenDlg)
COMMAND_ID_HANDLER_EX(IDOK, OnOK)
COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel)
END_MSG_MAP()
LRESULT OnInitDialog(HWND hWnd, LPARAM lParam){
// スクリーンの中央に配置
CenterWindow();
// 大きいアイコン設定
HICON hIcon = AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR,
::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON));
SetIcon(hIcon, TRUE);
// 小さいアイコン設定
HICON hIconSmall = AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR,
::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON));
SetIcon(hIconSmall, FALSE);
return TRUE;
}
void OnButtonOpenDlg(UINT uNotifyCode, int nID, HWND hWndCtl){
CCustomWizard wizard;
if(wizard.DoModal() == IDOK){
// [完了]ボタンを押して閉じた時の処理
}
}
void OnOK(UINT uNotifyCode, int nID, HWND hWndCtl){
EndDialog(nID);
}
void OnCancel(UINT uNotifyCode, int nID, HWND hWndCtl){
EndDialog(nID);
}
};
|
// CommDlg.cpp内
#include "stdafx.h"
#include "resource.h"
#include "CustomWizard.h"
#include "maindlg.h"
CAppModule _Module;
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR lpCmdLine, int nCmdShow)
{
HRESULT hRes = ::CoInitialize(NULL);
ATLASSERT(SUCCEEDED(hRes));
::DefWindowProc(NULL, 0, 0, 0L);
AtlInitCommonControls(ICC_COOL_CLASSES | ICC_WIN95_CLASSES);
hRes = _Module.Init(NULL, hInstance);
ATLASSERT(SUCCEEDED(hRes));
int nRet = 0;
// BLOCK: アプリケーション実行
{
CMainDlg dlgMain;
nRet = dlgMain.DoModal();
}
_Module.Term();
::CoUninitialize();
return nRet;
}
|
まず、リソースを作成します。ダイアログにボタンコントロールを配置し、
リソースIDを次のように指定します。
| コントロール名 |
リソースID |
| プッシュボタン |
IDC_BUTTON_OPENDLG |
次に、stdafx.h内では、atldlgs.hヘッダをインクルードします。
CMainDlgクラスでは、ボタン用のコマンドメッセージハンドラ
OnButtonOpenDlg()を追加し、
そこでCCustomWizardクラスのインスタンスを作成して
DoModal()によって独自のウィザードモードプロパティシートを表示します。
なお、表示したウィザードモードのプロパティシートを[完了]ボタンを押して閉じると、
DoModal()はIDOKを返します。
最後に、CommDlg.cpp内でmaindlg.hヘッダの前にCustomWizard.hヘッダをインクルードします。
|