第17章 一応の完成


第15章までで作ったプログラムを実行すると タスクバーに時刻が表示され、これを右クリックすると 自分で改造したシステムメニューが出ました。 この中の「オプション」を選択すると

左のようなダイアログボックスが表示されます。 これに適当な入力を行いOKボタンを押すと

左のようなメッセージボックスが表示されます。

ただそれだけです。

これじゃつまらん!

はい。ダイアログボックスの基本的な解説のために 作っただけです。今回は、ダイアログボックスを 次のように修正して、実際に機能するようにしてみましょう。

今回のプログラムでは使わないコントロールを削除しました。 ヘッダーファイルもいらないIDの定義は削除しておきましょう。
オプションで「時刻」か「日付」かを選んでこれを 表示させるようにします。 プログラムの修正は簡単です。 一番手っ取り早い方法は、GetTimeStr関数に 日付か時刻表示を指定する引数を持たせて time_strにその指定の文字列をコピーするだけですね。

int GetTimeStr(int sw) { char *str_org1 = "%2d時%2d分%2d秒"; char *str_org2 = "%2d年%2d月%2d日"; time_t long_time; struct tm *now_time; time(&long_time); now_time = localtime(&long_time); switch (sw) { case 1: sprintf(time_str, str_org1, now_time->tm_hour, now_time->tm_min, now_time->tm_sec); break; case 0: sprintf(time_str, str_org2, now_time->tm_year, now_time->tm_mon + 1, now_time->tm_mday); break; default: MessageBox(NULL, (LPCSTR)"エラーです", (LPCSTR)"エラー", MB_OK); return (-1); } return 0; }

では、呼び出し側も修正しましょう。ウィンドウプロシージャの中の WM_TIMERの所をほんの少し書き直すだけです。

case WM_TIMER: GetTimeStr(radio1); SetWindowText(hWnd, (LPCSTR)time_str); break;

あとは、GetTimeStr関数のプロトタイプを直すのと、不要な変数の削除だけです。

// 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(int); int SetWinCenter(HWND); HINSTANCE hInst1; char time_str[64]; int radio1 = 1; int radio2 = 0; //ラジオボタンが押されているかどうか 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)); } //ウィンドウの生成 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); 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; } //ウィンドウプロシージャ 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(radio1); 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; } int GetTimeStr(int sw) { char *str_org1 = "%2d時%2d分%2d秒"; char *str_org2 = "%2d年%2d月%2d日"; time_t long_time; struct tm *now_time; time(&long_time); now_time = localtime(&long_time); switch (sw) { case 1: sprintf(time_str, str_org1, now_time->tm_hour, now_time->tm_min, now_time->tm_sec); break; case 0: sprintf(time_str, str_org2, now_time->tm_year, now_time->tm_mon + 1, now_time->tm_mday); break; default: MessageBox(NULL, (LPCSTR)"エラーです", (LPCSTR)"エラー", MB_OK); return (-1); } return 0; } //ダイアログプロシージャ LRESULT CALLBACK MyDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_INITDIALOG: SendMessage(GetDlgItem(hDlgWnd, IDC_RADIO1), BM_SETCHECK, (WPARAM)radio1, 0L); SendMessage(GetDlgItem(hDlgWnd, IDC_RADIO2), BM_SETCHECK, (WPARAM)radio2, 0L); SetWinCenter(hDlgWnd); return TRUE; case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: if(IsDlgButtonChecked(hDlgWnd, IDC_RADIO1) == BST_CHECKED) { radio1 = 1; } else { radio1 = 0;} if(IsDlgButtonChecked(hDlgWnd, IDC_RADIO2) == BST_CHECKED) { radio2 = 1; } else { radio2 = 0;} EndDialog(hDlgWnd, IDOK); break; case IDCANCEL: EndDialog(hDlgWnd, IDCANCEL); break; default: return FALSE; } default: return FALSE; } return TRUE; } int SetWinCenter(HWND hWnd) { HWND hDeskWnd; RECT deskrc, rc; int x, y; hDeskWnd = GetDesktopWindow(); GetWindowRect(hDeskWnd, (LPRECT)&deskrc); GetWindowRect(hWnd, (LPRECT)&rc); x = (deskrc.right - (rc.right-rc.left)) / 2; y = (deskrc.bottom - (rc.bottom-rc.top)) / 2; SetWindowPos(hWnd, HWND_TOP, x, y, (rc.right-rc.left), (rc.bottom-rc.top),SWP_SHOWWINDOW); return 0; }

オプションで、「日付」を選択すると次のようになります。


これで、一応「timer.exe」の完成とします。不満な点はまだいくつもあります。 「日付」を表示している間1秒に1回表示し直す必要があるのか? いったん終了すると、次回起動時は必ず時刻表示になっている。 重複起動してしまう・・などなどです。これらの不満点を解決してみて下さい。


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

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