第103章 タイトルバーに時刻表示


今回は、前回の応用でよそのウィンドウのタイトルバーに 時刻表示をするプログラムを作ります。



「マイコンピュータ」のウィンドウのタイトルバーに時刻が 表示されました。タイトルバーのあるウィンドウならどんなものにも 時刻表示をさせることができます。これは、場所をとらないため 便利です。



外観は前回作ったものと似ていますが、メニューに「時計」「開始」「終了」 の各アイテムが新たに増えています。 作り方は、もう想像がつくと思います。マウスキャプチャで 目的のウィンドウのハンドルを取得します。そして「開始」メニューで そのウィンドウのキャプションを定期的に更新します。 ただ、これだけのことです。実際に作ってみると細かいことで 問題が起きますがおおざっぱな方針は今述べたとおりです。

// mcap03.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&X)", IDM_END END POPUP "時計(&C)" BEGIN MENUITEM "開始(&S)", IDM_START MENUITEM "終了(&E)", IDM_STOP END END ///////////////////////////////////////////////////////////////////////////// // // Cursor // MYCURSOR CURSOR DISCARDABLE "mycursor.cur" ///////////////////////////////////////////////////////////////////////////// // // Bitmap // MYBMP BITMAP DISCARDABLE "mybmp.bmp"

マウスカーソルや、ビットマップは前回のものを流用します。 メニューは「時計」「開始」「終了」が増えました。

// mcap03.cpp #define STRICT #include <windows.h> #include "resource.h" #define ID_MYTIMER 32767 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); BOOL InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); char szClassName[] = "mcap03"; //ウィンドウクラス HINSTANCE hInst; //インスタンスハンドル int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; if (!InitApp(hCurInst)) return FALSE; if (!InitInstance(hCurInst, nCmdShow)) return FALSE; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }

いつもと同じですが、タイマー用のIDをdefineしておきました。

//ウィンドウ・クラスの登録 BOOL InitApp(HINSTANCE hInst) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); 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 = NULL; wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = "MYMENU"; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); return (RegisterClassEx(&wc)); } //ウィンドウの生成 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "猫でもわかるマウスキャプチャー",//タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 250, //幅 150, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; hInst = hInstance; //インスタンスハンドルを保存 ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }

このへんは、毎度同じです。

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; POINTS pts; POINT pt; static HWND hTarget; HDC hdc, hdc_mem; PAINTSTRUCT ps; HBITMAP hBit; BITMAP bmp_info; static int wx, wy; RECT rc; static BOOL bHWND;//ターゲットとなるウィンドウハンドルがあるかどうか static BOOL bClock;//時計が表示されているかどうか static BOOL bCap; //キャプチャー中かどうか SYSTEMTIME st; char *str_org = "%02u:%02u:%02u"; char str[64]; static char title[64]; static HMENU hMenu; switch (msg) { case WM_CREATE: SetCursor(LoadCursor(NULL, IDC_ARROW)); hMenu = GetMenu(hWnd); EnableMenuItem(hMenu, IDM_START, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem(hMenu, IDM_STOP, MF_BYCOMMAND | MF_GRAYED); break; case WM_PAINT: if (!bCap) { GetClientRect(hWnd, &rc); hdc = BeginPaint(hWnd, &ps); hBit = LoadBitmap(hInst, "MYBMP"); GetObject(hBit, sizeof(BITMAP), &bmp_info); wx = bmp_info.bmWidth; wy = bmp_info.bmHeight; hdc_mem = CreateCompatibleDC(hdc); SelectObject(hdc_mem, hBit); BitBlt(hdc, (rc.right - wx)/2, (rc.bottom-wy)/2, wx, wy, hdc_mem, 0, 0, SRCCOPY); DeleteDC(hdc_mem); DeleteObject(hBit); EndPaint(hWnd, &ps); } break; case WM_COMMAND: switch(LOWORD(wp)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0L); break; case IDM_START: GetWindowText(hTarget, title, 64); SetTimer(hWnd, ID_MYTIMER, 500, NULL); bClock = TRUE; EnableMenuItem(hMenu, IDM_START, MF_GRAYED | MF_BYCOMMAND); EnableMenuItem(hMenu, IDM_STOP, MF_ENABLED | MF_BYCOMMAND); break; case IDM_STOP: KillTimer(hWnd, ID_MYTIMER); SetWindowText(hTarget, title); bClock = FALSE; EnableMenuItem(hMenu, IDM_STOP, MF_GRAYED | MF_BYCOMMAND); EnableMenuItem(hMenu, IDM_START, MF_ENABLED | MF_BYCOMMAND); break; } break; case WM_TIMER: GetLocalTime(&st); wsprintf(str, str_org, st.wHour, st.wMinute, st.wSecond); SetWindowText(hTarget, str); break; case WM_LBUTTONDOWN: if(!bClock) { bCap = TRUE; SetCapture(hWnd); SetCursor(LoadCursor(hInst, "MYCURSOR")); InvalidateRect(hWnd, NULL, TRUE); } break; case WM_MOUSEMOVE: if (bCap) { SetCursor(LoadCursor(hInst, "MYCURSOR")); } else SetCursor(LoadCursor(NULL, IDC_ARROW)); break; case WM_LBUTTONUP: if(!bClock) { SetCursor(LoadCursor(NULL, IDC_ARROW)); pts = MAKEPOINTS(lp); pt.x = pts.x; pt.y = pts.y; ClientToScreen(hWnd, &pt); hTarget = WindowFromPoint(pt); if (hTarget == NULL) { MessageBox(hWnd, "失敗です", "失敗", MB_OK); return (DefWindowProc(hWnd, msg, wp, lp)); } ReleaseCapture(); bHWND = TRUE; bCap = FALSE; EnableMenuItem(hMenu, IDM_START, MF_ENABLED | MF_BYCOMMAND); InvalidateRect(hWnd, NULL, TRUE); } break; case WM_CLOSE: id = MessageBox(hWnd, (LPCSTR)"終了してもよいですか", (LPCSTR)"終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { if (bClock) { SetWindowText(hTarget, title); KillTimer(hWnd, ID_MYTIMER); } DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

前回作ったプログラムに少し手を入れただけです。

WM_CREATEメッセージが来たときは、「時計」メニューが 実行できないようにメニューを灰色表示しています。

WM_PAINTメッセージの処理は前回と同じです。

メニューからIDM_STARTが選ばれたときは 相手のウィンドウのタイトルを取得して保存します。
そして、タイマーをセットします。
時計表示の有無の変数bClockをTRUEにします。
「開始」を灰色表示に、「終了」を有効にします。

IDM_STOPが選択されたらタイマーを殺します。 そして、保存してあったウィンドウのタイトルを 元に戻します。
bClockをFALSEにします。
「開始」を有効にして「終了」を灰色表示にします。

WM_TIMERメッセージが来たら現在時刻を表示して hTargetウィンドウのタイトルに時刻を表示します。 今回はwaprintfのstr_orgに%uを使っています。 これは、SYSTYMTIME構造体のwHourメンバなどがWORD値 (unsigned int)なのでこれにあわせたためです。 しかし、wHour, wMinute, wSecondの値はintの範囲を 越えないことは明白なので%dで受けても問題はありません。

WM_LBUTTONDOWNメッセージは時計表示がされていないときのみ 処理をして、表示していないときは何もしません。

WM_LBUTTONUPメッセージも同様です。

他のウィンドウに時計表示をしたままこのプログラムが 終了してはまずいので、終了時にもし時計表示をしていれば タイトルを元に戻して、タイマーを殺しています。

今回は、簡単でした。要するにマウスキャプチャーで目的の ウィンドウのハンドルを取得しタイトルバーにSetWindowTextを 使って時刻を表示しただけです。


[SDK第2部 Index] [総合Index] [Previous Chapter] [Next Chapter]

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