C/C++


アクティブウィンドウの検出・取得

アクティブウィンドウの検出を行いましょう。 アクティブウィンドウの検出とは、現在アクティブになっているウィンドウのウィンドウハンドルを取得しようというものです。

例として、アクティブウィンドウのハンドルを取得してそのクラス名とIDを取得し、 リアルタイムにそれを表示するプログラムを作成します。
まず、プログラムのソースを示します。

001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113

// ActiveWindowのクラス名とIDを出力する // wsprintfを使いLPWSTR型の文字列への代入を行う // Shirao 2009/08/06 #include <windows.h> #define LLEN 80 //テスト用途だから固定 // プロトタイプ宣言 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void ShowText(HWND hWnd); LPCTSTR ClassName = TEXT("GetActWin"); //クラス名 HWND hActWin=NULL; //アクティブなwindow LPWSTR lstr = new wchar_t[LLEN]; LPWSTR actWinName = new wchar_t[LLEN]; //エントリポイント int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInst, LPSTR lpszCmdLine, int nCmdShow) { WNDCLASSEX wcex; HWND hWnd; MSG msg; if (!hPreInst) { wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = NULL; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wcex.lpszMenuName = NULL; wcex.lpszClassName = ClassName; wcex.hIconSm = NULL; if (!RegisterClassEx(&wcex)) return FALSE; } hWnd = CreateWindow(ClassName, TEXT("GetActiveWindow"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 600, 100, NULL, NULL, hInstance, NULL); //ウィンドウを表示 ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); //メッセージループ while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (msg.wParam); } //ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CREATE: //ウィンドウ生成 SetTimer(hWnd, 1, 500, NULL); //TimerIDは1, 0.5秒タイマ break; case WM_DESTROY: //ウィンドウ破棄 KillTimer(hWnd, 1); PostQuitMessage(0); break; case WM_PAINT: hActWin = GetForegroundWindow(); ShowText(hWnd); break; case WM_TIMER: if(wParam == 1) //TimerID == 1? InvalidateRect(hWnd, NULL, TRUE); //再描画 break; default: return(DefWindowProc(hWnd, msg, wParam, lParam)); } return (0); } //指定のウィンドウハンドルにテキストを描画 void ShowText(HWND hWnd) { HDC hdc; PAINTSTRUCT paint; LPWSTR buffer = new wchar_t[LLEN]; hdc = BeginPaint(hWnd, &paint); char ss[] = "ActiveWindowName : "; LONG l = GetWindowLong(hActWin, GWL_ID); //IDを取得 wsprintf(lstr, L"WindowID:%li", l); //LONGは%li GetClassName(hActWin, buffer, LLEN); //アクティブなウィンドウ名 wsprintf(actWinName, L"%hs%s", ss, buffer); //char文字列は%hs, LPWSTRは%s TextOut(hdc, 10, 10, lstr, lstrlen(lstr)); TextOut(hdc, 10, 50, actWinName, lstrlen(actWinName)); EndPaint(hWnd, &paint); return; }

ポイント

アクティブウィンドウの取得

ポイントは、タイマーメッセージごとにアクティブなウィンドウのハンドルを GetForegroundWindowで取得しているこの部分です。

082 083 084 085

case WM_PAINT: hActWin = GetForegroundWindow(); ShowText(hWnd); break;

クラス名、IDの取得と表示

ShowTextは次のような表示関数です。

096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113

//指定のウィンドウハンドルにテキストを描画 void ShowText(HWND hWnd) { HDC hdc; PAINTSTRUCT paint; LPWSTR buffer = new wchar_t[LLEN]; hdc = BeginPaint(hWnd, &paint); char ss[] = "ActiveWindowName : "; LONG l = GetWindowLong(hActWin, GWL_ID); //IDを取得 wsprintf(lstr, L"WindowID:%li", l); //LONGは%li GetClassName(hActWin, buffer, LLEN); //アクティブなウィンドウ名 wsprintf(actWinName, L"%hs%s", ss, buffer); //char文字列は%hs, LPWSTRは%s TextOut(hdc, 10, 10, lstr, lstrlen(lstr)); TextOut(hdc, 10, 50, actWinName, lstrlen(actWinName)); EndPaint(hWnd, &paint); return; }

この関数のポイントはwsprintf関数を使ってLPWSTR型文字列の編集を行っているところでしょうか。 使う機会があるかもしれませんので憶えておくとお得かもしれません。これを使うとマルチバイトcharとか数字とかを まとめてLPWSTRにできるので楽なのです。

もうひとつのポイントは行106のGetClassNameによるクラス名の取得と 行103のGetWindowLongによるIDの取得です。一応今回の主題ですからね。 使い方はコードを見れば分かるかと思います。対象と入れ物、入れ物の大きさを指定するだけですね。

タイマー

タイマーはウィンドウ作成時にSetTimerでセットしています。

075 076 077

case WM_CREATE: //ウィンドウ生成 SetTimer(hWnd, 1, 500, NULL); //TimerIDは1, 0.5秒タイマ break;

このタイマーのIDは1で、500ミリごとにメッセージが送られますから、キャッチは次のようにすればOK。

086 087 088 089

case WM_TIMER: if(wParam == 1) //TimerID == 1? InvalidateRect(hWnd, NULL, TRUE); //再描画 break;

付録

動作画面

実際の動作画面を示しましょう。

ソース・実行ファイル

C++ソースファイルと実行ファイルを置いておきます。


プログラムに戻る