Использование FindWindow
требует, чтобы вы либо знали класс окна, либо заголовок окна. Оба они не обязательно уникальны. Поскольку у вас есть обработчик процесса (и его идентификатор), вы можете реализовать надежное решение, используя EnumWindows
.
Во-первых, объявите структуру, используемую для связи. Он передает идентификатор процесса в процедуру перечисления и возвращает дескриптор окна назад.
// Structure used to communicate data from and to enumeration procedure
struct EnumData {
DWORD dwProcessId;
HWND hWnd;
};
Далее, нам нужна процедура обратного вызова, которая извлекает идентификатор процесса (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;
}
То, что осталось это общедоступный интерфейс , Он заполняет структуру, используемую для связи с идентификатором процесса, запускает перечисление окон верхнего уровня и возвращает дескриптор окна. Вызовы 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));
}
Это извлекаемое первое окно верхнего уровня, который соответствует данному идентификатору процесса. Поскольку в требованиях указано, что для данного процесса будет только одно окно, первое совпадение - это правильное окно.
Если существуют дополнительные ограничения, то можно добавить EnumProc
, чтобы включить их. Я отметил место в реализации выше, где могут применяться дополнительные фильтры.
Да, 'EnumWindows' - ваш друг. Что это с эффективностью? Вам нужно сделать это несколько миллионов раз в секунду или что-то еще? – paddy
Я просто хочу научиться делать это правильно. Есть ли проблема с этим? oO – Forivin
Совсем нет. Это правильный путь. – paddy