Win32 - Получить Main Wnd Handle приложения - PullRequest
9 голосов
/ 01 июня 2011

Я ввел свой dll в процесс.Как я могу получить дескриптор главного окна главного приложения?

1 Ответ

34 голосов
/ 01 июня 2011

Хост-приложение может иметь несколько «главных окон». Чтобы обнаружить их, вы могли бы

  1. Позвоните GetCurrentProcessId, чтобы получить PID текущего процесса
  2. Позвоните EnumWindows, чтобы перебрать все окна верхнего уровня рабочего стола
  3. Для каждого окна на рабочем столе, позвоните GetWindowThreadProcessId, чтобы получить PID процесса, который создал окно
  4. Если PID окна совпадает с PID вашего собственного процесса, запомнить окно.

Это дает вам список окон верхнего уровня, созданных процессом, в который вы внедрили свою DLL. Однако обратите внимание, что этот подход может привести к появлению окон, которые были разрушены к тому времени, когда вы обрабатываете построенный список окон. Следовательно, когда вы что-то делаете с окнами, обязательно используйте функцию IsWindow, чтобы убедиться, что окно под рукой все еще действует (это все еще подвержено условиям гонки, так как окно может стать недействительным между вызовите IsWindow и получите доступ к окну, но временное окно намного меньше).

Вот функция C ++, реализующая этот алгоритм. Он реализует функцию getToplevelWindows, которая дает std::vector<HWND>, содержащую дескрипторы всех окон верхнего уровня текущего процесса.

struct EnumWindowsCallbackArgs {
    EnumWindowsCallbackArgs( DWORD p ) : pid( p ) { }
    const DWORD pid;
    std::vector<HWND> handles;
};

static BOOL CALLBACK EnumWindowsCallback( HWND hnd, LPARAM lParam )
{
    EnumWindowsCallbackArgs *args = (EnumWindowsCallbackArgs *)lParam;

    DWORD windowPID;
    (void)::GetWindowThreadProcessId( hnd, &windowPID );
    if ( windowPID == args->pid ) {
        args->handles.push_back( hnd );
    }

    return TRUE;
}

std::vector<HWND> getToplevelWindows()
{
    EnumWindowsCallbackArgs args( ::GetCurrentProcessId() );
    if ( ::EnumWindows( &EnumWindowsCallback, (LPARAM) &args ) == FALSE ) {
      // XXX Log error here
      return std::vector<HWND>();
    }
    return args.handles;
}

ОБНОВЛЕНИЕ: В эти дни (примерно через четыре года после того, как я дал ответ) я также рассмотрел бы обход списка потоков приложения и затем использование EnumThreadWindows в каждой теме. Я заметил, что во многих случаях это значительно быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...