C++: Best way to get Window Handle of the only window from a process by process id, process handle and title name [duplicate]

时间:2022-09-02 00:26:57

This question already has an answer here:

这个问题在这里已有答案:

I'm looking for the best way to get a Window Handle in the following situation:
I have the process id and process handle, I know the window titlename and I know that the process has only one window.

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

So how would I do it? FindWindow? EnumWIndows?

那我该怎么办呢? FindWindow函数? EnumWindows的?

1 个解决方案

#1


11  

Using FindWindow requires that you either know the window class or the window title. Both of these are not necessarily unique. Since you alread have the process handle (and its ID) you can implement a robust solution using EnumWindows.

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

First, declare a structure used for communication. It passes a process ID to the enumeration procedure and returns the window handle back.

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

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

Next, we need a callback procedure that retrieves the process ID (GetWindowThreadProcessId) for any given window and compares it to the one we are looking for:

接下来,我们需要一个回调过程来检索任何给定窗口的进程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;
}

What's left is the public interface. It populates the structure used for communication with the process ID, triggers the enumeration of top-level windows, and returns the window handle. The calls to SetLastError and GetLastError are required, since EnumWindows returns FALSE for both error and success in this case:

剩下的是公共界面。它使用进程ID填充用于通信的结构,触发*窗口的枚举,并返回窗口句柄。需要调用SetLastError和GetLastError,因为在这种情况下,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 ) );
}

This will retrieve the first top-level window that matches a given process ID. Since the requirements state that there will only ever be a single window for the given process, the first one that matches is the correct window.

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

If additional restrictions exist, EnumProc can be expanded to include those. I have marked the spot in the implementation above, where additional filters can be applied.

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

#1


11  

Using FindWindow requires that you either know the window class or the window title. Both of these are not necessarily unique. Since you alread have the process handle (and its ID) you can implement a robust solution using EnumWindows.

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

First, declare a structure used for communication. It passes a process ID to the enumeration procedure and returns the window handle back.

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

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

Next, we need a callback procedure that retrieves the process ID (GetWindowThreadProcessId) for any given window and compares it to the one we are looking for:

接下来,我们需要一个回调过程来检索任何给定窗口的进程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;
}

What's left is the public interface. It populates the structure used for communication with the process ID, triggers the enumeration of top-level windows, and returns the window handle. The calls to SetLastError and GetLastError are required, since EnumWindows returns FALSE for both error and success in this case:

剩下的是公共界面。它使用进程ID填充用于通信的结构,触发*窗口的枚举,并返回窗口句柄。需要调用SetLastError和GetLastError,因为在这种情况下,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 ) );
}

This will retrieve the first top-level window that matches a given process ID. Since the requirements state that there will only ever be a single window for the given process, the first one that matches is the correct window.

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

If additional restrictions exist, EnumProc can be expanded to include those. I have marked the spot in the implementation above, where additional filters can be applied.

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