hWndからpidやEXE名を取得、pidからhWndやEXE名を取得、EXE名からpidやhWndを取得する方法一覧 [C++Builder]

「hWnd から pid はどう取得するのか」「hWnd から EXE名はどう取得するのか」などの変換方法をまとめてみました。

一覧

変換方法の一覧です。

変換するには「どの Win32API を使うのか」といった変換方法の概要を記載しています。「変換元→変換先」のリンクをクリックするとページ内のサンプルコードへ飛びます。

変換元 → 変換先取得方法の概要
hWnd → pidGetWindowThreadProcessId() を使う。
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名 → hWndEXE名に対応する 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());
}

その他

他の変換も追加していきたいと思います。

コメント