Автор Тема: UIAutomate - автоматизация нестандартных элементов GUI  (Прочитано 56284 раз)

0 Пользователей и 2 Гостей просматривают эту тему.

Онлайн InnI [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 3162

  • Автор темы
  • Репутация: 834
    • Награды
  • Версия AutoIt: 3.3.14.0
rivega  [?]
Цитировать
кроме имени ничем не отличается
Уверен, что размером и/или положением точно отличается. К тому же в имени может быть уникальный символ, например %, которого нет у других элементов. Можно ещё найти все элементы с одинаковым свойством-значением и по индексу полученного массива обратиться к нужному (если они всегда создаются в определённом порядке).

Цитировать
в какую сторону смотреть
В сторону Internet Explorer. Либо самостоятельно разбирать POST и GET запросы. Примеров на форуме много.

Русское сообщество AutoIt

Re: UIAutomate - автоматизация нестандартных элементов GUI
« Ответ #30 Отправлен: Январь 27, 2015, 15:03:02 »

Оффлайн rivega [?]

  • Новичок
  • *
  • Сообщений: 45
  • Репутация: 0
    • Награды
Положением да, отличается, но обращаться по положению....мне кажется не очень правильно(размер окна изменился и уже не обратимся)
Что ищу: запись вида    "$0.00" (так оно отображается на сайте во всплывающем окне), инспект распознает символ $ как прямоугольник.
На основной странице сайта прокатывает поиск по части имени ".", во всплывающем окне, если ищу по ".", то возвращает имя с основной страницы((.
Поиск всех сейчас попробую...

Онлайн InnI [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 3162

  • Автор темы
  • Репутация: 834
    • Награды
  • Версия AutoIt: 3.3.14.0
rivega  [?]
Цитировать
во всплывающем окне
Если это такое же окно, как и регистрация, то оно только выглядит, как всплывающее. На самом деле оно находится в общем дереве объектов страницы, но, вероятно, ниже. А так как поиск производится до первого совпадения, то вы получаете объект самой страницы, а не этого "окна".


Добавлено: Январь 27, 2015, 23:04:40
Посмотрите хороший пример в этой теме: Ответ #13. Там coolpunk "выпрямляет" дерево в одномерный массив. Затем, перебирая элементы, находит нужный и от него отсчитывает необходимый "предыдущий/следующий".
На примере вашего окна регистрации таким образом можно найти элементы относительно флажка "Запомнить меня": поле пароля [$i - 2] и кнопку входа [$i + 2]
(нажмите для показа/скрытия)
« Последнее редактирование: Январь 27, 2015, 23:04:41 от InnI, Причина: Объединение сообщений »

Оффлайн rivega [?]

  • Новичок
  • *
  • Сообщений: 45
  • Репутация: 0
    • Награды
Так и сделал. Спасибо.

Русское сообщество AutoIt

Re: UIAutomate - автоматизация нестандартных элементов GUI
« Ответ #33 Отправлен: Январь 28, 2015, 16:31:54 »

Оффлайн rivega [?]

  • Новичок
  • *
  • Сообщений: 45
  • Репутация: 0
    • Награды

Цитировать
Не обязательно искать элемент по имени. Можно искать почти по любому другому свойству, которые отображает Inspect. Например, поле для ввода пароля можно найти так
Код: AutoIt [Выделить]
_UIA_GetControlTypeElement($oParent, "UIA_EditControlTypeId", True, "IsPassword")

Попробуйте найти такое свойство, которое отличает нужный вам элемент от других.

Вот вопрос возник....эта функция найдет первое подходящее под условие? можно сразу по нескольким свойствам искать?

Онлайн InnI [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 3162

  • Автор темы
  • Репутация: 834
    • Награды
  • Версия AutoIt: 3.3.14.0
rivega  [?]
Цитировать
сразу по нескольким свойствам
Интерфейс такое предусматривает, но в UDF данный функционал не реализован. В качестве аналога сделана функция _UIA_FindElementsInArray(). Другими словами, сначала вы ищете элементы с использованием _UIA_FindAllElements(), которая предполагает одну пару свойство-значение. Затем фильтруете полученный массив через _UIA_FindElementsInArray(), которая тоже ищет одну пару свойство-значение, но уже с возможностью частичного совпадения значения. После этого, при необходимости, опять фильтруете уже частично отсеянный массив через _UIA_FindElementsInArray() и так до тех пор, пока не останутся только нужные элементы.

Оффлайн inververs [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 2019
  • Репутация: 442
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.12.0
InnI
А чего бы вам не реализовать PropertyCondition, это же не сложно. И в функции поиска тогда можно передавать указатель на условия поиска.
Как то так
Код: AutoIt [Выделить]
Func _UIA_PropertyCondition($PropertyId, $PropertyValue)
    Local $pCondition
    $objUIAutomation.CreatePropertyCondition($PropertyId, $PropertyValue, $pCondition)
    If Not $pCondition Then Return SetError(1, @error, 0)
    Return SetError(0, 0, $pCondition)
EndFunc
Func _UIA_AndCondition(ByRef $pCondition_1, ByRef $pCondition_2)
    If Not ($pCondition_1 Or $pCondition_2) Then Return SetError(1, 0, 0)
    Local $pCondition
    $objUIAutomation.CreateAndCondition($pCondition_1, $pCondition_2, $pCondition)
    If Not $pCondition Then Return SetError(2, @error, 0)
    Return SetError(0, 0, $pCondition)
EndFunc   ;==>_UIA_AndCondition
Func _UIA_FirstElement_ByCondition(ByRef $oUIElement, $pCondition)
    If Not (IsObj($oUIElement) Or $pCondition) Then Return SetError(1, 0, 0)
    Local $pUIElement
    $oUIElement.FindFirst($TreeScope_Subtree, $pCondition, $pUIElement)
    If Not $pUIElement Then Return SetError(2, @error, 0)
    Local $oUIElementOut = ObjCreateInterface($pUIElement, $sIID_IUIAutomationElement, $dtagIUIAutomationElement)
    If Not IsObj($oUIElementOut) Then Return SetError(3, 0, 0)
    Return SetError(0, 0, $oUIElementOut)
EndFunc   ;==>_UIA_GetFirstElement_ByCondition
 



Добавлено: Январь 30, 2015, 18:04:47
К примеру, найти кнопку с именем закрыть можно будет так:
Код: AutoIt [Выделить]
    Local $p1 = _UIA_PropertyCondition($UIA_ControlTypePropertyId, $UIA_ButtonControlTypeId)
    Local $p2 = _UIA_PropertyCondition($UIA_NamePropertyId, 'Закрыть')
    Local $p = _UIA_AndCondition($p1, $p2)
    Local $close_button = _UIA_FirstElement_ByCondition($oElement, $p)


Онлайн InnI [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 3162

  • Автор темы
  • Репутация: 834
    • Награды
  • Версия AutoIt: 3.3.14.0
inververs  [?]
Цитировать
чего бы вам не реализовать
Не было необходимости. _UIA_FindElementsInArray() прекрасно заменяет данный функционал. Возможно, проигрывает в скорости, зато проще в понимании.

Цитировать
это же не сложно
Реализовать не сложно. Сложно объяснить пользователю, что такое Condition и как им пользоваться. А если делать, то нужно и OR и NOT добавлять. К тому же данные должны быть строго типизированы, что непривычно для AutoIt. Нет поддержки частичного совпадения (а для имён очень часто это необходимо). И вот осознав всё это я сделал простенькую фильтрацию через _UIA_FindElementsInArray().

Но, раз возник такой интерес, то подумаю над добавлением данного функционала.

Русское сообщество AutoIt

Re: UIAutomate - автоматизация нестандартных элементов GUI
« Ответ #37 Отправлен: Январь 30, 2015, 18:34:35 »

Оффлайн inververs [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 2019
  • Репутация: 442
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.12.0
InnI понятно, дело конечно ваше, если будет желание можете реализовать, вдруг кому то понадобится.

Онлайн InnI [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 3162

  • Автор темы
  • Репутация: 834
    • Награды
  • Версия AutoIt: 3.3.14.0
inververs  [?]
Цитировать
если будет желание
Не то, чтобы нет желания... Скорее нет понимания необходимости дублирования функционала. Тем более дублирования с усложнением для пользователя. Потом могут быть вопросы вроде "Если это можно сделать при помощи одной этой функции, зачем нужны вот эти три?" :think:

Онлайн InnI [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 3162

  • Автор темы
  • Репутация: 834
    • Награды
  • Версия AutoIt: 3.3.14.0
Обновление до версии 1.2:
- добавлены функции _UIA_CreateLogicalCondition(), _UIA_CreatePropertyCondition(), _UIA_ElementGetFirstLastChild(), _UIA_ElementGetParent(), _UIA_FindAllElementsEx(), _UIA_GetElementFromCondition(), _UIA_WaitElementFromCondition()

Оффлайн POMKA [?]

  • Новичок
  • *
  • Сообщений: 1
  • Репутация: 0
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.12.0
Пробую запускать скриптик из Ответ #32
И вот, как самый начинающий, нашел такие фишки: Если Chrome не запущен, то скрипт работает отлично! Если же Chrome уже работает со всякими окошками, то запускаемаое новаое окно или вкладка (по настроению Chrome) уже не отрабатывает опцию --force-renderer-accessibility и скрипт выдает ошибки ожидания :(
Моя задача автоматизировать некоторые действия в интернете, пользователь сидит в инете в Chrome с открытыми несколькими страничками и иногда для некоторых страниц хочет автоматически выполнить некоторые действия (обновить объявления). Получается, что в этом случает автоматизация Chrome невозможна? Или нужно Chrome закрывать и запускать с опцией --force-renderer-accessibility, что совсем не есть гуд :(
Куда копать, посоветуйте новичку?
 
и сам скрипт из ответа 32
(нажмите для показа/скрытия)

Онлайн InnI [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 3162

  • Автор темы
  • Репутация: 834
    • Награды
  • Версия AutoIt: 3.3.14.0
POMKA  [?]
Цитировать
Куда копать, посоветуйте новичку
Во-первых, что мешает сразу прописать параметр --force-renderer-accessibility в ярлык запуска Chrome?
Во-вторых, если в адресной строке запущенного Chrome ввести chrome://accessibility[enter], то можно перейти на одноимённую страницу, позволяющую управлять режимом доступа (глобально или отдельно по открытым вкладкам).

Цитировать
и сам скрипт из ответа 32
И зачем? :stars:

Оффлайн coolpunk [?]

  • Новичок
  • *
  • Сообщений: 7
  • Репутация: 2
    • Награды
Спасибо автору за работу, очень помогли данные функции в моем хобби.
Субъективно сужу только по своей задаче, но с поиском и массивами получилось сложновато.
Гораздо проще, если бы поиск возвращал индекс объекта в массиве. Предусмотреть в параметрах начальный индекс поиска. В общем, как реализован поиск в строках.
Для примера покажу свое дерево, в котором объекты не всегда на своем месте.
Ближайший точный ориентир для нужного объекта - надпись "НАПАСТЬ", который бывает и кнопкой и текстом.
В данном случае мне нужен текст "19" (выделен на скринах). Попробовал новой функцией, не получилось, разбираться не стал, потому что в процессе написания уже не понравилось.

Код: AutoIt [Выделить]
$aFinds = _UIA_FindElementsInArray($aAllElements, $UIA_NamePropertyId, "НАПАСТЬ")
If IsArray($aFinds) And $aFinds[0] > 0 Then
    ;Local $property = _UIA_CreatePropertyCondition($UIA_ControlTypePropertyId, 0xC364)
    Local $aFindText = _UIA_FindAllElementsEx($aFinds[$aFinds[0]]) ;$property
    If IsArray($aFindText) And $aFindText[0] > 0 Then
        _DebugOut(_UIA_ElementGetPropertyValue($aFindText[1], $UIA_NamePropertyId))
    EndIf
EndIf


Вот так делал раньше, работает.
Код: AutoIt [Выделить]
For $i = 1 To $aAllElements[0]
    If _UIA_ElementGetPropertyValue($aAllElements[$i], $UIA_NamePropertyId) = "НАПАСТЬ" Then
        For $j = $i+1 To $aAllElements[0]
            If _UIA_ElementGetPropertyValue($aAllElements[$j], $UIA_ControlTypePropertyId) = 0xC364 And _
                _UIA_ElementGetPropertyValue($aAllElements[$j], $UIA_NamePropertyId) <> "НАПАСТЬ" Then
                    _DebugOut(_UIA_ElementGetPropertyValue($aAllElements[$j], $UIA_NamePropertyId))
                    ExitLoop 2
            EndIf
        Next
    EndIf
Next

В данном случае возврат в поиске только индекса избавил бы нас от лишних циклов и условий, освобождение стека от передачи и возвратов массивов.


Внимание: Для просмотра прикреплённых файлов необходимо Войти или Зарегистрироваться
« Последнее редактирование: Май 28, 2015, 13:27:49 от coolpunk, Причина: подправил код »

Онлайн InnI [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 3162

  • Автор темы
  • Репутация: 834
    • Награды
  • Версия AutoIt: 3.3.14.0
coolpunk
Цитировать
если бы поиск возвращал индекс объекта в массиве
Если вы про функцию _UIA_FindElementsInArray(), то она возвращает самостоятельный массив и была задумана, как "фильтр" по определённому свойству-значению. Если же у вас есть массив, в котором нужно найти определённый элемент, то просто пробегитесь по нему в цикле до нужного совпадения. Это всего 3-4 строчки кода...

coolpunk
Цитировать
Вот так делал раньше, работает.
И чем вас теперь это не устраивает?

В любом случае поиск в UIAutomation работает только для дочерних элементов и потомков. Я имею в виду поиск, когда возвращается массив элементов. В вашем случае, насколько я понял, нужно найти текст, находящийся после кнопки, на этом же уровне вложенности. Вариант может быть следующий:
- найти кнопку "UIA_ButtonControlTypeId" с именем "НАПАСТЬ" при помощи _UIA_GetControlTypeElement()
- в цикле вызывать _UIA_ElementGetPreviousNext(), начиная с этой кнопки, пока не найдёте свой элемент (или пока элементы не закончатся)

Русское сообщество AutoIt

Re: UIAutomate - автоматизация нестандартных элементов GUI
« Ответ #44 Отправлен: Май 28, 2015, 14:41:33 »

 

Похожие темы

  Тема / Автор Ответов Последний ответ
0 Ответов
31287 Просмотров
Последний ответ Сентябрь 22, 2010, 22:13:33
от CreatoR
18 Ответов
11355 Просмотров
Последний ответ Сентябрь 18, 2011, 20:49:26
от Zalman1980
0 Ответов
2469 Просмотров
Последний ответ Ноябрь 20, 2011, 19:11:43
от ohos
9 Ответов
4528 Просмотров
Последний ответ Март 12, 2012, 00:33:05
от cobra2029
0 Ответов
1680 Просмотров
Последний ответ Май 07, 2012, 15:00:44
от Dedullika
18 Ответов
3895 Просмотров
Последний ответ Октябрь 17, 2012, 00:07:30
от Kaster
0 Ответов
1660 Просмотров
Последний ответ Декабрь 02, 2012, 10:15:22
от madmasles
6 Ответов
2868 Просмотров
Последний ответ Декабрь 10, 2012, 11:30:14
от Zergii
3 Ответов
1517 Просмотров
Последний ответ Декабрь 21, 2014, 19:24:21
от brain
8 Ответов
1598 Просмотров
Последний ответ Ноябрь 26, 2015, 17:54:56
от Garrett