• Как используя функцию EnumWindows найти требуемое окно, после нажать в этом окне кнопку "ОК"?

    SHVV
    @SHVV
    Если окно появляется всегда в одном и том же положении, то можно просто тыкать мышкой в нужных координатах. Как-то так:
    #include "windows.h"
    void set_event(int a_x, int a_y, int a_btn)
    {
      // Перемещаем мышку в абсолютных координатах
      DWORD flags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
    
      // Устанавливаем флаги для нажатия/отпускания кнопки мыши
      switch (a_btn) {
        case 1: {
          flags |= MOUSEEVENTF_LEFTDOWN;
          break;
        }
    
        case 2: {
          flags |= MOUSEEVENTF_LEFTUP;
          break;
        }
      }
    
      // Получаем размер рабочего стола, чтобы получить нормализованные координаты
      RECT full_rect;
      GetWindowRect(GetDesktopWindow(), &full_rect);
    
      // Нормализуем координаты
      LONG x = (LONG)(a_x*(65535.0f/(full_rect.right - full_rect.left - 1)));
      LONG y = (LONG)(a_y*(65535.0f/(full_rect.bottom - full_rect.top - 1)));
    
      INPUT input;
      memset(&input, 0, sizeof(INPUT));
      input.type = INPUT_MOUSE;
      input.mi.dwFlags = flags;
      input.mi.dx = x;
      input.mi.dy = y;
    
      // Посылаем событие мыши
      SendInput(1, &input, sizeof(INPUT));
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
      // Координаты, по которым тыкаем
      int x = 1160;
      int y = 640;
      // Сначала перемещаем мышку
      set_event(x, y, 0);
      // Потом нажимаем левую кнопку
      set_event(x, y, 1);
      // И, наконец, отпускаем
      set_event(x, y, 2);
    
      return 0;
    }

    У меня этот вариант работает.

    Если нужен более стабильный подход, то можно использовать EnumWindows, так как FindWindow вроде как не будет работать с окнами другого процесса. Используется он просто:
    BOOL CALLBACK enum_wnd_proc(HWND hwnd, LPARAM lParam)
    // hwnd - окно, которое надо проверить
    // lParam пользовательский параметр, передаваемый в функцию. Я через него свойства искомого окна передаю
    {
      WindowInfo* window_info = (WindowInfo*)lParam;
    
      // Тут идут проверки нужных свойств, если они не проходят, надо вернуть TRUE
    
      // Если все проверки прошли, сохраняем текущий хэндл окна в передаваемой структуре и возвращаем FALSE
      window_info->m_hwnd = hwnd;
      return FALSE;
    }
    
    // Это для окон верхнего уровня
    if (EnumWindows(enum_wnd_proc, (LPARAM)(&window_info)) == TRUE) {
      // Окно найдено
      // window_info->m_hwnd;  <-- это родительское окно
      // Дальше ищем дочернее окно аналогично, но с помощью 
      WindowInfo window_info_2;
      EnumChildWindows(window_info->m_hwnd, enum_wnd_proc, (LPARAM)(&window_info_2));
      // window_info_2.m_hwnd <-- это дочернее окно
    }

    Что можно проверять?
    Для окна верхнего уровня - название процесса (GetWindowThreadProcessId, OpenProcess, EnumProcessModules, GetModuleBaseName).
    Для всех окон - заголовок (GetWindowText), класс (GetClassName), конкретные значения можно найти в Spy++. Для вашей задачи должно быть достаточно.
    Нажимать кнопку уже можно либо как выше написал, либо:
    l_param = x | (y << 16);
    ::PostMessage(hwnd, WM_MOUSEMOVE, 0, l_param);
    ::PostMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, l_param);
    ::PostMessage(hwnd, WM_LBUTTONUP, 0, l_param);
    Ответ написан
    2 комментария