Программно нажмите кнопку в другом приложении (C, Windows) - PullRequest
18 голосов
/ 03 августа 2009

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

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, но ничего.

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

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

EDIT: Причина, по-видимому, не работает разрешения. Я отправил PostMessage (), и результатом стала ошибка с GetLastError () = 5 (или Access Denied). Есть идеи?

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

РЕДАКТИРОВАТЬ 3: Ответ на вопрос был выбран автоматически, когда награда закончилась. Вопрос до сих пор остается без ответа.

Ответы [ 11 ]

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

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

SendMessage(ButtonHandle, BM_CLICK, 0, 0);
3 голосов
/ 17 сентября 2009
SendMessage(btnHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(btnHandle, WM_LBUTTONUP, 0, 0);
SendMessage(btnHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(btnHandle, WM_LBUTTONUP, 0, 0);

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

2 голосов
/ 17 сентября 2009

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

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

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

2 голосов
/ 17 сентября 2009

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

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);
  }

 }



}

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

2 голосов
/ 04 августа 2009

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

1 голос
/ 21 сентября 2009

Microsoft теперь выдвигает Active Accessibility (MSAA) для автоматизации пользовательского интерфейса, (Это было переименовано несколько раз за эти годы) см

Извините, у меня нет простого кода для начала работы. Поскольку «SendMessage ()», похоже, не работает для вас, я не знаю другого варианта, кроме «UI Automation»

Я предполагаю, что вы проверили с помощью Spy ++ (установленным с MsDev), что ваше сообщение отправляется на правильную кнопку и т. Д., И что эта кнопка является стандартной кнопкой Windows. Мое первое мгновение говорило бы использовать «SendMessage ()» или «PostMessage ()», но учитывая количество ответов о «SendMessage ()» и тот факт, что он не работает для вас. Я ожидаю, что кто-то происходит ...

1 голос
/ 17 сентября 2009

Когда мне приходится делать подобные вещи, я использую SendKeys. Это VB-иш, и C # предоставляет хороший интерфейс для использования, но для C / C ++ вам придется сделать это <<a href="http://www.codeproject.com/KB/cpp/sendkeys_cpp_Article.aspx" rel="nofollow noreferrer"> таким образом >. Что приятно, так это то, что вы можете писать сценарии и запускать их, вместо того, чтобы жестко кодировать их в своем коде.

1 голос
/ 16 сентября 2009

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

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

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

0 голосов
/ 17 сентября 2009

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

0 голосов
/ 16 сентября 2009

если вы уверены, что ButtonHandle является допустимым дескриптором, вы можете использовать пару сообщений WM_LBUTTONDOWN и WM_LBUTTONUP вместо 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);
}
...