Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.06.2017, 08:02   #1
evanov4
Новичок
Джуниор
 
Регистрация: 05.06.2017
Сообщений: 4
По умолчанию Найти и нажать нужную кнопку другой программы

Пользовался FindWindowEx все работало хорошо, пока не попалась одна программа, где функция не сработала. Почитав тему http://www.programmersforum.ru/showthread.php?t=5139

выяснил, что возможно, кнопка расположена на панели или типа того.

в той же теме (пост №3) была приведена рекурсивная функция, которая обходит "оконное дерево" в поисках нужной кнопки по кэпшену.
Все бы ничего, но она написана на Си и прежде чем автор откликнулся на просьбу написать подобное на Паскале, тему закрыли.
Своими силами написать не смог, поэтому прошу помощи.

Вот, собственно, она:

Код:
HWND Walk(HWND Current,char * name)
{
  HWND temp;
  temp=GetWindow(Current,GW_CHILD); // находим первое дочернее окно
  while (temp!=NULL) // проверяем, а есть ли оно вообще
  {
     char WindowText[1024];
     GetWindowText(temp,WindowText,1023); // получаем его название
     if (!strcmp(name,WindowText)) return temp; // проверяем, искомая ли это кнопка, если да, то возвращаем её хэндл

     HWND result=Walk(temp,name); // если это была не она, то обходим её дочерние объекты

     if (result!=NULL) return result; // если при этом искомый объект был найден, возвращаем хэндл на него

     temp=GetWindow(temp,GW_HWNDNEXT) // иначе - проверяем следующий объект, дочерний для Current
  }
  return NULL; // объект не найден
}
evanov4 вне форума Ответить с цитированием
Старый 05.06.2017, 09:21   #2
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Вот накидал из вашего примера в любом окне находит нужное дочернее окно
Код:
function strcmp(const Str1, Str2: PChar): Integer; assembler;
asm
        PUSH    EDI
        PUSH    ESI
        MOV     EDI,EDX
        MOV     ESI,EAX
        MOV     ECX,0FFFFFFFFH
        XOR     EAX,EAX
        REPNE   SCASB
        NOT     ECX
        MOV     EDI,EDX
        XOR     EDX,EDX
        REPE    CMPSB
        MOV     AL,[ESI-1]
        MOV     DL,[EDI-1]
        SUB     EAX,EDX
        POP     ESI
        POP     EDI
end;

function Walk(Current: HWND; FindName: String): HWND;
var
tempHwnd: HWND;
WindowText: string;
begin
Result:= 0;

  tempHwnd:= GetWindow(Current, GW_CHILD);
  while tempHwnd <> 0 do
  begin

  SetLength(WindowText, 1023);
  SetLength(WindowText, GetWindowText(tempHwnd, PAnsiChar(WindowText), 1023));

  if (strcmp(PAnsiChar(FindName), PAnsiChar(WindowText)) = 0) then
  begin
  Result:= tempHwnd;
  exit;
  end;

 tempHwnd:= GetWindow(tempHwnd, GW_HWNDNEXT);
end;
 end;

//Применять так
procedure TForm1.Button1Click(Sender: TObject);
var
H: Hwnd;
begin
H:= FindWindow('TForm1', 'Form1');
if H <> 0 then
Showmessage(Inttostr(Walk(H, 'Button2')));
end;

Последний раз редактировалось Aliens_wolfs; 05.06.2017 в 09:23.
Aliens_wolfs вне форума Ответить с цитированием
Старый 05.06.2017, 10:42   #3
evanov4
Новичок
Джуниор
 
Регистрация: 05.06.2017
Сообщений: 4
По умолчанию

Спасибо, но не совсем так.

Например мне нужно нажать Кнопку №3

структура формы:

...................Главная______фор ма..........................
.................../........................... \........................
............Панель N1 ................. Панель N2...............
.........../........... \.................. /.............\..............
....кнопка N1 .... Кнопка N2 ... Панель N3 ... Кнопка N3
................................... ......./................................
................................... Кнопка N4..........................

Ваша функция обходит все дочерние элементы главной формы (т.е. Панель №1 и Панель №2) и, не найдя Кнопку №3, возвращает 0.

Я доработал условие:
Код:
if (strcmp(PAnsiChar(FindName), PAnsiChar(WindowText)) = 0) then
  begin
  Result:= tempHwnd;
  exit;
  end 
else result:=walk(tempHwnd,FindName)
чтоб обойти дочерние элементы Панелей 1 и 2,
но возвращается все равно 0. Не пойму почему...
evanov4 вне форума Ответить с цитированием
Старый 05.06.2017, 12:00   #4
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Подкорректировал попробуйте

Код:
function Walk(Current: HWND; FindName: String): HWND;
var
tempHwnd: HWND;
WindowText: string;
begin
  tempHwnd:= GetWindow(Current, GW_CHILD);
  while tempHwnd <> 0 do
  begin

  SetLength(WindowText, 1023);
  SetLength(WindowText, GetWindowText(tempHwnd, PAnsiChar(WindowText), 1023));

  if (strcmp(PAnsiChar(FindName), PAnsiChar(WindowText)) = 0) then
  begin
  Result:= tempHwnd;
  exit;
  end
  else
    Result:= Walk(tempHwnd, FindName);

  tempHwnd:= GetWindow(tempHwnd, GW_HWNDNEXT);
end;

 end;

Последний раз редактировалось Aliens_wolfs; 05.06.2017 в 12:25.
Aliens_wolfs вне форума Ответить с цитированием
Старый 05.06.2017, 12:20   #5
evanov4
Новичок
Джуниор
 
Регистрация: 05.06.2017
Сообщений: 4
По умолчанию

Все равно возвращается 0.

У меня отрабатывает вот такой вариант:

Код:
function  Walk(Current:HWND;name:string):hwnd;
var temp,res:HWND; WindowText:pansichar;
begin

  temp:=GetWindow(Current,GW_CHILD);

  while (temp > 0) do begin
     GetWindowText(temp,(WindowText),1023); 

     if (name)=(WindowText) then
     result:= temp
           else
     result:=Walk(temp,name);

     if (result <> NULL)
     then result:= result;

     temp:=GetWindow(temp,GW_HWNDNEXT) 

  end;

end;
Нужная мне кнопка нажимается, но вылетает ошибка
"Access violation at address EE20E5E8. Read of address EE20E5E8."
evanov4 вне форума Ответить с цитированием
Старый 05.06.2017, 12:31   #6
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Попробуйте
Код:
function Walk(Current: HWND; FindName: String): HWND;
var
tempHwnd: HWND;
WindowText: string;
begin
  tempHwnd:= GetWindow(Current, GW_CHILD);
  while tempHwnd <> 0 do
  begin

  SetLength(WindowText, 1023);
  SetLength(WindowText, GetWindowText(tempHwnd, PAnsiChar(WindowText), 1023));

  if (strcmp(PAnsiChar(FindName), PAnsiChar(WindowText)) = 0) then
  begin
  Result:= tempHwnd;
  exit;
  end;

  Result:= Walk(tempHwnd, FindName);

  if Result <> 0 then
  Exit;

  tempHwnd:= GetWindow(tempHwnd, GW_HWNDNEXT);
end;
Result:= 0;
 end;
Второй вариант игнорирет регистр
Код:
function Walk(Current: HWND; FindName: String): HWND;
var
tempHwnd: HWND;
WindowText: string;
begin
  tempHwnd:= GetWindow(Current, GW_CHILD);
  while tempHwnd <> 0 do
  begin

  SetLength(WindowText, 1023);
  SetLength(WindowText, GetWindowText(tempHwnd, PAnsiChar(WindowText), 1023));

  if (AnsiLowerCase(FindName) = AnsiLowerCase(WindowText)) then
  begin
  Result:= tempHwnd;
  exit;
  end
  else
  Result:= Walk(tempHwnd, FindName);

  tempHwnd:= GetWindow(tempHwnd, GW_HWNDNEXT);
end;

 end;

Последний раз редактировалось Aliens_wolfs; 05.06.2017 в 18:15.
Aliens_wolfs вне форума Ответить с цитированием
Старый 05.06.2017, 12:43   #7
evanov4
Новичок
Джуниор
 
Регистрация: 05.06.2017
Сообщений: 4
По умолчанию

Да! Прекрасно работает!

Безмерно благодарен вам за помощь, дорогой друг!
evanov4 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Найти кнопку и нажать на неё в Webbrowser vmilyoshin Общие вопросы Delphi 0 23.01.2015 20:36
Как из VBA нажать на кнопку программы на php Jaroslav Microsoft Office Excel 2 12.04.2014 00:17
Нажать на кнопку MainMenu Чужой программы maks5 Общие вопросы Delphi 2 05.01.2012 23:34
Нужно программно найти окно программы и нажать на нем кнопку SeRыЙ Win Api 23 09.03.2010 08:00