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

1

7

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.

So how would I do it? FindWindow? EnumWIndows?

Ventricular answered 23/11, 2013 at 12:36 Comment(5)
Yep, EnumWindows is your friend. What's this with efficiency? Do you need to do it a few million times per second or something?Diena
I just want to learn to do it the right way. Is there a problem with that? oOVentricular
Not at all. This is the right way.Diena
Btw this is no duplicate. I'm NOT looking for any way to get the window handle! I'm looking for the best way for MY PARTICULAR case. ... So EnumWindows is the most efficient one yes?Ventricular
It is a duplicate. Your particular case is identical to the one in the linked question, with additional restrictions that do not make a difference. However, the answer to the previous question only provides basic guidance, not a fully functional solution, so this question should not be closed.Pahari
P
15

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.

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

// 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:

// 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:

// 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.

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.

Pahari answered 23/11, 2013 at 14:44 Comment(2)
In Win10 this will now not work for ex. "calc.exe". We have do search with EnumWindows the WindowTitle "Calculator" or "Rechner" in German version. I don't know exactly why.Wilona
@TomTom I'm not sure I understand. This proposed answer doesn't use the window title or window class. It simply enumerates all top-level windows and returns the first one that is owned by a thread of a process with a given process ID.Pahari

© 2022 - 2024 — McMap. All rights reserved.