Windows API 根据进程 ID 查找窗口的 HWND
在 Windows API 中,从进程 ID (PID) 获取窗口句柄 (HWND) 并没有一个直接的单一步骤函数(如 GetWindowByPid),因为一个进程可能拥有多个顶级窗口,也可能完全没有窗口。
通常的做法是枚举系统中的所有顶级窗口,并检查每个窗口所属的进程 ID 是否与目标 PID 匹配。
核心实现逻辑
最标准且高效的方法是使用 EnumWindows 函数。
- 定义一个结构体:用于在回调函数中存储目标 PID 和返回的 HWND。
- 调用
EnumWindows:该函数会遍历屏幕上的所有顶级窗口。 - 编写回调函数:
- 使用
GetWindowThreadProcessId获取当前枚举窗口的 PID。 - 对比该 PID 与目标 PID。
- 如果匹配,检查是否是主窗口(通常通过
IsWindowVisible或GetWindow(hwnd, GW_OWNER)进一步筛选)。 - 保存 HWND 并停止枚举。
- 使用
C++ 代码示例
1#include <windows.h>
2#include <iostream>
3
4// 用于传递数据给回调函数的结构体
5struct EnumData {
6 DWORD targetPid;
7 HWND hWnd;
8};
9
10// EnumWindows 的回调函数
11BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) {
12 EnumData* data = (EnumData*)lParam;
13 DWORD windowPid = 0;
14
15 // 获取该窗口所属的进程 ID
16 GetWindowThreadProcessId(hWnd, &windowPid);
17
18 // 如果 PID 匹配 且 是主窗口(没有所有者)
19 if (windowPid == data->targetPid && GetWindow(hWnd, GW_OWNER) == NULL && IsWindowVisible(hWnd)) {
20 data->hWnd = hWnd;
21 return FALSE; // 找到目标,停止枚举
22 }
23
24 return TRUE; // 继续枚举
25}
26
27HWND GetHwndByPid(DWORD pid) {
28 EnumData data;
29 data.targetPid = pid;
30 data.hWnd = NULL;
31
32 EnumWindows(EnumWindowsProc, (LPARAM)&data);
33
34 return data.hWnd;
35}
36
37int main() {
38 DWORD pid = 1234; // 替换为你的目标 PID
39 HWND hWnd = GetHwndByPid(pid);
40
41 if (hWnd) {
42 std::cout << "找到窗口句柄: " << hWnd << std::endl;
43 } else {
44 std::cout << "未找到该进程的窗口。" << std::endl;
45 }
46 return 0;
47}
48关键函数说明
| 函数 | 作用 |
EnumWindows | 枚举屏幕上所有的顶级窗口,每发现一个窗口就调用一次回调函数。 |
GetWindowThreadProcessId | 获取创建指定窗口的线程 ID,并通过输出参数返回进程 ID。 |
IsWindowVisible | 确保你找到的是用户能看到的窗口,而不是进程创建的隐藏辅助窗口。 |
GetWindow(hWnd, GW_OWNER) | 检查窗口是否有所有者。通常“主窗口”没有所有者(返回 NULL)。 |