これが32ビット版DialogBox関数です。 最初の引数はWinMain関数の第1引数と同じと考えてよい。 2番目の引数は、ダイアローグボックスのテンプレートの名前。 自分で作ったのならその名前を指定します。 3番目は、親ウィンドウの名前。最後は、このダイアログボックスの プロシージャ関数の名前。と簡単に覚えておきましょう。int DialogBox( HINSTANCE hInstance, // アプリケーションインスタンスハンドル LPCTSTR lpTemplate, // ダイアログボックステンプレート HWND hWndParent, // 親ウィンドウ DLGPROC lpDialogFunc // ダイアログプロシージャ );
さて、最初の引数ですがWinMain関数のところでグローバル変数に コピーしておくというのが最も簡単な方法です。 (他にもいろいろな方法があります。) 次が、ダイアログボックスの終了関数です。
となっています。 では、さっそくプログラムを書いてみましょう。BOOL EndDialog( HWND hDlg, // ダイアログボックスのウィンドウハンドル int nResult // DialogBoxへ戻す値 );
ここまでは、前回までと殆ど同じです。ただ、hInst1というグローバル変数 を作って、hCurInstをコピーするのを付け加えただけです。 あとでこのhInst1が必要になってきます。 また、ダイアログプロシージャのプロトタイプ宣言をしています。// timer.cpp #include <windows.h> #include <time.h> #include <stdio.h> #include "timer.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM); BOOL InitApp(HINSTANCE, LPCSTR); BOOL InitInstance(HINSTANCE, LPCSTR, int); int GetTimeStr(void); HINSTANCE hInst1; //インスタンスハンドル char time_str[256]="123"; int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; char szClassName[] = "timer"; //ウィンドウクラス hInst1 = hCurInst; //グローバル変数にコピー if (!hPrevInst) { if (!InitApp(hCurInst, szClassName)) return FALSE; } if (!InitInstance(hCurInst, szClassName, nCmdShow)) { return FALSE; } while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }
ここも前回と同じです。//ウィンドウ・クラスの登録 BOOL InitApp(HINSTANCE hInst, LPCSTR szClassName) { 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/*"TIMERMENU"*/; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; return (RegisterClass(&wc)); }
ここでは、AppendMenu関数の3番目の引数と、4番目の引数を少し変えています。 したがって、ヘッダーファイルも修正する必要があります。//ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, LPCSTR szClassName, int nCmdShow) { HWND hWnd; HMENU hMenu; int i; hWnd = CreateWindow(szClassName, NULL, //タイトルバーにこの名前が表示されます WS_CAPTION | WS_SYSMENU, //ウィンドウの種類 9999, //X座標 9999, //Y座標 0, //幅 0, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, SW_MINIMIZE/*nCmdShow*/); UpdateWindow(hWnd); hMenu = GetSystemMenu(hWnd, FALSE); for (i = 0; i <= 5; i++) DeleteMenu(hMenu, 0, MF_BYPOSITION); AppendMenu(hMenu, MF_STRING, IDM_OPTION, "オプション"); DrawMenuBar(hWnd); return TRUE; }
WM_SYSCOMMANDのIDM_OPTIONのところで、ダイアログボックス 関数を使っています。システムメニューのIDM_OPTIONが選ばれたら ダイアログボックスが出てくるという仕組みです。本来 この関数の戻り値でさらに処理を振り分けますが、ここでは 簡単のために、単にダイアログボックスを呼び出しているのみです。//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; switch (msg) { case WM_SYSCOMMAND: switch (wp) { case IDM_OPTION: DialogBox(hInst1, "OPTDLG", hWnd, (DLGPROC)MyDlgProc); break; default: return(DefWindowProc(hWnd, msg, wp, lp)); break; } break; case WM_CREATE: if(SetTimer(hWnd, ID_MYTIMER, 1000, NULL) == 0) { MessageBox(hWnd, (LPCSTR)"タイマー失敗!", (LPCSTR)"失敗", MB_OK | MB_ICONEXCLAMATION); } break; case WM_TIMER: GetTimeStr(); SetWindowText(hWnd, (LPCSTR)time_str); break; case WM_CLOSE: id = MessageBox(hWnd, (LPCSTR)"終了してもよいですか", (LPCSTR)"終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { if(KillTimer(hWnd, ID_MYTIMER) == TRUE) { MessageBox(hWnd, (LPCSTR)"タイマーを殺しました!", (LPCSTR)"タイマー削除の成功", MB_OK | MB_ICONEXCLAMATION); } DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0L; }
ここで、新しく出てきたダイアログボックスのプロシージャです。 ウィンドウプロシージャと似ていますね。WM_CREATEに相当するのが WM_INITDIALOGです。ここでは何もしないのでFALSEを返しています。 メッセージをきちんと処理したらTRUEを返すようにします。LRESULT CALLBACK MyDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_INITDIALOG: return FALSE; case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: EndDialog(hDlgWnd, IDOK); break; case IDCANCEL: EndDialog(hDlgWnd, IDCANCEL); break; default: return FALSE; } default: return FALSE; } return TRUE; }
現在時刻を文字列に整形する関数です。int GetTimeStr(void) { char *str_org = "%2d時%2d分%2d秒"; time_t long_time; struct tm *now_time; time(&long_time); now_time = localtime(&long_time); sprintf(time_str, str_org, now_time->tm_hour, now_time->tm_min, now_time->tm_sec); return 0; }
ヘッダーファイルはIDM_OPTIONを付け加えました。(IDM_TESTは削除)// timer.h #define IDM_END 1000 #define IDM_OPTION 2000 #define IDC_STATIC 3000 #define ID_MYTIMER 32767
また、ダイアログボックスのところで使うIDC_STATICを加えています。
はい。これらをビルドして実行するとタスクバーに 時刻を表示するアイコンが出現します。 そして、それを右クリックしてシステムメニューを出し 「オプション」を選択すると#include "windows.h" #include "timer.h" ////////////////////////////////////////////////////// // // Dialog // OPTDLG DIALOG DISCARDABLE 0, 0, 121, 69 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "オプション" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "OK",IDOK,7,38,50,14 PUSHBUTTON "キャンセル",IDCANCEL,61,37,50,14 LTEXT "オブションです。",IDC_STATIC,36,19,48,8 END
左のようなダイアログボックスが出現します。
(ただし、見た目はメッセージボックスと殆ど同じですね。)
という感じで使います。DialogBoxの最後の引数に 直接プロシージャの名前(アドレス)を指定してはいけません。 逆に32ビット版でこのように書いても問題はありません。static FARPROC fnDlgProc; ・・・・・・略 fnDlgProc = MakeProcInstance((FARPROC)DlgProc, hInst); ・・・・・・略 DialogBox(hInst, "MYDLG", hWnd, fnDlgProc);
Update Apr/04/1997 By Y.Kumei