Win32 – 获取主要的Wnd应用程序的句柄

我注入了我的DLL进程。 我怎样才能得到主机应用程序的主窗口句柄?

主机应用程序可能有多个“主窗口”。 要发现他们,你可以

  1. 调用GetCurrentProcessId来获取当前进程的PID
  2. 调用EnumWindows遍历桌面的所有顶层窗口
  3. 对于桌面上的每个窗口,调用GetWindowThreadProcessId来获取创建该窗口的进程的PID
  4. 如果窗口的PID与您自己的进程的PID匹配,请记住该窗口。

这给你一个顶级窗口的列表,由您注入DLL的过程创建。 但是,请注意,这种方法可能会产生窗口,这些窗口在处理构建的窗口列表时已经被破坏。 因此,在使用窗口进行某些操作时,一定要使用IsWindow函数来确保手边的窗口仍然有效(这仍然很容易出现竞争状态,因为在调用IsWindow和实际访问窗口之间窗口可能变得无效,但时间窗口要小得多)。

这是一个实现这个算法的C ++函数。 它实现了一个getToplevelWindows函数,该函数生成一个包含当前进程所有顶层窗口std::vector<HWND>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 我注意到这在很多情况下是相当快的。