如何从进程ID获取主窗口句柄?

如何从进程ID获取窗口句柄?

我想把这个窗口放在前面。

它在“Process Explorer”中运行良好。

我检查了.NET如何确定主窗口。

我的发现表明它也使用EnumWindows()

这段代码应该和.NET的方式类似:

 struct handle_data { unsigned long process_id; HWND best_handle; }; HWND find_main_window(unsigned long process_id) { handle_data data; data.process_id = process_id; data.best_handle = 0; EnumWindows(enum_windows_callback, (LPARAM)&data); return data.best_handle; } BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lParam) { handle_data& data = *(handle_data*)lParam; unsigned long process_id = 0; GetWindowThreadProcessId(handle, &process_id); if (data.process_id != process_id || !is_main_window(handle)) { return TRUE; } data.best_handle = handle; return FALSE; } BOOL is_main_window(HWND handle) { return GetWindow(handle, GW_OWNER) == (HWND)0 && IsWindowVisible(handle); } 

我不相信Windows(而不是.NET)提供了一个直接的方法来获取它。

我知道的唯一方法是用EnumWindows()枚举所有的顶层窗口,然后find每个属于GetWindowThreadProcessID()进程。 这听起来是间接和低效的,但并不像你所期望的那么糟糕 – 在一个典型的例子中,你可能有十几个顶级窗口可以通过…

这里可能会有一个错误的理解。 .Net中的WinForms框架自动将所创build的第一个窗口(例如, Application.Run(new SomeForm()) )指定为MainWindow 。 但是,win32 API不能识别每个进程的“主窗口”的概念。 消息循环完全能够处理尽可能多的“主”窗口,因为系统和进程资源将允许您创build。 所以,你的过程没有“主窗口”。 在一般情况下,你可以做的最好的事情是使用EnumWindows()来获得所有非子窗口在一个给定的进程上活动,并尝试使用一些启发式来找出哪一个是你想要的。 幸运的是,大多数进程只能在大多数情况下运行一个“主”窗口,因此在大多数情况下应该得到好的结果。

虽然它可能与您的问题无关,请查看GetGUIThreadInfo函数 。

这是我的解决scheme,使用基于顶级答案的纯Win32 / C ++。 这个想法是将所有需要的东西包装到一个函数中,而不需要外部的callback函数或结构:

 HWND FindTopWindow(DWORD pid) { std::pair<HWND, DWORD> params = { 0, pid }; // Enumerate the windows using a lambda to process each window BOOL bResult = EnumWindows([](HWND hwnd, LPARAM lParam) -> BOOL { auto pParams = (std::pair<HWND, DWORD>*)(lParam); DWORD processId; if (GetWindowThreadProcessId(hwnd, &processId) && processId == pParams->second) { // Stop enumerating SetLastError(-1); pParams->first = hwnd; return FALSE; } // Continue enumerating return TRUE; }, (LPARAM)&params); if (!bResult && GetLastError() == -1 && params.first) { return params.first; } return 0; } 

只是为了确保你不会混淆tid(线程ID)和PID(进程ID):

 DWORD pid; DWORD tid = GetWindowThreadProcessId( this->m_hWnd, &pid); 

作为Hiale解决scheme的扩展,您可以提供支持具有多个主窗口的进程的不同或修改版本。

首先,修改结构以允许存储多个句柄:

 struct handle_data { unsigned long process_id; std::vector<HWND> handles; }; 

二,修改callback函数:

 BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lParam) { handle_data& data = *(handle_data*)lParam; unsigned long process_id = 0; GetWindowThreadProcessId(handle, &process_id); if (data.process_id != process_id || !is_main_window(handle)) { return TRUE; } // change these 2 lines to allow storing of handle and loop again data.handles.push_back(handle); return TRUE; } 

最后,修改主要function的回报:

 std::vector<HWD> find_main_window(unsigned long process_id) { handle_data data; data.process_id = process_id; EnumWindows(enum_windows_callback, (LPARAM)&data); return data.handles; }