#Robot_ModuleGUI_Refactoring_50%

dev-linux
Ivan Maslov 6 years ago
parent 165b6290b1
commit 35aa1ea7ef

@ -20,6 +20,16 @@ from threading import Timer
####################################
# GUI Module - interaction with Desktop application
#GUI Naming convention
#<InArgument>_<ActivityName>_<OutArgument - if exist>
#UIO - UI Object (class of pywinauto UI object)
#UIOSelector - List of dict (key attributes)
#PWA - PyWinAuto
#PWASpecification - List of dict (key attributes in pywinauto.find_window notation)
#UIOTree - Recursive Dict of Dict ... (UI Parent -> Child hierarchy)
#UIOInfo - Dict of UIO attributes
#UIOActivity - Activity of the UIO (UI object) from the Pywinauto module
#inActivitySpecificationDict:
#{
@ -43,31 +53,188 @@ from threading import Timer
# Result: <Result, returned from the Activity, int, str, boolean, list, dict> - required if ErrorFlag is false
#}
mFlagIsDebug=False
#inUIOSelector:
#[
# {
# "index":<Позиция элемента в родительском объекте>,
# "depth_start" - глубина, с которой начинается поиск (по умолчанию 1),
# "depth_end" - глубина, до которой ведется поиск (по умолчанию 1),
# "class_name" - наименование класса, который требуется искать,
# "title" - наименование заголовка,
# "rich_text" - наименование rich_text,
# "backend": <"win32"||"uia", only for the 1-st list element> - if not specified, use mDefaultPywinautoBackend
# },
# { ... }
#
#]
mPywinautoApplication=pywinauto.Application(backend="win32")
#mPywinautoActiveBackend="win32"
mPywinautoActiveBackend="uia"
#mPywinautoApplication=pywinauto.Application(backend="uia")
#Default parameters
mDefaultPywinautoBackend="win32"
#####
##Внимание! Нельзя делать print так как он уходит в родительский поток и ломает механизм взаимодействия
##Чтобы его использовать надо писать функцию обертку
#####
############################
#Новая версия
############################
#Получить список элементов, который удовлетворяет условиям через расширенный движок поиска
#[
# {
# "index":<Позиция элемента в родительском объекте>,
# "depth_start" - глубина, с которой начинается поиск (по умолчанию 1)
# "depth_end" - глубина, до которой ведется поиск (по умолчанию 1)
# "class_name" - наименование класса, который требуется искать
# "title" - наименование заголовка
# "rich_text" - наименование rich_text
# }
#]
################
#return: List of UI Object
#old name - PywinautoExtElementsGet
def UIOSelector_Get_UIOList (inSpecificationList,inElement=None):
lResultList=[]
lChildrenList=[]
#Получить родительский объект если на вход ничего не поступило
if inElement is None:
#сформировать спецификацию на получение элемента
lRootElementSpecification=[inSpecificationList[0]]
lRootElement=GetControl(lRootElementSpecification)
if lRootElement is not None:
lChildrenList.append(lRootElement.wrapper_object())
#Елемент на вход поступил - выполнить его анализ
else:
#Получить список элементов
lElementChildrenList=inElement.children()
#Поступил index - точное добавление
if 'index' in inSpecificationList[0]:
if inSpecificationList[0]['index']<len(lElementChildrenList):
#Получить дочерний элемент - точное добавление
lChildrenList.append(lElementChildrenList[inSpecificationList[0]['index']])
else:
raise ValueError('Object has no children with index: ' + str(inSpecificationList[0]['index']))
#Поступил ctrl_index - точное добавление
elif 'ctrl_index' in inSpecificationList[0]:
if inSpecificationList[0]['ctrl_index']<len(lElementChildrenList):
#Получить дочерний элемент
lChildrenList.append(lElementChildrenList[inSpecificationList[0]['ctrl_index']])
else:
raise ValueError('Object has no children with index: ' + str(inSpecificationList[0]['ctrl_index']))
#Если нет точного обозначения элемента
else:
lFlagGoCheck=True
#Учесть поле depth_start (если указано)
if 'depth_start' in inSpecificationList[0]:
if inSpecificationList[0]["depth_start"]>1:
lFlagGoCheck=False
#pdb.set_trace()
#Циклический обход по детям, на предмет соответствия всем условиям
for lChildrenItem in lElementChildrenList:
#Обработка глубины depth (рекурсивный вызов для всех детей с занижением индекса глубины)
#По умолчанию значение глубины 1
if 'depth_end' in inSpecificationList[0]:
if inSpecificationList[0]['depth_end']>1:
#Подготовка новой версии спецификации
lChildrenItemNewSpecificationList=inSpecificationList.copy()
lChildrenItemNewSpecificationList[0]=lChildrenItemNewSpecificationList[0].copy()
lChildrenItemNewSpecificationList[0]["depth_end"]=lChildrenItemNewSpecificationList[0]["depth_end"]-1
if 'depth_start' in lChildrenItemNewSpecificationList[0]:
lChildrenItemNewSpecificationList[0]["depth_start"]=lChildrenItemNewSpecificationList[0]["depth_start"]-1
#pdb.set_trace()
#Циклический вызов для всех детей со скорректированной спецификацией
lResultList.extend(PywinautoExtElementsGet(lChildrenItemNewSpecificationList,lChildrenItem))
#Фильтрация
if lFlagGoCheck:
lFlagAddChild=True
#Фильтрация по title
if 'title' in inSpecificationList[0]:
if lChildrenItem.element_info.name != inSpecificationList[0]["title"]:
lFlagAddChild=False
#Фильтрация по rich_text
if 'rich_text' in inSpecificationList[0]:
if lChildrenItem.element_info.rich_text != inSpecificationList[0]["rich_text"]:
lFlagAddChild=False
#Фильтрация по class_name
if 'class_name' in inSpecificationList[0]:
if lChildrenItem.element_info.class_name != inSpecificationList[0]["class_name"]:
lFlagAddChild=False
#Фильтрация по friendly_class_name
if 'friendly_class_name' in inSpecificationList[0]:
if lChildrenItem.friendly_class_name() != inSpecificationList[0]["friendly_class_name"]:
lFlagAddChild=False
#Фильтрация по control_type
if 'control_type' in inSpecificationList[0]:
if lChildrenItem.element_info.control_type != inSpecificationList[0]["control_type"]:
lFlagAddChild=False
#####
#Все проверки пройдены - флаг добавления
if lFlagAddChild:
lChildrenList.append(lChildrenItem)
#Выполнить рекурсивный вызов (уменьшение количества спецификаций), если спецификация больше одного элемента
if len(inSpecificationList)>1 and len(lChildrenList)>0 is not None:
#Вызвать рекурсивно функцию получения следующего объекта, если в спецификации есть следующий объект
for lChildElement in lChildrenList:
lResultList.extend(PywinautoExtElementsGet(inSpecificationList[1:],lChildElement))
else:
lResultList.extend(lChildrenList)
return lResultList
###########################
####Модуль Automation
###########################
#################################################################################################
#Get first (in more than one) UIO (UI Object)
#inSpecificationList - UIOSelector
#old name - PywinautoExtElementGet
def UIOSelector_Get_UIO (inSpecificationList,inElement=None):
lResult=None
#Получить родительский объект если на вход ничего не поступило
lResultList=PywinautoExtElementsGet(inSpecificationList,inElement)
if len(lResultList)>0:
lResult=lResultList[0]
return lResult
#inElementSpecificationList = [ [{lvl_0},{lvl_1},{lvl_2}],... ]
##################################################################################################
#inControlSpecificationArray - List of dict, dict in pywinauto.find_windows notation
#Backend selection - attribute "backend" ("win32" || "uia") in 1-st list element
#return UIO object
#old name - GetControl
def PWASpecification_Get_UIO(inControlSpecificationArray):
#Определение backend
lBackend=mDefaultPywinautoBackend
if "backend" in inControlSpecificationArray[0]:
lBackend=inControlSpecificationArray[0]["backend"]
#Подготовка входного массива
inControlSpecificationArray=ElementSpecificationArraySearchPrepare(inControlSpecificationArray)
#Выполнить идентификацию объектов, если передан массив
lResultList=[];
lTempObject=None
if len(inControlSpecificationArray) > 0:
#Выполнить подключение к объекту
lRPAApplication = pywinauto.Application(backend=lBackend)
#Проверка разрядности
try:
lRPAApplication.connect(**inControlSpecificationArray[0])
except Exception as e:
PywinautoExtTryToRestore(inControlSpecificationArray)
try:
lRPAApplication.connect(**inControlSpecificationArray[0])
except Exception as e:
lRPAApplication = None
if lRPAApplication is not None:
#lTempObject=lRPAApplication.window(**inControlSpecificationArray[0])
#Скорректировано из-за недопонимания структуры
lTempObject=lRPAApplication
#Нормализация массива для целей выборки объекта (удаление конфликтующих ключей)
inControlSpecificationArray=ElementSpecificationListNormalize(inControlSpecificationArray)
#Циклическое прохождение к недрам объекта
for lWindowSpecification in inControlSpecificationArray[0:]:
lTempObject=lTempObject.window(**lWindowSpecification)
return lTempObject
###########################################################################################################
#inElementSpecificationList = UIOSelector (see description on the top of the document)
#result = pywinauto element wrapper instance or None
def AutomationSearchMouseElement(inElementSpecification,inFlagIsSearchOnline=True):
#old name - AutomationSearchMouseElement
def UIOSelector_SearchChildByMouse_UIO(inElementSpecification):
lGUISearchElementSelected=None
#Настройка - частота обновления подсвечивания
lTimeSleepSeconds=0.4
lElementFoundedList=[]
#Ветка поиска в режиме реального времени
if inFlagIsSearchOnline:
#Сбросить нажатие Ctrl, если оно было
bool(win32api.GetAsyncKeyState(17))
lFlagLoop = True
@ -95,51 +262,16 @@ def AutomationSearchMouseElement(inElementSpecification,inFlagIsSearchOnline=Tru
lFlagLoop=False;
#Заснуть до следующего цикла
time.sleep(lTimeSleepSeconds)
#Ветка поиска по заранее созданной карте
else:
###################################
#Внимание Старая ветка (неправильный результат)
###################################
lBitmap={}
#Создать карту пикселей и элементов
lBitmap=GUISearchBitmapCreate(PywinautoExtElementGet(inElementSpecification),lBitmap)
#Выдать сообщение, что поиск готов к использованию
#print("GUISearch: Ready for search!")
###########
#Версия с задержкой (без таймеров, событий в отдельных потоках)
###########
#Сбросить нажатие Ctrl, если оно было
bool(win32api.GetAsyncKeyState(17))
lFlagLoop = True
while lFlagLoop:
#Проверить, нажата ли клавиша Ctrl (код 17)
lFlagKeyPressedCtrl=bool(win32api.GetAsyncKeyState(17))
#Подсветить объект, если мышка наведена над тем объектом, который не подсвечивался в прошлый раз
if not lFlagKeyPressedCtrl:
#Получить координаты мыши
(lX,lY) = win32api.GetCursorPos()
#Подсветить объект, если мышь над ним
if (lX,lY) in lBitmap:
if lGUISearchElementSelected != lBitmap[lX,lY]:
lGUISearchElementSelected = lBitmap[lX,lY]
#Классическая функция отрисовки (из pywinauto)
#lBitmap[lX,lY].draw_outline()
#Доработанная функция отрисовки
draw_outline_new(lBitmap[lX,lY])
else:
lGUISearchElementSelected = None
else:
#Была нажата клавиша Ctrl - выйти из цикла
lFlagLoop=False;
#Заснуть до следующего цикла
time.sleep(lTimeSleepSeconds)
#Вернуть результат поиска
return lElementFoundedList
def AutomationSearchMouseElementHierarchy(inElementSpecification,inFlagIsSearchOnline=True):
####################################################################################################
#inElementSpecification - UIOSelector
#old name - AutomationSearchMouseElementHierarchy
def UIOSelector_SearchChildByMouse_UIOTree(inElementSpecification):
lItemInfo = []
#Запустить функцию поиска элемента по мыши
lElementList = AutomationSearchMouseElement(inElementSpecification,inFlagIsSearchOnline)
lElementList = UIOSelector_SearchChildByMouse_UIO(inElementSpecification,inFlagIsSearchOnline)
lElement = lElementList[-1]['element']
#Detect backend of the elements
lFlagIsBackendWin32 = True
@ -178,13 +310,10 @@ def AutomationSearchMouseElementHierarchy(inElementSpecification,inFlagIsSearchO
lListIterator=lListIterator+1
#Вернуть результат
return lItemInfo
#return [1,2,3,4,5,3]
###########################
####Модуль PywinautoExt
###########################
def PywinautoExtElementCtrlIndexGet(inElement):
####################################################################################################
#inElement- UIO (UI Object)
#old name - PywinautoExtElementCtrlIndexGet
def UIO_GetCtrlIndex_Int(inElement):
lResult = None
#Выполнить алгоритм, если есть Element
if inElement is not None:
@ -212,103 +341,12 @@ def PywinautoExtElementCtrlIndexGet(inElement):
lFlagFind=False
#Вернуть результат
return lResult
#Получить список элементов, который удовлетворяет условиям через расширенный движок поиска
#[ {
#"index":<Позиция элемента в родительском объекте>,
# "depth_start" - глубина, с которой начинается поиск (по умолчанию 1)
# "depth_end" - глубина, до которой ведется поиск (по умолчанию 1)
# "class_name" - наименование класса, который требуется искать
# "title" - наименование заголовка
# "rich_text" - наименование rich_text
#} ]
def PywinautoExtElementsGet (inSpecificationList,inElement=None):
lResultList=[]
lChildrenList=[]
#Получить родительский объект если на вход ничего не поступило
if inElement is None:
#сформировать спецификацию на получение элемента
lRootElementSpecification=[inSpecificationList[0]]
lRootElement=GetControl(lRootElementSpecification)
if lRootElement is not None:
lChildrenList.append(lRootElement.wrapper_object())
#Елемент на вход поступил - выполнить его анализ
else:
#Получить список элементов
lElementChildrenList=inElement.children()
#Поступил index - точное добавление
if 'index' in inSpecificationList[0]:
if inSpecificationList[0]['index']<len(lElementChildrenList):
#Получить дочерний элемент - точное добавление
lChildrenList.append(lElementChildrenList[inSpecificationList[0]['index']])
else:
raise ValueError('Object has no children with index: ' + str(inSpecificationList[0]['index']))
#Поступил ctrl_index - точное добавление
elif 'ctrl_index' in inSpecificationList[0]:
if inSpecificationList[0]['ctrl_index']<len(lElementChildrenList):
#Получить дочерний элемент
lChildrenList.append(lElementChildrenList[inSpecificationList[0]['ctrl_index']])
else:
raise ValueError('Object has no children with index: ' + str(inSpecificationList[0]['ctrl_index']))
#Если нет точного обозначения элемента
else:
lFlagGoCheck=True
#Учесть поле depth_start (если указано)
if 'depth_start' in inSpecificationList[0]:
if inSpecificationList[0]["depth_start"]>1:
lFlagGoCheck=False
#pdb.set_trace()
#Циклический обход по детям, на предмет соответствия всем условиям
for lChildrenItem in lElementChildrenList:
#Обработка глубины depth (рекурсивный вызов для всех детей с занижением индекса глубины)
#По умолчанию значение глубины 1
if 'depth_end' in inSpecificationList[0]:
if inSpecificationList[0]['depth_end']>1:
#Подготовка новой версии спецификации
lChildrenItemNewSpecificationList=inSpecificationList.copy()
lChildrenItemNewSpecificationList[0]=lChildrenItemNewSpecificationList[0].copy()
lChildrenItemNewSpecificationList[0]["depth_end"]=lChildrenItemNewSpecificationList[0]["depth_end"]-1
if 'depth_start' in lChildrenItemNewSpecificationList[0]:
lChildrenItemNewSpecificationList[0]["depth_start"]=lChildrenItemNewSpecificationList[0]["depth_start"]-1
#pdb.set_trace()
#Циклический вызов для всех детей со скорректированной спецификацией
lResultList.extend(PywinautoExtElementsGet(lChildrenItemNewSpecificationList,lChildrenItem))
#Фильтрация
if lFlagGoCheck:
lFlagAddChild=True
#Фильтрация по title
if 'title' in inSpecificationList[0]:
if lChildrenItem.element_info.name != inSpecificationList[0]["title"]:
lFlagAddChild=False
#Фильтрация по rich_text
if 'rich_text' in inSpecificationList[0]:
if lChildrenItem.element_info.rich_text != inSpecificationList[0]["rich_text"]:
lFlagAddChild=False
#Фильтрация по class_name
if 'class_name' in inSpecificationList[0]:
if lChildrenItem.element_info.class_name != inSpecificationList[0]["class_name"]:
lFlagAddChild=False
#Фильтрация по friendly_class_name
if 'friendly_class_name' in inSpecificationList[0]:
if lChildrenItem.friendly_class_name() != inSpecificationList[0]["friendly_class_name"]:
lFlagAddChild=False
#Фильтрация по control_type
if 'control_type' in inSpecificationList[0]:
if lChildrenItem.element_info.control_type != inSpecificationList[0]["control_type"]:
lFlagAddChild=False
#####
#Все проверки пройдены - флаг добавления
if lFlagAddChild:
lChildrenList.append(lChildrenItem)
#Выполнить рекурсивный вызов (уменьшение количества спецификаций), если спецификация больше одного элемента
if len(inSpecificationList)>1 and len(lChildrenList)>0 is not None:
#Вызвать рекурсивно функцию получения следующего объекта, если в спецификации есть следующий объект
for lChildElement in lChildrenList:
lResultList.extend(PywinautoExtElementsGet(inSpecificationList[1:],lChildElement))
else:
lResultList.extend(lChildrenList)
return lResultList
####################################################################################################
#Получить список информационных объектов, который удовлетворяет условиям
def PywinautoExtElementsGetInfo (inSpecificationList,inElement=None):
#inSpecificationList - UIOSelector
#old name - PywinautoExtElementsGetInfo
def UIOSelector_Get_UIOInfoList (inSpecificationList,inElement=None):
#Получить родительский объект если на вход ничего не поступило
lResultList=PywinautoExtElementsGet(inSpecificationList,inElement)
lIterator = 0
@ -316,108 +354,50 @@ def PywinautoExtElementsGetInfo (inSpecificationList,inElement=None):
lResultList[lIterator]=ElementInfoExportObject(lResultList[lIterator].element_info)
lIterator = lIterator + 1
return lResultList
#Получить элемент через расширенный движок поиска
#[ {
#"index":<Позиция элемента в родительском объекте>,
#
#} ]
def PywinautoExtElementGet (inSpecificationList,inElement=None):
lResult=None
#Получить родительский объект если на вход ничего не поступило
lResultList=PywinautoExtElementsGet(inSpecificationList,inElement)
if len(lResultList)>0:
lResult=lResultList[0]
return lResult
#Проверить, существует ли объект
def PywinautoExtElementExist (inSpecificationList):
#pdb.set_trace()
####################################################################################################
#Check is the UIO/UIO's by the UIOSelector exist
#inSpecificationList - UIOSelector
#old name - PywinautoExtElementExist
def UIOSelector_IsExist_Bool (inSpecificationList):
return len(PywinautoExtElementsGet(inSpecificationList))>0
#Ожидать появления элемента
def PywinautoExtElementWaitAppear(inSpecificationList,inTimeout=60):
####################################################################################################
#Wait for the UIO by the UIOSelector appear
#inSpecificationList - UIOSelector
#result - { }
#old name - PywinautoExtElementWaitAppear
def UIOSelector_WaitAppear_Dict(inSpecificationList,inTimeout=60):
lTimeoutSeconds = 0
while (not PywinautoExtElementExist(inSpecificationList) and inTimeout>lTimeoutSeconds):
lTimeoutSeconds = lTimeoutSeconds + 0.5
#Заснуть на полсекунды
time.sleep(0.5)
return PywinautoExtElementExist(inSpecificationList)
#Функция, которая попытается восстановить окно, если оно есть, но свернуто (особенность uia backend - он не может прицепиться к окну, если оно свернуто)
def PywinautoExtTryToRestore(inSpecificationList):
#pdb.set_trace()
####################################################################################################
#Try to restore (maximize) window, if it's was minimized
#(особенность uia backend - он не может прицепиться к окну, если оно свернуто)
#inSpecificationList - UIOSelector
#old name - PywinautoExtTryToRestore
def UIOSelector_TryRestore_Dict(inSpecificationList):
lResult={}
try:
#Подготовка взодного массива
inControlSpecificationArray=ElementSpecificationArraySearchPrepare(inSpecificationList)
#Выполнить подключение к объекту. Восстановление необходимо только в бэке win32, так как в uia свернутое окно не распознается
#Выполнить подключение к объекту. Восстановление необходимо только в бэке win32,
#так как в uia свернутое окно не распознается
lRPAApplication = pywinauto.Application(backend="win32")
lRPAApplication.connect(**inSpecificationList[0])
lRPAApplication.top_window().restore()
except Exception:
True==False
################################
#Функция повторяющегося таймера
#############################
class RepeatedTimer(object):
def __init__(self, interval, function, *args, **kwargs):
self._timer = None
self.interval = interval
self.function = function
self.args = args
self.kwargs = kwargs
self.is_running = False
self.start()
def _run(self):
self.is_running = False
self.start()
self.function(*self.args, **self.kwargs)
def start(self):
if not self.is_running:
self._timer = Timer(self.interval, self._run)
self._timer.start()
self.is_running = True
def stop(self):
self._timer.cancel()
self.is_running = False
#mTimer.start() # after 30 seconds, "hello, world" will be printed
#Флаг отладки напрямую (не выполнять чтение буфера stdin)
##################################
###Методы взаимодействия с GUI интерфейсом
##################################
#pywinauto
def GetControl(inControlSpecificationArray):
#Подготовка взодного массива
inControlSpecificationArray=ElementSpecificationArraySearchPrepare(inControlSpecificationArray)
#Выполнить идентификацию объектов, если передан массив
lResultList=[];
lTempObject=None
if len(inControlSpecificationArray) > 0:
#Выполнить подключение к объекту
lRPAApplication = pywinauto.Application(backend=mPywinautoActiveBackend)
#Проверка разрядности
try:
lRPAApplication.connect(**inControlSpecificationArray[0])
except Exception as e:
PywinautoExtTryToRestore(inControlSpecificationArray)
try:
lRPAApplication.connect(**inControlSpecificationArray[0])
except Exception as e:
lRPAApplication = None
if lRPAApplication is not None:
#lTempObject=lRPAApplication.window(**inControlSpecificationArray[0])
#Скорректировано из-за недопонимания структуры
lTempObject=lRPAApplication
#Нормализация массива для целей выборки объекта (удаление конфликтующих ключей)
inControlSpecificationArray=ElementSpecificationListNormalize(inControlSpecificationArray)
#Циклическое прохождение к недрам объекта
for lWindowSpecification in inControlSpecificationArray[0:]:
lTempObject=lTempObject.window(**lWindowSpecification)
return lTempObject
#Получить массив свойств и методов у элемента
def ElementActionGetList (inControlSpecificationArray):
return lResult
####################################################################################################
#Get the list of the UI object activities
#inControlSpecificationArray - UIOSelector
#old name - ElementActionGetList
def UIOSelector_Get_UIOActivityList (inControlSpecificationArray):
#Получить объект
lObject=PywinautoExtElementGet(inControlSpecificationArray)
lActionList=dir(lObject)
@ -431,8 +411,14 @@ def ElementActionGetList (inControlSpecificationArray):
if lActionItem[0].isupper():
lResult.remove(lActionItem)
return lResult
#Выполнить действие над элементом
def ElementRunAction(inControlSpecificationArray,inActionName,inArgumentList=[],inkwArgumentObject={}):
####################################################################################################
#Run the activity in UIO (UI Object)
#inControlSpecificationArray - UIOSelector
#inActionName - UIOActivity (name) from Pywinauto
#old name - ElementRunAction
def UIOSelectorUIOActivity_Run_Dict(inControlSpecificationArray,inActionName,inArgumentList=[],inkwArgumentObject={}):
lResult={}
#Определить объект
lObject=PywinautoExtElementGet(inControlSpecificationArray)
#Получить метод для вызова
@ -455,8 +441,12 @@ def ElementRunAction(inControlSpecificationArray,inActionName,inArgumentList=[],
return lResult
else:
raise e
return lResult
def ElementGetInfo(inControlSpecificationArray):
####################################################################################################
#Get the UIO dict of the attributes
#old name - ElementGetInfo
def UIOSelector_Get_UIOInfo(inControlSpecificationArray):
#Подготовка входного массива
inControlSpecificationArray=ElementSpecificationArraySearchPrepare(inControlSpecificationArray)
#Выполнить идентификацию объектов, если передан массив
@ -469,6 +459,16 @@ def ElementGetInfo(inControlSpecificationArray):
#Добавить информацию об обнаруженом объекте
lResultList.append(ElementInfoExportObject(lTempObjectInfo));
return lResultList
############################
#Старая версия
############################
mFlagIsDebug=False
##################################
############################################
###Модуль поиска объекта на экране
############################################

Loading…
Cancel
Save