c++ - Win32 - 获取应用程序的主窗口句柄

标签 c++ windows winapi

我已经将我的 dll 注入(inject)到进程中。 如何获取主机应用程序的主窗口句柄?

最佳答案

宿主应用程序可能有多个“主窗口”。要检测它们,您可以

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

这会为您提供由您将 DLL 注入(inject)到的进程创建的顶层窗口列表。但是,请注意,这种方法可能会产生在您处理构建的窗口列表时已被销毁的窗口。因此,在对 Windows 进行操作时,请确保使用 IsWindow 。函数以确保手头的窗口仍然有效(这仍然容易出现竞争条件,因为窗口可能在您调用 IsWindow 和实际访问窗口之间变得无效,但时间窗口要小得多)。

这是一个实现该算法的 C++ 函数。它实现了一个 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;
}

更新:最近(我给出答案大约四年后)我也会考虑 traversing the list of threads应用程序,然后使用 EnumThreadWindows 在每个线程上。我注意到在许多情况下这要快得多。

关于c++ - Win32 - 获取应用程序的主窗口句柄,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6202547/

相关文章:

c++ - 这个测试是否证明 malloc、calloc、new 在我的系统上管理它们自己的内存池?

c++ - IMAGEM~1 代表什么?

c++ - 为什么忽略模板参数中的 cv 限定符?

c++ - Tic Tac Toe 覆盖数组用户输入

android - 是否可以在我的设备和桌面之间模拟网络?

python - 在Python中为不同操作系统构建文件路径

c++ - 禁用 Windows 中的文件夹虚拟化

c++ - 对 Windows Media Foundation AAC 编码器的多 channel 支持

c++ - 如何使用指针指向结构的 vector ?

winapi - 使用 win API 从 Win XP 操作系统检索键盘布局的语言名称