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
?
So, your process doesn't have a "main window". The best you can do in the general case is use EnumWindows() to get all the non-child windows active on a given process and try to use some heuristics to figure out which one is the one you want.
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.
The best you can do in the general case is use EnumWindows () to get all the non-child windows active on a given process and try to use some heuristics to figure out which one is the one you want. Luckily, most processes are only likely to have a single "main" window running most of the time, so you should get good results in most cases.
So the window is considered the "main window" if it is visible and has no owner, which is a good-enough description of most "main windows".
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With