кросспост win32 как эмулировать нажатие мыши в окне левого приложения?

vladan67

Есть прога, там есть кнопка.
окно этой проги может перемещаться/сворачиваться...
кнопка в окне не двигается
нужно через некоторое время нажимать на эту кнопку...
Я так понимаю, надо послать сообщение в это окно?
как это сделать?
предпочтительнее решения на VC++

Elina74

Напишу для дельфи. Функции winapi везде одинаково называются, только синтаксис немножко разный.
1. Найти хэндл окна этого приложения. Скажем, если в заголовке его окна есть слово PRIVET, то хэндл ищется так
PrivetHandle := FindWindow(Nil, 'PRIVET');
2. Использовать программу Spy++, которая входит в состав Visual Studio для того, чтобы исследовать в какой части окна находится эта кнопка. При этом могут помочь команды FindWindowEx и GetWindow. Мне в свое время пришлось использовать такую последовательность команд, конечно так сложились звезды для моего приложения, для твоего все может быть не совсем так:
AfxMDIFrame80sd := FindWindowEx(PrivetHandle, 0, 'AfxMDIFrame80sd', nil);
PrivetDialog := GetWindow(AfxMDIFrame80sd, GW_CHILD);
AfxMDIFrame80sd_2 := GetWindow(PrivetDialog, GW_HWNDNEXT);
hDialog1 := GetWindow(AfxMDIFrame80sd_2, GW_CHILD);
hRunButton := GetWindow(hDialog1, GW_CHILD);
3. Нажать кнопку:
SendMessage(hRunButton, BM_CLICK, 0, 0 );

bleyman

Я тут пришёл к выводу, что самое правильное — использовать AutoHotKey, которому можно даже скармливать всякие параметры в скрипт.
Язык там, правда, довольно странный, зато функций много полезных.
Вот пример, как оно выглядит:

if 0 != 1
{
ExitApp 17
}
param := %0%
; MsgBox, 4 Parameter is %param%
IfWinNotExist, Регистрация
ExitApp 19
ControlSetText, TEdit1, %param%
ControlClick, TButton2
WinWait, ahk_class Ошибка ввода, 1
If ErrorLevel
ExitApp 21
ControlClick, OK
WinWaitClose, ahk_class Ошибка ввода, 1
If ErrorLevel
ExitApp 23
ExitApp 1
Как создавать процесс — читай мсдн.

dimon72

практически всё разъяснил. Добавить могу только, что можно просто эмулировать нажатие кнопок на клавиатуре. Вот фрагмент кода программы, которая при нажатии на кнопке формы находит виндовский "Калькулятор" и эмулирует работу пользователя с этой программой:
code:
-----------------------------------------------------------------------------------------------------------------------------
uses ShellAPI, UCalc2, Clipbrd;
procedure PressKey(Key: Word);
// имитация нажатия клавиши Key
begin
keybd_event(Key,0,0,0);
end;
procedure ClickKey(Key: Word);
begin
// имитация щелчка на клавише Key
keybd_event(Key,0,0,0);
keybd_event(Key,0,KEYEVENTF_KEYUP,0);
end;
procedure ReleaseKey(Key: Word);
// имитация отпускания клавиши Key
begin
keybd_event(Key,0,KEYEVENTF_KEYUP,0);
end;
procedure TForm1.Button1Click(Sender: TObject);
var H:hWnd;
BMCopy:TBitMap;
begin
// поиск программы 'Калькулятор'
H:=FindWindow('SciCalc','Калькулятор');
// активизация программы 'Калькулятор'
SetForegroundWindow(H);
// если 'Калькулятор' не выполняется
if (H = 0)
// зпуск программы 'Калькулятор'
then ShellExecute(Handle,'open','Calc',nil,nil,SW_RESTORE);
// задержка
Sleep(1000);
// щелчок Alt
ClickKey(VK_MENU);
Sleep(1000);
// щелчок стрелкой вправо - в меню "Вид"
ClickKey(VK_RIGHT);
Sleep(1000);
// щелчок Enter - раскрытие меню
ClickKey(VK_RETURN);
Sleep(1000);
// щелчок стрелкой вниз - во второй раздел меню
ClickKey(VK_DOWN);
Sleep(1000);
// щелчок Enter - выполнение раздела
ClickKey(VK_RETURN);
Sleep(1000);
// нажатие Alt - переход в полосу меню
PressKey(VK_MENU);
// щелчок клавиши с латинским 'D' и русским 'В' -
// клавиша быстрого доступа
ClickKey(ord('D';
// отпускание Alt
ReleaseKey(VK_MENU);
Sleep(1000);
// щелчок Enter - выполнение раздела
ClickKey(VK_RETURN);
Sleep(1000);
// щелчок цифры 2
ClickKey(ord('2';
Sleep(1000);
// нажатие Shift
PressKey(VK_SHIFT);
// щелчок клавиши с цифрой 8 и знаком умножение
ClickKey(187);
// отпускание Shift
ReleaseKey(VK_SHIFT);
// щелчок цифры 2
ClickKey(ord('2';
Sleep(1000);
// щелчок клавиши с символами '=' и '+' - результат
ClickKey(187);
Sleep(1000);
// нажатие Ctrl-C - копирование результата
PressKey(VK_CONTROL);
ClickKey(ord('C';
ReleaseKey(VK_CONTROL);
Sleep(1000);
// чтение результата
RichEdit1.Clear;
RichEdit1.Lines.Add('2 * 2 = ');
RichEdit1.SelStart := RichEdit1.SelStart - 2;
RichEdit1.Perform(WM_PASTE,0,0);
RichEdit2.Clear;
RichEdit2.Lines.Add('2 * 2 = ');
RichEdit2.SelStart := RichEdit2.SelStart - 2;
RichEdit2.Perform(WM_PASTE,0,0);
// занесение окна в буфер обмена
PressKey(VK_MENU);
ClickKey(VK_SNAPSHOT);
ReleaseKey(VK_MENU);
Sleep(1000);
// возврат активности в данное приложение
SetForegroundWindow(Handle);
ShowMessage('Программа управления Калькулятором выполнена');
Form2.Visible := false;
BMCopy := TBitMap.Create;
try
try
BMCopy.LoadFromClipBoardFormat(cf_BitMap,
ClipBoard.GetAsHandle(cf_Bitmap0);
with Form2 do
Image1.Canvas.CopyRect(RectClientWidth-BMCopy.Width) div 2,
(ClientHeight-Image1.Height) div 2,
(ClientWidth+BMCopy.Width) div 2,
(ClientHeight+BMCopy.Height) div 2
BMCopy.Canvas,Rect(0,0,BMCopy.Width,BMCopy.Height;
finally
BMCopy.Free;
end;
except
On EInvalidGraphic do
ShowMessage('Ошибочный формат графики');
end;
Form2.Show;
end;
-----------------------------------------------------------------------------------------------------------------------------
Недостаток такого способа очевиден: такая программа во-первых, работает медленнее, чем при передаче сообщения непосредственно нужному контролу, а во-вторых, может легко сбиться и начинать давить на не те кнопки. А так, если у компонента чужого приложения есть хендл, то почти всегда можно осуществлять с ним манипуляции: читать или писать данные через него через сообщения.
Оставить комментарий
Имя или ник:
Комментарий: