モーダルダイアログボックスを作成する関数には、DialogBoxの他にDialogBoxParamがある。
https://msdn.microsoft.com/ja-jp/library/cc410761.aspx
int DialogBoxParam( HINSTANCE hInstance, // アプリケーションのインスタンスのハンドル LPCTSTR lpTemplateName, // ダイアログボックステンプレートを指定します HWND hWndParent, // オーナーウィンドウのハンドル DLGPROC lpDialogFunc, // ダイアログボックスプロシージャへのポインタ LPARAM dwInitParam // 初期値 );
この初期値と呼ばれる第五引数dwInitParamは何かというと、ダイアログ初期化の際に呼ばれるWM_INITDIALOGのlParam値である。
オブジェクト指向ではないDialogBoxにとって、DialogBoxに渡せる、ユーザが任意に指定できるグローバル変数以外の唯一のパラメータがこれなのである。
以下はこのdwInitParamで初期値を渡す例である:
#include <Windows.h> #include "resource.h" #include <tchar.h> //ダイアログプロシージャ INT_PTR CALLBACK WndProcModal(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: if (lParam) { TCHAR* c = (TCHAR*)lParam; MessageBox(hWnd, c, 0, 0); } return TRUE; case WM_COMMAND: switch (wParam) { case IDOK: MessageBox(hWnd, _T("IDOK"), 0, 0); EndDialog(hWnd, 0); return TRUE; } return FALSE; } return FALSE; } //エントリーポイント int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR lpCmdLine,int nCmdShow) { DialogBoxParam( hInstance, MAKEINTRESOURCE(IDD_DIALOG1), nullptr, WndProcModal, (LPARAM)_T("鵺")//このパラメータがWM_INITDIALOGのlParamへ入る ); return 0; }
要はCreateWindow関数の第十一引数lpParam「ウィンドウ作成データ」と同じ性質の物だと思えばいい。
https://msdn.microsoft.com/ja-jp/library/cc410713.aspx
これを使えば、CreateWindow関数の時と同様に、DialogBoxをカプセル化できる。考え方はCreateWindowの時と同じだ。
CnuDlgModal.h
#pragma once #include <windows.h> class CnuDlgModal{ INT_PTR m_dlg;//DialogBoxの戻り値 HINSTANCE m_hInstance; //このクラスで作成したモーダルダイアログの全てのイベントが入ってくるダイアログプロシージャ static INT_PTR CALLBACK StaticWndProcDlg(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); public: HINSTANCE GetHInstance()const { return m_hInstance; } virtual ~CnuDlgModal() {} //DialogBoxParam関数の呼び出し INT_PTR nuDialogBox( const HINSTANCE hInst, LPCTSTR lpTemplate, HWND hWndParent ); //個別のウィンドウプロシージャ virtual INT_PTR WndProcDlg( HWND hWnd, UINT msg, WPARAM wp, LPARAM lp ); };
CnuDlgModal.cpp
#include "CnuDlgModal.h" //このクラスで作成したモーダルダイアログの全てのイベントが入ってくるダイアログプロシージャ INT_PTR CALLBACK CnuDlgModal::StaticWndProcDlg(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { CnuDlgModal* This = (CnuDlgModal*)GetWindowLongPtr(hWnd, GWLP_USERDATA); if (message == WM_INITDIALOG) { if (lParam) { This = (CnuDlgModal*)lParam; SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)This); return This->WndProcDlg(hWnd, message, wParam, lParam); } } else if (This == 0) { return FALSE; } return This->WndProcDlg(hWnd, message, wParam, lParam); } ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// //DialogBoxParam関数の呼び出し INT_PTR CnuDlgModal::nuDialogBox( const HINSTANCE hInst, LPCTSTR lpTemplate, HWND hWndParent ) { m_hInstance = hInst; m_dlg = DialogBoxParam(GetHInstance(), lpTemplate, hWndParent, (DLGPROC)CnuDlgModal::StaticWndProcDlg, (LPARAM)this); return m_dlg; } //個別のウィンドウプロシージャ INT_PTR CnuDlgModal::WndProcDlg( HWND hWnd, UINT msg, WPARAM wp, LPARAM lp ) { switch (msg) { case WM_CLOSE: EndDialog(hWnd, 0); PostQuitMessage(0); return TRUE; } return FALSE; }
main.cpp
#include <Windows.h> #include "resource.h" #include <tchar.h> #include "CnuDlgModal.h" //モーダルダイアログを扱うクラス class CnuDlgModal_special :public CnuDlgModal { //CnuDlgModalからオーバーライド。このために親クラスでvirtual指定をしている INT_PTR WndProcDlg(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp) override{ switch (msg) { case WM_COMMAND: switch (wp) { case IDOK: EndDialog(hWnd, 100); return TRUE; } return FALSE; case WM_CLOSE: EndDialog(hWnd, 0); return TRUE; } return FALSE; } }; /////////////////////////////////////////////////////// //エントリーポイント//////////////////////////////////// int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) { CnuDlgModal_special modalsp;//新たなモーダルダイアログを定義 modalsp.nuDialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), nullptr);//ダイアログ作成・待機 PostQuitMessage(0); return 0; }
CnuDlgModal.zip