Программно нажать кнопку в другом приложении (C, Windows)

StackOverflow https://stackoverflow.com/questions/1223872

  •  11-07-2019
  •  | 
  •  

Вопрос

Я пытаюсь использовать следующий код, чтобы нажать кнопку в моем другом приложении:

HWND ButtonHandle;
if( (wnd = FindWindow(0, "Do you want to save?")) )
{   
   ButtonHandle = FindWindowEx(wnd, 0, "SaveButton", "&Save");
   SendMessage(wnd, WM_COMMAND, MAKEWORD(GetDlgCtrlID(ButtonHandle), BN_CLICKED ), (LPARAM)ButtonHandle);

}

Это не работает.Я попытался передать разные дескрипторы в MAKEWORD и изменить WPARM и LPARAM, но ничего.

Есть какие-нибудь идеи о том, как нажать кнопку в окне другого приложения?

Код приветствуется.Спасибо.

Редактировать:Причина, по которой это, похоже, не работает с разрешениями.Я отправил postMessage(), и результатом стала ошибка с GetLastError() = 5 (или доступ запрещен).Есть какие-нибудь идеи?

РЕДАКТИРОВАТЬ 2 Я не хочу показаться грубым, но, пожалуйста, пожалуйста, пожалуйста, я уже обыскал все API, включая получение и настройку регионов для кнопки, а затем отправку кнопки вниз и кнопки вверх, получение идентификатора элемента управления, получение идентификатора класса и множество других.Причина, по которой я вообще задал этот вопрос здесь, заключается в том, что я уже исчерпал свой поиск в Интернете.Если вы знаете ответ ПОЖАЛУЙСТА, ОТПРАВЬТЕ КОД, не предлагайте API и все, покажите мне, как этот API решает проблему.Это совсем не сложно.Спасибо.

ПРАВКА 3:Ответ на вопрос был выбран автоматически, когда розыгрыш был завершен.Этот вопрос по-прежнему остается без ответа.

Это было полезно?

Решение

  1. Вы уверены, что имя класса "SaveButton" является допустимым?Вы поняли кнопку ручка?
  2. Попробуйте отправлять сообщения в окно ButtonHandle (непосредственно на кнопку).

Обновить: Я считаю, что это должно сработать,

SendMessage(ButtonHandle, BM_CLICK, 0, 0);

Другие советы

SendMessage(btnHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(btnHandle, WM_LBUTTONUP, 0, 0);
SendMessage(btnHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(btnHandle, WM_LBUTTONUP, 0, 0);

Вы должны отправить нажатие кнопки дважды.Не уверен почему (возможно, первый щелчок активирует только окно кнопки), но я использую этот код в течение длительного времени, и он всегда работал у меня.

может быть, это может помочь:http://www.cplusplus.com/forum/beginner/8806/

Смотрите следующее решение, также вы можете использовать

SendMessage(ButtonHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(ButtonHandle, WM_LBUTTONUP, 0, 0);

Или

SendMessage(ButtonHandle, BM_CLICK, 0, 0);

HWND buttonHandle = 0;

BOOL CALLBACK GetButtonHandle(HWND handle, LPARAM)
{
 char label[100];
 int size = GetWindowTextA(handle,label,sizeof(label));
 if(strcmp(label,"&Save") == 0)
 {
  buttonHandle = handle;
  return false;
 }
 return true;
}
void main()
{
 HWND windowHandle = FindWindowA(NULL,"Do you want to Save?");
 if(windowHandle != 0)
 {
  BOOL ret = EnumChildWindows(windowHandle,GetButtonHandle,0);

  if(buttonHandle != 0)
  {
   LRESULT res = SendMessage(buttonHandle,BM_CLICK,0,0);
   //SendMessage(buttonHandle,WM_LBUTTONDOWN,0,0); 
   //SendMessage(buttonHandle,WM_LBUTTONUP,0,0);
  }

 }



}

Примечание:Получение уверенности из текста окна, текста кнопки (проверьте, есть ли пробел в конце заголовка окна)

Ошибки отказа в доступе в SendMessage или postMessage не имеют смысла, если только процесс, отправляющий сообщение, не выполняется на более низком уровне целостности, чем целевой процесс.

Этого не должно происходить, если только процесс, которому принадлежит целевое окно, не запускается "Как администратор" или не является сервисом.И службам чертовски сложно создавать окна на интерактивном рабочем столе с Windows 6 и выше.

Вы можете немного почитать о Уровни целостности Здесь если они хотя бы отдаленно применимы к данной ситуации.Internet Explorer - это, пожалуй, единственное приложение, которое "выбирает" модель безопасности целостности, намеренно снижая уровень целостности самого себя, чтобы более эффективно работать в изолированной среде.

Если вы можете открыть окно, содержащее кнопку, вы можете отправить необработанное событие мыши в позицию в пределах кнопки.

Существует две функции для имитации события мыши Отправленный ввод и mouse_event.Я рекомендую использовать mouse_event функция.Чтобы открыть окно, вы можете использовать Показать окно.Я не знаю, как получить дескриптор кнопки, но если у вас есть ее hWnd, то легко найти ее абсолютное положение, используя Получить windowrect функция.Попробуйте использовать их, если у вас возникнут какие-либо проблемы, я буду рад помочь.

Или определите пользовательский WM в вашем приложении окно для обработки запроса на сохранение. WM_CUSTOM или WM_USER (не могу вспомнить, какой) отмечает начало пользовательских оконных сообщений.

Когда мне нужно делать подобные вещи, я использую SendKeys.Это VB-ish, и C # предоставляет приятный в использовании интерфейс, но для C / C ++ вам придется это сделать <вот так>.Что в этом хорошего, так это то, что вы могли бы писать скрипты и запускать их вместо того, чтобы жестко кодировать это в своем коде.

Microsoft сейчас продвигает Активная доступность (MSAA) для автоматизации пользовательского интерфейса, (За эти годы его несколько раз переименовывали) смотрите

Извините, у меня нет никакого простого кода, который помог бы вам начать.Поскольку “SendMessage()”, похоже, у вас не работает, я не знаю другого варианта, кроме “Автоматизация пользовательского интерфейса”.

Я предполагаю, что у вас есть проверка с помощью Spy ++ (установленного с MsDev), что ваше сообщение отправляется на правильную кнопку и т.д. – и что кнопка является стандартной кнопкой Windows.В первый момент я бы посоветовал использовать “SendMessage()" или "postMessage()”, но, учитывая количество ответов о “SendMessage()" и тот факт, что у вас это не работает.Я ожидаю, что кто-то продолжает…

Вы можете использовать sendkeys (как сказал tr3) для отправки щелчков мыши, что отличается от использования SendMessage.Это также менее прямолинейно и более хакерски, но полезно для автоматизации (в VBS).

Кроме того, просто предположение, но проблема может заключаться в том, что ваша обработка сообщений где-то нарушена из-за того, что вы не вызываете элемент базового класса.Пример:

void CMyClass::OnMessageY(CWnd *cwnd)
{
    CBaseClass::OnMessageY(cwnd);
    //... my code
}

если вы уверены, что ButtonHandle является допустимым дескриптором, вы можете использовать пару WM_LBUTTONDOWN и WM_LBUTTONUP message вместо BN_CLICKED

HWND ButtonHandle;
if( (wnd = FindWindow(0, "Do you want to save?")) )
{   
    SendMessage(ButtonHandle, WM_LBUTTONDOWN, MK_LBUTTON, 0);
    SendMessage(ButtonHandle, WM_LBUTTONUP, MK_LBUTTON, 0);
}

Подход, отличный от C:Используйте Java и класс java.awt.Robot, чтобы перемещать мышь, выполняя реальные щелчки (я думаю, в мире Windows тоже есть что-то для этого).Проблема:Вы должны знать, где находится ваша кнопка: D

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top