第30章 モードレス・ダイアログボックス


さて、今まで作ってきたダイアログボックスは、 何か決定をしたり、キャセルをするまで ダイアログボックス以外の入力はできませんでした。

前回作ったダイアログボックスも、これが表示されている 間は、メニューなどは選択できませんでした。

そして、決定とかキャンセルが行われると ダイアログボックスは消えてなくなりました。

しかし、このダイアログボックスがでている間も 他のアプリケーションは、自由に使うことができます。 これが、一般的なダイアログボックスですね。 これを、タスク・モーダル なダイアログボックスといいます。 ワープロで、「ファイル」「開く」を選択したときに 出てくるダイアログボックスもたいていこの手の物です。

しかし、「文字列の検索」ダイアログボックスはどうでしょうか。 これが、出ている間も文字を修正したりできますね。 この手のダイアログボックスをモードレス ダイアログボックスといいます。

また、ウィンドウズを終了するときに出てくるダイアログ ボックスはどうでしょうか。これが出ているとそのダイアログボックス 以外、全く入力などができません。こういうのを システム・モーダルといいます。 今回は、モードレス・ダイアログボックスを作ってみます。


実行すると、まず左のようなダイアログボックスが出てきます。 このダイアログボックスで、フォントとか、文字色を決めてやります。 そして、「更新」ボタンを押すと親ウィンドウに表示されていた 文字のフォントとか文字色が変わります。「更新」ボタンを 押しても、ダイアログボックスは ずっと居座っています。 これが、ふつうのダイアログボックスと違うところです。

そして、更新ボタンが押される度にラジオボタンで 設定されたフォントと色に変わります。

うーん、これは作るのが難しいかもしれない・・・

そんなことはありません。

モードレス・ダイアログボックスの作り方 1.CreateDialog関数(32ビット版ではマクロ)で作る 2.不要になったらDestroyWindow関数で壊す

これだけのことです。

ただし、キーボード操作にモードレスダイアログボックスが 応答する場合はメッセージループを次のように書きかえる必要が あります。

while(GetMessage(&msg, NULL, 0, 0)) { if (hDlg == 0 || !IsDialogMessage(hDlg, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }

ここでhDlgはモードレスダイアログボックスのウィンドウハンドルです。 キーボード操作を無視する場合はこの書き換えは不要です。

BOOL IsDialogMessage( HWND hDlg, // ダイアログボックスのハンドル LPMSG lpMsg // MSG構造体のアドレス );

指定のメッセージが指定のダイアログボックスへ送られてきたものか どうかを調べます。

HWND CreateDialog( HINSTANCE hInstance, // インスタンスハンドル LPCTSTR lpTemplate, // ダイアログボックスの名前 HWND hWndParent, // 親ウィンドウのハンドル DLGPROC lpDialogFunc // プロシージャ );

この関数の戻り値がこのダイアログボックスのウィンドウハンドルと なります。

では、早速プログラムを見てみましょう。

// mdless01.rcの一部 // 自力でリソース・スクリプトを書く人は参考にしてください。 ///////////////////////////////////////////////////////////////////////////// // // Dialog // MYDLG DIALOG DISCARDABLE 0, 0, 187, 93 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "猫でもわかるオプション" FONT 9, "MS Pゴシック" BEGIN CONTROL "赤",IDC_RED,"Button",BS_AUTORADIOBUTTON | WS_GROUP,15, 20,23,10 CONTROL "青",IDC_BLUE,"Button",BS_AUTORADIOBUTTON,51,20,23,10 CONTROL "緑",IDC_GREEN,"Button",BS_AUTORADIOBUTTON,87,20,23,10 CONTROL "明朝",IDC_MIN,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13, 67,30,10 CONTROL "ゴシック",IDC_GO,"Button",BS_AUTORADIOBUTTON,66,67,39, 10 DEFPUSHBUTTON "更新",IDOK,130,7,50,14,WS_GROUP PUSHBUTTON "終了",IDCANCEL,130,70,50,14 GROUPBOX "色",IDC_STATIC,7,7,117,31 GROUPBOX "書体",IDC_STATIC,7,53,117,31 CONTROL "MYBMP",IDC_STATIC,"Static",SS_BITMAP,133,22,13,14 END

ま、これは普通のダイアログボックスのリソースです。

// mdless01.cpp #include <windows.h> #include <windowsx.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM); BOOL InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); int DrawMyText(HDC); HFONT SetMyFont(LPCTSTR); int SetMyDlg(HWND); int GetMyDlg(HWND); int SetDraw(HWND); int nCF[5]; //色とフォント LPCSTR szClassName = "mdless01"; //クラス名 HWND hDlg; int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; if (!hPrevInst) { if (!InitApp(hCurInst)) return FALSE; } if (!InitInstance(hCurInst, nCmdShow)) { return FALSE; } while (GetMessage(&msg, NULL, NULL, NULL)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } //ウィンドウ・クラスの登録 BOOL InitApp(HINSTANCE hInst) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; //インスタンス wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; //メニュー名 wc.lpszClassName = szClassName; return (RegisterClass(&wc)); } //ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd, hDlgWnd; hWnd = CreateWindow(szClassName, "猫でもわかるモードレス",//タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 300, //幅 150, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; hDlgWnd = CreateDialog(hInst, "MYDLG", hWnd, (DLGPROC)MyDlgProc); if (hDlgWnd == NULL) return FALSE; hDlg = hDlgWnd; ShowWindow(hDlgWnd, SW_SHOW); ShowWindow(hWnd, SW_SHOW); UpdateWindow(hDlgWnd); UpdateWindow(hWnd); return TRUE; } //ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; HDC hdc; PAINTSTRUCT ps; static HFONT hFont, hFontOld; switch (msg) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); if (nCF[0] > 0) SetTextColor(hdc, RGB(255, 0, 0)); if (nCF[1] > 0) SetTextColor(hdc, RGB(0, 255, 0)); if (nCF[2] > 0) SetTextColor(hdc, RGB(0, 0, 255)); if (nCF[3] > 0) hFont = SetMyFont("MS 明朝"); hFontOld = SelectObject(hdc, hFont); if (nCF[4] > 0) hFont = SetMyFont("MS ゴシック"); hFontOld = SelectObject(hdc, hFont); DrawMyText(hdc); SelectObject(hdc, hFontOld); DeleteObject(hFont); EndPaint(hWnd, &ps); break; case WM_CLOSE: id = MessageBox(hWnd, (LPCSTR)"終了してもよいですか", (LPCSTR)"終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hDlg); DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0L; } LRESULT CALLBACK MyDlgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { static HWND hParent; hParent = GetParent(hWnd); switch (msg) { case WM_INITDIALOG: SetMyDlg(hWnd); return TRUE; case WM_COMMAND: switch(LOWORD(wp)) { case IDOK: GetMyDlg(hWnd); InvalidateRect(hParent, NULL, TRUE); return TRUE; case IDCANCEL: SendMessage(hParent, WM_CLOSE, 0, 0L); return TRUE; } } return FALSE; } int DrawMyText(HDC hdc) { TextOut(hdc, 10, 10, "猫でもわかる", 12); TextOut(hdc, 15, 50, "モードレス", 10); return 0; } HFONT SetMyFont(LPCTSTR face) { HFONT hFont; hFont = CreateFont(40, //フォント高さ 0, //文字幅 0, //テキストの角度 0, //ベースラインとx軸との角度 FW_REGULAR, //フォントの重さ(太さ) FALSE, //イタリック体 FALSE, //アンダーライン FALSE, //打ち消し線 SHIFTJIS_CHARSET, //文字セット OUT_DEFAULT_PRECIS, //出力精度 CLIP_DEFAULT_PRECIS,//クリッピング精度 PROOF_QUALITY, //出力品質 FIXED_PITCH | FF_MODERN,//ピッチとファミリー face); //書体名 return hFont; } int SetMyDlg(HWND hWnd) { Button_SetCheck(GetDlgItem(hWnd, IDC_RED), BST_CHECKED); Button_SetCheck(GetDlgItem(hWnd, IDC_MIN), BST_CHECKED); GetMyDlg(hWnd); InvalidateRect(hWnd, NULL, TRUE); return 0; } int GetMyDlg(HWND hWnd) { int i, id[5]; id[0] = IDC_RED; id[1] = IDC_GREEN; id[2] = IDC_BLUE; id[3] = IDC_MIN; id[4] = IDC_GO; for (i = 0; i <= 4; i++) nCF[i] = Button_GetCheck(GetDlgItem(hWnd, id[i])); return 0; }

とまあ、こんな具合になります。 じつは、ダイアログボックスのコントロールでまだ 説明していない物がありました。それは、ラジオボタンです。 この解説はまた、次回します。(筆者は、今日はもう眠くなった!)

[SDK Index] [総合Index] [Previous Chapter] [Next Chapter]

Update May/07/1997 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。