Найти окно и нажать кнопку

  • Автор темы Shouldercannon
  • Дата начала
S

Shouldercannon

Если кнопка находится на Panel1 или PageControl1 и возмжно где-то ещё, то она не нажимается. Из-за чего это происходит?
Код:
 if FindWindow(nil, 'Form1') <> 0 then
begin
Wind := FindWindow(nil, 'Form1');
Btn := FindWindowEx(Wind, 0, nil, 'Кнопка');
SendMessage(Btn, BM_CLICK, 0, 0);
end;
 
S

sinkopa

Если кнопка находится на Panel1 или PageControl1 и возмжно где-то ещё, то она не нажимается. Из-за чего это происходит?
Код:
 if FindWindow(nil, 'Form1') <> 0 then
begin
Wind := FindWindow(nil, 'Form1');
Btn := FindWindowEx(Wind, 0, nil, 'Кнопка');
SendMessage(Btn, BM_CLICK, 0, 0);
end;

Не уверен, что Ваша кнопка действительно нашлась...
Чтобы до нее добраться нужно "перелопанить" все дерево вложенных (дочерних к Form1 ) окон...

Я бы сделал так

Код:
...

implementation

{$R *.dfm}


function EnumChildProc(Wnd: HWND; CaptList: TStrings): BOOL; stdcall;
var
captBuf: array[0..260] of Char;
begin
Result := (Wnd <> 0); // условие завершения обхода дерева окон
if Result then
begin
GetWindowText(Wnd, captBuf, SizeOf(captBuf)); // получаем заголовок (текст) окна
if (Pos(CaptList[0], StrPas(captBuf)) > 0)	// проверяем не наше ли это окно
and (CaptList.IndexOfObject(TObject(Wnd)) < 0) // проверяем не заглядывали ли мы уже в это окошко
then CaptList.AddObject(StrPas(captBuf), TObject(Wnd)); // Добавляем в список заголовок и хэндл окна
EnumChildWindows(Wnd, @EnumChildProc, Longint(CaptList)); // Рекурсивный обход дочерних окон
end;
end;

function ClickButton(ParentWindow: HWND; ButtonCaption: string): Boolean;
var
Btn: HWND;
CaptList: TStringList; // В items-ы будем класть заголовки окон;
// в objects-ы будем класть хэндлы окон;
begin
CaptList := TStringList.Create;
try
// В первый item листа кладем заголовок кнопки
CaptList.AddObject(ButtonCaption, nil);

// обходим все дочерние окна (ищем кнопку с указанным ButtonCaption )
EnumChildWindows(ParentWindow, @EnumChildProc, Longint(CaptList));

// Убеждаемся что нашлась ТОЛЬКО ОДНА КНОПКА с указанным ButtonCaption
Result := ((CaptList.Count = 2) and (HWND(CaptList.Objects[1]) <> 0));

if Result then
begin
Btn := HWND(CaptList.Objects[1]);
PostMessage(Btn, BM_CLICK, 0, 0);
{ //или лучше
SendMessage(Btn, WM_LBUTTONDOWN, 1, 1);
SendMessage(Btn, WM_LBUTTONUP, 1, 1);
}
end;
finally
CaptList.Free;
end;
end;

...

Пример использования:

Код:
procedure TMyForm.btn1Click(Sender: TObject);
begin
Wind := FindWindow(nil, 'Form1');
if (Wind <> 0) then
begin

if ClickButton(Wind,'Кнопка') then
begin
ShowMessage('вроде нажали');
end
else
begin
ShowMessage('нету такой кнопки (или больше одной с таким капшеном)');
end;

end
begin
ShowMessage('нету окна с капшеном "Form1"');
end;
end;
 
S

Shouldercannon

Код:
procedure TForm1.Button1Click(Sender: TObject);
var
Wind: HWND;
begin
Wind := FindWindow(nil, PChar(Edit1.Text));
if (Wind <> 0) then
begin
if ClickButton(Wind, Edit2.Text) then ShowMessage('Вроде нажали') else ShowMessage('Нету такой кнопки или больше одной с таким Caption');
end
else ShowMessage('Нет окна с Caption "' + Edit1.Text + '"');
end;
SendMessage возвращает результат, а PostMessage нет. Нужен отчёт об успешном нажатии кнопки, значит нужно всётаки использовать SendMessage, как вы предложили в закоментированном участке кода, если я не ошибаюсь.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!