2013-11-23 3 views
7

Я ищу лучший способ получить Window Handle в следующей ситуации:
У меня есть идентификатор процесса и дескриптор процесса, я знаю окно TITLENAME и я знаю, что этот процесс имеет только одно окно.C++: Лучший способ получить Window Handle единственного окна из процесса по идентификатору процесса, дескриптору процесса и названию названия

Итак, как бы я это сделал? FindWindow? EnumWIndows?

+0

Да, 'EnumWindows' - ​​ваш друг. Что это с эффективностью? Вам нужно сделать это несколько миллионов раз в секунду или что-то еще? – paddy

+1

Я просто хочу научиться делать это правильно. Есть ли проблема с этим? oO – Forivin

+0

Совсем нет. Это правильный путь. – paddy

ответ

11

Использование 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, чтобы включить их. Я отметил место в реализации выше, где могут применяться дополнительные фильтры.