@username235

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

приложение Microsoft Visual C++. Как используя функцию EnumWindows найти требуемое окно, после нажать в этом окне кнопку "Да" ? Окно диалоговое с приглашением «Данный компьютер используется другими пользователями. Завершение работы Windows может привести к потере данных. Продолжить завершение работы?» И кнопки "Да" "Нет". Можно пример с пояснением кода. либо мануал на функцию на русском языке понятный нубу.
  • Вопрос задан
  • 6293 просмотра
Решения вопроса 1
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);
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@AlexP11223
А FindWindow (+видимо FindWindowEx для поиска кнопок в окне) не хватит? По заголовку окна.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы