我已经将我的dll注入到进程中。 如何获取宿主应用程序的主窗口句柄?
主机应用程序可能有多个“主窗口”。要检测它们,您可以:
GetCurrentProcessId
获取当前进程的PID。EnumWindows
迭代桌面上所有顶层窗口。GetWindowThreadProcessId
获取创建窗口的进程的PID。这样可以得到一个由您注入DLL的进程创建的顶层窗口列表。但是,请注意,此方法可能会产生已在构建的窗口列表处理时销毁的窗口。因此,在处理窗口时,请确保使用IsWindow
函数确保手头的窗口仍然有效(这仍然容易受到竞争条件的影响,因为窗口可能在您调用IsWindow
和实际访问窗口之间变得无效,但时间窗口要小得多)。
getToplevelWindows
的函数,该函数生成一个包含当前进程所有顶级窗口句柄的 std::vector<HWND>
。struct EnumWindowsCallbackArgs {
EnumWindowsCallbackArgs( DWORD p ) : pid( p ) { }
const DWORD pid;
std::vector<HWND> handles;
};
static BOOL CALLBACK EnumWindowsCallback( HWND hnd, LPARAM lParam )
{
EnumWindowsCallbackArgs *args = (EnumWindowsCallbackArgs *)lParam;
DWORD windowPID;
(void)::GetWindowThreadProcessId( hnd, &windowPID );
if ( windowPID == args->pid ) {
args->handles.push_back( hnd );
}
return TRUE;
}
std::vector<HWND> getToplevelWindows()
{
EnumWindowsCallbackArgs args( ::GetCurrentProcessId() );
if ( ::EnumWindows( &EnumWindowsCallback, (LPARAM) &args ) == FALSE ) {
// XXX Log error here
return std::vector<HWND>();
}
return args.handles;
}
更新:在我回答这个问题的大约四年后,我也会考虑遍历应用程序的线程列表,然后在每个线程上使用EnumThreadWindows
。我注意到在许多情况下,这样做要快得多。EnumWindows
和EnumThreadWindows
之间的性能产生了好奇。在我的测试中,使用EnumWindows
要快得多:当使用EnumThreadWindows
时,速度为4毫秒对比200毫秒。我在此仅提供参考,将我的实现发布在此处:https://gist.github.com/gaspardpetit/3b1a10f6a2a9866b2bba8eb5d8e4ef36 - GaspardP对于之前的答案,有一个小补充 - 主应用程序窗口没有父窗口,因此GetParent()将返回0。