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

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

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 23.01.2012, 13:35   #1
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию Найти окно, нажать в нём кнопку. Не срабатывает с 1-2-ой попытки.

Доброго времени!

При энумирации окон, ищу и коллекционирую нужные данные, конкретно чужого окна.
В числе прочих, нахожу кнопку с нужным текстом, нужно произвести 2 действия над окном:
1. Нажать найденную кнопку
2. Просто закрыть окно

Проблема:
Не сработывает с первого раза, ни первое ни второе действия.

Выкладываю исходник, помогите пожалуйста=)
Вложения
Тип файла: zip sources.zip (7.1 Кб, 16 просмотров)
Человек_Борща вне форума Ответить с цитированием
Старый 23.01.2012, 22:44   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

EnumProc
1. Если задан класс окна и он не совпадает с классом найденного окна - дальше зачем проверять? Сразу Exit
2. Аналогично для заголовка окна

EnumChildProc
1. в строке if Pos(LowerCase(p.swText), LowerCase(sText)) > 0 then нужно с p.swButtonText работать
2. Если задан класс кнопки и он не совпадает с классом найденного окна - дальше зачем проверять? Сразу Exit
3. Аналогично для текста
4. Если нашли искомый объект - сразу прервать в EnumProc поиск, а у вас он продолжается и всегда на последнюю кнопку вываливает, если их несколько и по ней отрабатывает нажатие
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 23.01.2012, 23:08   #3
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Вот немного подправил, коряво, но работает
Код:
type
  TWindowSearchInfo = record //Èíôîðìàöèÿ äëÿ ïîèñêà
    swClass: string;
    swTitle: string;
    swText: string;
    swAction: SmallInt;
    swButtonClass: string;
    swButtonText: string;
    WindowInfo: PWindowInfo;
    swFound: Boolean;
    swFoundButton: Boolean;
  end;
  PWindowSEarchInfo = ^TWindowSearchInfo;
Код:
function EnumChildProc(aHWND: HWND; lParam: LPARAM): LongBool; stdcall;
var
  P: PWindowSEarchInfo;
  sText, sTextClass: string;

begin
  P := PWindowSearchInfo(lParam);

  if IsChild(p.WindowInfo.wHandle, aHWND) and not p.swFoundButton then
  begin
    sText := ReturnControlText(aHWND);
    sTextClass := ReturnControlClass(aHWND);
    MainForm.Memo1.Lines.Add('"' + sText + '" "' + sTextClass + '" ' +
      IntToStr(aHWND));

    //Ищем класс кнопки
    if not (p.swButtonClass = EmptyStr) then
    begin
      if Pos(LowerCase(p.swButtonClass), LowerCase(sTextClass)) > 0 then
      begin
        p.WindowInfo.wButtonClass := sTextClass;
        p.WindowInfo.wButtonHandle := aHWND;
      end
      else Exit;
    end;

    //Ищем текст кнопки
    if not (p.swButtonText = EmptyStr) then
    begin
      if Pos(LowerCase(p.swButtonText), LowerCase(sText)) > 0 then
      begin
        p.WindowInfo.wButtonText := sText;
        p.WindowInfo.wButtonHandle := aHWND;
      end
      else Exit;
    end;

    p.swFoundButton:=True;
  end;
end;

function EnumProc(aHWND: HWND; alParam: LPARAM): LongBool; stdcall;
var
  P: PWindowSEarchInfo;
  sClass, sTitle: string;
begin
  P := PWindowSearchInfo(alParam);
  if IsWindowVisible(aHWND) and IsWindowEnabled(aHWND) and not IsIconic(aHWND) and not P.swFound
    then
  begin
    //Класс
    if not (p.swClass = EmptyStr) then
    begin
      sClass := ReturnControlClass(aHWND);
      if Pos(LowerCase(p.swClass), LowerCase(sClass)) > 0 then
      begin
        p.WindowInfo.wClass := sClass;
        p.WindowInfo.wTitle := ReturnControlText(aHWND);
        p.WindowInfo.wHandle := aHWND;
      end
      else Exit;
    end;

    //Заголовок
    if not (p.swTitle = EmptyStr) then
    begin
      sTitle := ReturnControlText(aHWND);
      if Pos(LowerCase(p.swTitle), LowerCase(sTitle)) > 0 then
      begin
        p.WindowInfo.wClass := ReturnControlClass(aHWND);
        p.WindowInfo.wTitle := sTitle;
        p.WindowInfo.wHandle := aHWND;
      end
      else Exit;
    end;

    P.swFound:=True;

    //Поиск внутри окна компонентов
    if not (p.swText = EmptyStr) or not (p.swButtonClass = EmptyStr) or not
      (p.swButtonText = EmptyStr) then
    begin
      EnumChildWindows(aHWND, @EnumChildProc, Integer(P))
    end;
  end;
end;

procedure TMainForm.StartBtnClick(Sender: TObject);
var
  aRec: TWindowSearchInfo;
  afRec: TWindowInfo;
  tStart, tEnd: Cardinal;

begin
  Memo1.Lines.Clear;
  tStart := GetTickCount;
  FillChar(aRec, 0, SizeOf(TwindowSearchInfo));
  FillChar(afRec, 0, SizeOf(TwindowInfo));
  aRec.swClass := WindowClassEdit.Text;
  aRec.swTitle := WindowTitleEdit.Text;
  aRec.swText := WindowTextEdit.Text;
  aRec.swAction := WindowActionCombo.ItemIndex;
  aRec.swButtonClass := ButtonClassEdit.Text;
  aRec.swButtonText := ButtonTextEdit.Text;
  aREc.WindowInfo := @afRec;
  aREc.swFound := False;
  aREc.swFoundButton := False;
  if EnumWindows(@EnumProc, Integer(@aRec)) then
  begin
    Log.Lines.Clear;
    log.Lines.Add('Класс окна: ' + afRec.wClass);
    log.Lines.Add('Заголовок окна: ' + afRec.wTitle);
    log.Lines.Add('---------');
    log.Lines.Add(' ');
    log.Lines.Add('Класс текста в окне: ' + afRec.wTextClass);
    log.Lines.Add('Текст в окне: ' + afRec.wText);
    log.Lines.Add('ID текста в окне: ' + IntToStr(afRec.wTextHandle));
    log.Lines.Add('---------');
    log.Lines.Add(' ');
    log.Lines.Add('Класс кнопки: ' + afRec.wButtonClass);
    log.Lines.Add('Текст кнопки: ' + afRec.wButtonText);
    log.Lines.Add('ID кнопки: ' + IntToStr(afREc.wButtonHandle));
    log.Lines.Add('---------');
    log.Lines.Add(' ');
    log.Lines.Add('ID окна: ' + IntToStr(afRec.wHandle));
  end;
  tEnd := GetTickCount - tStart;
  log.Lines.Add('---------');
  log.Lines.Add('TIME: ' + IntToStr(tEnd) + ' ms');

 // SetForegroundWindow(afRec.wHandle);
  IF aRec.swFound then //найдено
  case aRec.swAction of
    0: SendMessage(afRec.wHandle, WM_CLOSE, 0, 0);//close
    1: if aRec.swFoundButton then
    begin
      SendMessage(afRec.wButtonHandle, WM_LBUTTONDOWN, 1, 1);
      SendMessage(afRec.wButtonHandle, WM_LBUTTONUP, 1, 1);
    end;
  end;
end;
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 24.01.2012, 00:12   #4
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
EnumProc
1. Если задан класс окна и он не совпадает с классом найденного окна - дальше зачем проверять? Сразу Exit
2. Аналогично для заголовка окна

EnumChildProc
1. в строке if Pos(LowerCase(p.swText), LowerCase(sText)) > 0 then нужно с p.swButtonText работать
2. Если задан класс кнопки и он не совпадает с классом найденного окна - дальше зачем проверять? Сразу Exit
3. Аналогично для текста
4. Если нашли искомый объект - сразу прервать в EnumProc поиск, а у вас он продолжается и всегда на последнюю кнопку вываливает, если их несколько и по ней отрабатывает нажатие
Почему Exit? EnumProc по сути это CallBack какого-то системного цикла. Exit - прервёт цикл...


Допустимя я получаю нужную информацию по окнам..
Сработывает вот этот кусок:
Код:
  if aRec.swFound then //найдено
    case aRec.swAction of
      0: SendMessage(afRec.wHandle, WM_CLOSE, 0, 0); //close
      1: if aRec.swFoundButton then
        begin
          SendMessage(afRec.wButtonHandle, WM_LBUTTONDOWN, 1, 1);
          SendMessage(afRec.wButtonHandle, WM_LBUTTONUP, 1, 1);
        end;
    end;

С какого-то перепугу на окно не действует WM_CLOSE, можно ли как-то закрыть окно другим способом?

С нажатием тоже интересная ситуация, нужно 2 раза найти нужное окно и только со 2-го раза оно ткнёт на нужную кнопку(С первого раза, вообще ничего не происходит)...

В качестве мыши для препарирования, наваял консолькую программу с вызовом MessageBox при запуске(MsgBox.dpr)

Последний раз редактировалось Человек_Борща; 24.01.2012 в 00:37.
Человек_Борща вне форума Ответить с цитированием
Старый 24.01.2012, 00:55   #5
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Цитата:
Почему Exit? EnumProc по сути это CallBack какого-то системного цикла. Exit - прервёт цикл...
Чего вдруг прервет? Выход по концу процедуры не прерывает, чем Exit хуже? Попробуйте подправленный код, нормально закрывает и кнопки нажимает. У вас там просто небольшая путаница с сохранением Handle. Я задавал класс окна и его заголовок, класс кнопки и Caption её. А для отладки просто проект с формой и двумя буттонами
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Найти окно ошибки и нажать OK Shouldercannon Общие вопросы Delphi 8 01.05.2011 21:38
Нажать на кнопку в WB kroŧ Работа с сетью в Delphi 8 18.09.2010 15:05
Нужно программно найти окно программы и нажать на нем кнопку SeRыЙ Win Api 23 09.03.2010 08:00
Нажать кнопку Dron_kss Работа с сетью в Delphi 1 28.03.2009 17:33
Нажать кнопку Teen4jump Работа с сетью в Delphi 11 29.02.2008 08:33