「hWnd から pid はどう取得するのか」「hWnd から EXE名はどう取得するのか」などの変換方法をまとめてみました。
一覧
変換方法の一覧です。
変換するには「どの Win32API を使うのか」といった変換方法の概要を記載しています。「変換元→変換先」のリンクをクリックするとページ内のサンプルコードへ飛びます。
変換元 → 変換先 | 取得方法の概要 |
---|---|
hWnd → pid | GetWindowThreadProcessId() を使う。 |
hWnd → EXE名 | hWnd から GetWindowThreadProcessId() で pid を取得し、pid から OpenProcess() で hProcess を取得し、hProcess から QueryFullProcessImageName() で EXE名を取得する。 |
hWnd → クラス名 | GetClassName() を使う。 |
hWnd → ウィンドウ名 | GetWindowText() を使う。 |
hWnd → ウィンドウスタイル | GetWindowLong(hWnd, GWL_STYLE) を使う。 |
hWnd → 拡張ウィンドウスタイル | GetWindowLong(hWnd, GWL_EXSTYLE) を使う。 |
pid → hWnd | 複数あるため全て取れるようにする。EnumWindows()に入ってきた hWnd から GetWindowThreadProcessID() で pid を取得し、探している pid と一致する hWnd を取得する。 |
pid → EXE名 | pid から OpenProcess() で hProcess を取得し、hProcess から QueryFullProcessImageName() で EXE名を取得する。 |
EXE名 → pid | 複数あるため全て取れるようにする。CreateToolhelp32Snapshot() でシステムの全プロセスをスナップショットし、Process32First() から Process32Next() しながらスナップショットの中から探している EXE名と一致する pid を取得する。 |
EXE名 → hWnd | EXE名に対応する pid が複数あり、更に pid 毎に対応する hWnd が複数あるため全て取れるようにする。このページに記載しているEXE名→pid の方法 と pid→hWnd の方法 を組み合わせて取得する。 |
クラス名 → hWnd | 複数あるため全て取れるようにする。EnumWindows()に入ってきた hWnd から GetClassName() で クラス名 を取得し、探している クラス名 と一致する hWnd を取得する。 |
ウィンドウ名 → hWnd | 複数あるため全て取れるようにする。EnumWindows()に入ってきた hWnd から GetWindowText() で ウィンドウ名 を取得し、探している ウィンドウ名 と一致する hWnd を取得する。 |
文中の略語は以下を意味しています。
- hWnd : ウィンドウハンドル
- pid : プロセスID
- EXE名 : 実行可能ファイル名
- ウィンドウ名 : ウィンドウのタイトルバーのテキストのことです。キャプションやウィンドウテキストと書かれることもあります。
hWnd → *
hWnd → pid
ウィンドウハンドル から プロセスID を取得するには GetWindowThreadProcessId() を使います。
DWORD GetPidFormHwnd(HWND hWnd)
{
DWORD pid;
DWORD succeeded = GetWindowThreadProcessId(hWnd, &pid);
return succeeded ? pid : 0;
}
hWnd → EXE名
ウィンドウハンドル から EXE名 を取得するには、ウィンドウハンドル から GetWindowThreadProcessId() で プロセスID を取得し、プロセスID から OpenProcess() で hProcess を取得し、hProcess から QueryFullProcessImageName() で EXE名を取得します。
UnicodeString GetExePathFromHwnd(HWND hWnd)
{
UnicodeString result;
DWORD pid;
if (GetWindowThreadProcessId(hWnd, &pid) == 0)
return "";
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, -1, pid);
if (hProcess == NULL)
return "";
const int BUFSIZE = 1024;
wchar_t exePath[BUFSIZE];
unsigned long len = BUFSIZE;
BOOL succeeded = QueryFullProcessImageName(hProcess, 0, exePath, &len);
result = (succeeded)? UnicodeString(exePath) : "";
CloseHandle(hProcess);
return result;
}
hWnd → クラス名
ウィンドウハンドル から クラス名 を取得するには GetClassName() を使います。
UnicodeString GetClassNameFromHwnd(HWND hWnd)
{
const int BUFSIZE = 256;
wchar_t ClassName[BUFSIZE];
GetClassName(hWnd, ClassName, BUFSIZE);
return ClassName;
}
hWnd → ウィンドウ名
ウィンドウハンドル から ウィンドウ名 を取得するには GetWindowText() を使います。
UnicodeString GetCaptionFromHwnd(HWND hWnd)
{
const int BUFSIZE = 256;
wchar_t Caption[BUFSIZE];
GetWindowText(hWnd, Caption, BUFSIZE);
return Caption;
}
hWnd → ウィンドウスタイル
ウィンドウハンドル から ウィンドウスタイル を取得するには、GetWindowLong(hWnd, GWL_STYLE) を使います。
int GetWindowStyleFromHwnd(HWND hWnd)
{
return GetWindowLong(hWnd, GWL_STYLE);
}
hWnd → 拡張ウィンドウスタイル
ウィンドウハンドル から 拡張ウィンドウスタイル を取得するには、GetWindowLong(hWnd, GWL_EXSTYLE) を使います。
int GetWindowExStyleFromHwnd(HWND hWnd)
{
return GetWindowLong(hWnd, GWL_EXSTYLE);
}
pid → *
pid → hWnd
pid に対応する ウィンドウハンドル は複数あるため、下記の FindHwndsFromPid() のような関数を作って、一致する 全ての ウィンドウハンドルを取得します。
EnumWindows()に入ってきた ウィンドウハンドル から GetWindowThreadProcessID() で プロセスID を取得し、探している プロセスID と一致する ウィンドウハンドル を取得していきます。
// _EnumWindowsProc() に渡す構造体
struct _EnumWindowsArg {
DWORD targetPid; // 検索対象のプロセスID
std::vector<HWND> *foundWindowHandles; // 一致したウィンドウハンドルが格納される
_EnumWindowsArg(DWORD targetPid, std::vector<HWND>& foundWindowHandles) {
this->targetPid = targetPid;
this->foundWindowHandles = &foundWindowHandles;
}
};
// 関数宣言
BOOL __stdcall _EnumWindowsProc(HWND hWnd, LPARAM lp);
/*
* FindHwndsFromPid()
* pid : 指定した pid (プロセスID) に一致するウィンドウハンドルを探す。
* hWnds : pid に一致したウィンドウハンドルのリストが格納される。
*/
void FindHwndsFromPid(DWORD pid, std::vector<HWND>& hWnds)
{
_EnumWindowsArg args = _EnumWindowsArg(pid, hWnds);
EnumWindows((WNDENUMPROC)_EnumWindowsProc, (LPARAM)&args);
}
// EnumWindows に呼んで貰うコールバック関数
BOOL __stdcall _EnumWindowsProc(HWND hWnd, LPARAM lp)
{
_EnumWindowsArg *args = (_EnumWindowsArg*)lp;
// hWnd → pid を取得して、探している pid でなければスキップする
DWORD pid;
if (GetWindowThreadProcessId(hWnd, &pid) == 0) return TRUE;
if (pid != args->targetPid) return TRUE;
// 見つかったウィンドウハンドルをリストに追加する。
args->foundWindowHandles->push_back(hWnd);
// _EnumWindowsProc を継続して次へ
return TRUE;
}
使用例
std::vector<HWND> hWnds = std::vector<HWND>();
FindHwndsFromPid(pid, hWnds);
std::vector<HWND>::iterator it;
for (it = hWnds.begin(); it != hWnds.end(); it++) {
printf("hWnd = 0x%08x\n", *it);
}
別ページにも書いています。
pid → EXE名
プロセスID から EXE名を取得するには、プロセスID から OpenProcess() で hProcess を取得し、hProcess から QueryFullProcessImageName() で EXE名を取得します。
UnicodeString GetExePathFromPid(DWORD pid)
{
UnicodeString result;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, -1, pid);
if (hProcess == NULL)
return "";
const int BUFSIZE = 1024;
wchar_t exePath[BUFSIZE];
unsigned long len = BUFSIZE;
BOOL succeeded = QueryFullProcessImageName(hProcess, 0, exePath, &len);
result = (succeeded)? UnicodeString(exePath) : "";
CloseHandle(hProcess);
return result;
}
EXE名 → *
EXE名 → pid
EXE名 に対応する プロセスID は複数あるため、下記の FindPidsFromExeName() のような関数を作って、一致する全ての プロセスID を取得します。
CreateToolhelp32Snapshot() でシステムの全プロセスをスナップショットし、Process32First() から Process32Next() しながらスナップショットの中から探している EXE名と一致する プロセスID を取得していきます。
void FindPidsFromExeName(const UnicodeString& exeName, std::vector<DWORD> &pids)
{
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE)
return;
PROCESSENTRY32 processEntry;
processEntry.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(snapshot, &processEntry)) {
do {
if (_wcsicmp(processEntry.szExeFile, exeName.c_str()) != 0)
continue;
DWORD pid = processEntry.th32ProcessID;
pids.push_back(pid);
} while (Process32Next(snapshot, &processEntry));
}
CloseHandle(snapshot);
return;
}
使用例
std::vector<DWORD> pids = std::vector<DWORD>();
FindPidsFromExeName(exeName, pids);
std::vector<DWORD>::iterator it;
for (it = pids.begin(); it != pids.end(); it++) {
printf(" pid = %d\n", *it);
}
EXE名 → hWnd
EXE名に対応する プロセスID は複数あり、更に プロセスID 毎に対応する ウィンドウハンドル が複数あります。このページに記載しているEXE名→pid の方法 と pid→hWnd の方法 を組み合わせて取得します。
// exeName -> pid (複数)
std::vector<DWORD> pids = std::vector<DWORD>();
FindPidsFromExeName(exeName, pids);
// pid (複数) をループして hWnd を取得する
std::vector<DWORD>::iterator itPid;
for (itPid = pids.begin(); itPid != pids.end(); itPid++) {
DWORD pid = *itPid;
// pid -> hWnd (複数)
std::vector<HWND> hWnds = std::vector<HWND>();
FindHwndsFromPid(pid, hWnds);
std::vector<HWND>::iterator itHwnd;
for (itHwnd = hWnds.begin(); itHwnd != hWnds.end(); itHwnd++) {
printf("hWnd = 0x%08x\n", *itHwnd);
}
}
クラス名 → *
クラス名 → hWnd
クラス名 に対応する ウィンドウハンドル は複数あるため、下記の FindHwndsFromClassName() のような関数を作って、一致する 全ての ウィンドウハンドル を取得します。
EnumWindows()に入ってきた ウィンドウハンドル から GetClassName() で クラス名 を取得し、探している クラス名 と一致する ウィンドウハンドル を取得していきます。
struct _EnumWindowsArg {
UnicodeString className; // 検索対象のクラス名
std::vector<HWND> *foundWindowHandles; // 一致したウィンドウハンドルが格納される
_EnumWindowsArg(UnicodeString className, std::vector<HWND>& foundWindowHandles) {
this->className = className;
this->foundWindowHandles = &foundWindowHandles;
}
};
void FindHwndsFromClassName(const UnicodeString &className, std::vector<HWND> &hWnds)
{
_EnumWindowsArg args = _EnumWindowsArg(className, hWnds);
EnumWindows((WNDENUMPROC)_EnumWindowsProc, (LPARAM)&args);
}
// EnumWindows に呼んで貰うコールバック関数
BOOL __stdcall ClassNameToAny::_EnumWindowsProc(HWND hWnd, LPARAM lp)
{
_EnumWindowsArg *args = (_EnumWindowsArg*)lp;
// hWnd → className を取得して、探している className でなければスキップする
UnicodeString className = GetClassNameFromHwnd(hWnd);
if (className != args->className) return TRUE;
// 見つかったウィンドウハンドルをリストに追加する。
args->foundWindowHandles->push_back(hWnd);
// _EnumWindowsProc を継続して次へ
return TRUE;
}
使用例
std::vector<HWND> hWnds = std::vector<HWND>();
FindHwndsFromClassName(className, hWnds);
std::vector<HWND>::iterator it;
for (it = hWnds.begin(); it != hWnds.end(); it++) {
printf("hWnd = 0x%08x\n", *it);
}
次のように FindWindow() を使ったのでは、クラス名に対応する複数の ウィンドウハンドル のうち一つだけしか取れません。
HWND GetHwndFromClassName(const UnicodeString &className)
{
return FindWindow(className.c_str(), NULL);
}
ウィンドウ名 → *
ウィンドウ名 → hWnd
ウィンドウ名 に対応する ウィンドウハンドル は複数あるため、下記の FindHwndsFromCaption() のような関数を作って、一致する 全ての ウィンドウハンドル を取得します。
EnumWindows()に入ってきた ウィンドウハンドル から GetWindowText() で ウィンドウ名 を取得し、探している ウィンドウ名 と一致する ウィンドウハンドル を取得していきます。
struct _EnumWindowsArg {
UnicodeString caption; // 検索対象のウィンドウ名
std::vector<HWND> *foundWindowHandles; // 一致したウィンドウハンドルが格納される
_EnumWindowsArg(UnicodeString caption, std::vector<HWND>& foundWindowHandles) {
this->caption = caption;
this->foundWindowHandles = &foundWindowHandles;
}
};
void FindHwndsFromCaption(const UnicodeString &caption, std::vector<HWND> &hWnds)
{
_EnumWindowsArg args = _EnumWindowsArg(caption, hWnds);
EnumWindows((WNDENUMPROC)_EnumWindowsProc, (LPARAM)&args);
}
// EnumWindows に呼んで貰うコールバック関数
BOOL __stdcall _EnumWindowsProc(HWND hWnd, LPARAM lp)
{
_EnumWindowsArg *args = (_EnumWindowsArg*)lp;
// hWnd → caption を取得して、探している caption でなければスキップする
UnicodeString caption = GetCaptionFromHwnd(hWnd);
if (caption != args->caption) return TRUE;
// 見つかったウィンドウハンドルをリストに追加する。
args->foundWindowHandles->push_back(hWnd);
// _EnumWindowsProc を継続して次へ
return TRUE;
}
使用例
std::vector<HWND> hWnds = std::vector<HWND>();
FindHwndsFromCaption(caption, hWnds);
std::vector<HWND>::iterator it;
for (it = hWnds.begin(); it != hWnds.end(); it++) {
printf("hWnd = 0x%08x\n", *it);
}
次のように FindWindow() を使ったのでは、ウィンドウ名に対応する複数の ウィンドウハンドル のうち一つだけしか取れません。
HWND _GetHwndFromCaption(const UnicodeString &caption)
{
return FindWindow(NULL, caption.c_str());
}
その他
他の変換も追加していきたいと思います。
コメント