C ++:通过进程ID,进程句柄和标题名称从进程中获取Window Handle的唯一窗口的最佳方法

时间:2013-11-23 12:36:17

标签: c++ winapi window-handles

我正在寻找在以下情况下获得窗口把手的最佳方法:
我有进程ID 进程句柄,我知道窗口titlename ,我知道该进程只有一个窗口

那我该怎么办呢? FindWindowEnumWIndows

1 个答案:

答案 0 :(得分:11)

使用FindWindow要求您知道窗口类或窗口标题。这两者都不一定是唯一的。由于您已经获得了流程句柄(及其ID),因此您可以使用EnumWindows实现强大的解决方案。

首先,声明用于通信的结构。它将进程ID传递给枚举过程并返回窗口句柄。

// Structure used to communicate data from and to enumeration procedure
struct EnumData {
    DWORD dwProcessId;
    HWND hWnd;
};

接下来,我们需要一个回调过程来检索任何给定窗口的进程ID(GetWindowThreadProcessId)并将其与我们要查找的窗口进行比较:

// Application-defined callback for EnumWindows
BOOL CALLBACK EnumProc( HWND hWnd, LPARAM lParam ) {
    // Retrieve storage location for communication data
    EnumData& ed = *(EnumData*)lParam;
    DWORD dwProcessId = 0x0;
    // Query process ID for hWnd
    GetWindowThreadProcessId( hWnd, &dwProcessId );
    // Apply filter - if you want to implement additional restrictions,
    // this is the place to do so.
    if ( ed.dwProcessId == dwProcessId ) {
        // Found a window matching the process ID
        ed.hWnd = hWnd;
        // Report success
        SetLastError( ERROR_SUCCESS );
        // Stop enumeration
        return FALSE;
    }
    // Continue enumeration
    return TRUE;
}

剩下的是公共界面。它使用进程ID填充用于通信的结构,触发顶级窗口的枚举,并返回窗口句柄。需要调用SetLastErrorGetLastError,因为EnumWindows在这种情况下会因错误和成功而返回FALSE

// Main entry
HWND FindWindowFromProcessId( DWORD dwProcessId ) {
    EnumData ed = { dwProcessId };
    if ( !EnumWindows( EnumProc, (LPARAM)&ed ) &&
         ( GetLastError() == ERROR_SUCCESS ) ) {
        return ed.hWnd;
    }
    return NULL;
}

// Helper method for convenience
HWND FindWindowFromProcess( HANDLE hProcess ) {
    return FindWindowFromProcessId( GetProcessId( hProcess ) );
}

这将检索与给定进程ID匹配的第一个顶级窗口。由于要求声明给定进程只有一个窗口,匹配的第一个窗口是正确的窗口。

如果存在其他限制,可以扩展EnumProc以包含这些限制。我在上面的实现中标记了这个位置,可以应用其他过滤器。