#NewSearchEngine(depth_start,depth_end,class_name,title,rich_text) #GeneralClipboardSet/Get #MouseVisualSearchFix

dev-linux
Ivan Maslov 5 years ago
parent 6c5b5abd03
commit 81158f10d4

@ -177,7 +177,7 @@
mGlobal.TreeObjectInfoLoad =function (inElementId) { mGlobal.TreeObjectInfoLoad =function (inElementId) {
//Подгрузка массива спецификаций //Подгрузка массива спецификаций
lSpecificationArray = mGlobal.GUIElement[inElementId].GUISelectorFull lSpecificationArray = mGlobal.GUIElement[inElementId].GUISelectorFull
var lHTMLList='<div class="ui relaxed divided list">' var lHTMLList='<div class="ui relaxed divided list" style="height:350px;overflow:scroll;">'
var lSpecificationArrayNew=[] var lSpecificationArrayNew=[]
for (i=0;i<lSpecificationArray.length;i++) { for (i=0;i<lSpecificationArray.length;i++) {
lSpecificationArrayNew.push(lSpecificationArray[i]) lSpecificationArrayNew.push(lSpecificationArray[i])

@ -10,7 +10,9 @@ import os
import select import select
import zlib import zlib
import win32api import win32api
import win32clipboard
import time import time
import traceback
from threading import Timer from threading import Timer
mFlagIsDebug=False mFlagIsDebug=False
@ -35,6 +37,7 @@ def AutomationSearchMouseElement(inElementSpecification,inFlagIsSearchOnline=Tru
lGUISearchElementSelected=None lGUISearchElementSelected=None
#Настройка - частота обновления подсвечивания #Настройка - частота обновления подсвечивания
lTimeSleepSeconds=0.4 lTimeSleepSeconds=0.4
lElementFoundedList=[]
#Ветка поиска в режиме реального времени #Ветка поиска в режиме реального времени
if inFlagIsSearchOnline: if inFlagIsSearchOnline:
#Сбросить нажатие Ctrl, если оно было #Сбросить нажатие Ctrl, если оно было
@ -50,7 +53,9 @@ def AutomationSearchMouseElement(inElementSpecification,inFlagIsSearchOnline=Tru
lElementFounded={} lElementFounded={}
#Создать карту пикселей и элементов #Создать карту пикселей и элементов
#####Внимание! Функция GUISearchElementByRootXY не написана #####Внимание! Функция GUISearchElementByRootXY не написана
lElementFounded=GUISearchElementByRootXY(PywinautoExtElementGet(inElementSpecification),lX,lY) lElementFoundedList=GUISearchElementByRootXY(PywinautoExtElementGet(inElementSpecification),lX,lY)
#print(lElementFoundedList)
lElementFounded=lElementFoundedList[-1]["element"]
#Подсветить объект, если он мышь раньше стояла на другом объекте #Подсветить объект, если он мышь раньше стояла на другом объекте
if lGUISearchElementSelected != lElementFounded: if lGUISearchElementSelected != lElementFounded:
lGUISearchElementSelected = lElementFounded lGUISearchElementSelected = lElementFounded
@ -64,6 +69,9 @@ def AutomationSearchMouseElement(inElementSpecification,inFlagIsSearchOnline=Tru
time.sleep(lTimeSleepSeconds) time.sleep(lTimeSleepSeconds)
#Ветка поиска по заранее созданной карте #Ветка поиска по заранее созданной карте
else: else:
###################################
#Внимание Старая ветка (неправильный результат)
###################################
lBitmap={} lBitmap={}
#Создать карту пикселей и элементов #Создать карту пикселей и элементов
lBitmap=GUISearchBitmapCreate(PywinautoExtElementGet(inElementSpecification),lBitmap) lBitmap=GUISearchBitmapCreate(PywinautoExtElementGet(inElementSpecification),lBitmap)
@ -98,35 +106,42 @@ def AutomationSearchMouseElement(inElementSpecification,inFlagIsSearchOnline=Tru
#Заснуть до следующего цикла #Заснуть до следующего цикла
time.sleep(lTimeSleepSeconds) time.sleep(lTimeSleepSeconds)
#Вернуть результат поиска #Вернуть результат поиска
return lGUISearchElementSelected return lElementFoundedList
def AutomationSearchMouseElementHierarchy(inElementSpecification,inFlagIsSearchOnline=True): def AutomationSearchMouseElementHierarchy(inElementSpecification,inFlagIsSearchOnline=True):
lItemInfo = None lItemInfo = []
#Запустить функцию поиска элемента по мыши #Запустить функцию поиска элемента по мыши
lElement = AutomationSearchMouseElement(inElementSpecification,inFlagIsSearchOnline) lElementList = AutomationSearchMouseElement(inElementSpecification,inFlagIsSearchOnline)
lElement = lElementList[-1]['element']
#Detect backend of the elements #Detect backend of the elements
lFlagIsBackendWin32 = True lFlagIsBackendWin32 = True
#Если объект имеется (не None), то выполнить построение иерархии #Если объект имеется (не None), то выполнить построение иерархии
#pdb.set_trace()
if lElement is not None: if lElement is not None:
if lElement.backend.name == 'uia': if lElement.backend.name == 'uia':
lFlagIsBackendWin32 = False lFlagIsBackendWin32 = False
#Циклическое создание дерева #Циклическое создание дерева
while lElement is not None: #while lElement is not None:
lListIterator=0
lItemInfo2=lItemInfo
for lListItem in lElementList:
lElement = lListItem["element"]
#Продолжать построение иерархии во всех случаях кроме бэк uia & parent() is None #Продолжать построение иерархии во всех случаях кроме бэк uia & parent() is None
if not lFlagIsBackendWin32 and lElement.parent() is None: #if not lFlagIsBackendWin32 and lElement.parent() is None:
lElement = None # lElement = None
else: #else:
#Получить информацию про объект #Получить информацию про объект
lItemInfo2 = ElementInfoExportObject(lElement.element_info) lItemInfo2.append(ElementInfoExportObject(lElement.element_info))
#Дообогатить информацией об индексе ребенка в родительском объекте #Дообогатить информацией об индексе ребенка в родительском объекте
lItemInfo2['ctrl_index']=PywinautoExtElementCtrlIndexGet(lElement) lItemInfo2[-1]['ctrl_index']=lListItem["index"]
#Оборачиваем потомка в массив, потому что у родителя по структуре интерфейса может быть больше одного наследников #Оборачиваем потомка в массив, потому что у родителя по структуре интерфейса может быть больше одного наследников
lItemInfo2['SpecificationChild']=[lItemInfo] lItemInfo2[-1]['SpecificationChild']=[]
lItemInfo=lItemInfo2 lItemInfo2=lItemInfo2[-1]['SpecificationChild']
#Переход на родительский объект #Переход на родительский объект
lElement = lElement.parent() #lElement = lElement.parent()
lListIterator=lListIterator+1
#Вернуть результат #Вернуть результат
return [lItemInfo] return lItemInfo
#return [1,2,3,4,5,3] #return [1,2,3,4,5,3]
@ -161,39 +176,104 @@ def PywinautoExtElementCtrlIndexGet(inElement):
lFlagFind=False lFlagFind=False
#Вернуть результат #Вернуть результат
return lResult return lResult
#Получить элемент через расширенный движок поиска #Получить список элементов, который удовлетворяет условиям через расширенный движок поиска
#[ { #[ {
#"index":<Позиция элемента в родительском объекте>, #"index":<Позиция элемента в родительском объекте>,
# # "depth_start" - глубина, с которой начинается поиск (по умолчанию 1)
# "depth_end" - глубина, до которой ведется поиск (по умолчанию 1)
# "class_name" - наименование класса, который требуется искать
# "title" - наименование заголовка
# "rich_text" - наименование rich_text
#} ] #} ]
def PywinautoExtElementGet (inSpecificationList,inElement=None): def PywinautoExtElementsGet (inSpecificationList,inElement=None):
lResult=None lResultList=[]
lChildElement=None lChildrenList=[]
#Получить родительский объект если на вход ничего не поступило #Получить родительский объект если на вход ничего не поступило
if inElement is None: if inElement is None:
#сформировать спецификацию на получение элемента #сформировать спецификацию на получение элемента
lRootElementSpecification=[inSpecificationList[0]] lRootElementSpecification=[inSpecificationList[0]]
lChildElement=GetControl(lRootElementSpecification) lChildrenList.append(GetControl(lRootElementSpecification))
if lChildrenList[0] is not None:
lChildrenList[0] = lChildrenList[0].wrapper_object()
#Елемент на вход поступил - выполнить его анализ #Елемент на вход поступил - выполнить его анализ
else: else:
#Поступил index #Получить список элементов
lElementChildrenList=inElement.children()
#Поступил index - точное добавление
if 'index' in inSpecificationList[0]: if 'index' in inSpecificationList[0]:
lChildrenList=inElement.children() if inSpecificationList[0]['index']<len(lElementChildrenList):
if inSpecificationList[0]['index']<len(lChildrenList): #Получить дочерний элемент - точное добавление
#Получить дочерний элемент lChildrenList.append(lElementChildrenList[inSpecificationList[0]['index']])
lChildElement=lChildrenList[inSpecificationList[0]['index']] else:
#Поступил ctrl_index raise ValueError('Object has no children with index: ' + str(inSpecificationList[0]['index']))
#Поступил ctrl_index - точное добавление
elif 'ctrl_index' in inSpecificationList[0]: elif 'ctrl_index' in inSpecificationList[0]:
lChildrenList=inElement.children() if inSpecificationList[0]['ctrl_index']<len(lElementChildrenList):
if inSpecificationList[0]['ctrl_index']<len(lChildrenList):
#Получить дочерний элемент #Получить дочерний элемент
lChildElement=lChildrenList[inSpecificationList[0]['ctrl_index']] lChildrenList.append(lElementChildrenList[inSpecificationList[0]['ctrl_index']])
#Выполнить рекурсивный вызов, если спецификация больше одного элемента else:
if len(inSpecificationList)>1 and lChildElement is not None: 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
#####
#Все проверки пройдены - флаг добавления
if lFlagAddChild:
lChildrenList.append(lChildrenItem)
#Выполнить рекурсивный вызов (уменьшение количества спецификаций), если спецификация больше одного элемента
if len(inSpecificationList)>1 and len(lChildrenList)>0 is not None:
#Вызвать рекурсивно функцию получения следующего объекта, если в спецификации есть следующий объект #Вызвать рекурсивно функцию получения следующего объекта, если в спецификации есть следующий объект
lResult=PywinautoExtElementGet(inSpecificationList[1:],lChildElement) for lChildElement in lChildrenList:
lResultList.extend(PywinautoExtElementsGet(inSpecificationList[1:],lChildElement))
else: else:
lResult=lChildElement lResultList.extend(lChildrenList)
return lResultList
#Получить элемент через расширенный движок поиска
#[ {
#"index":<Позиция элемента в родительском объекте>,
#
#} ]
def PywinautoExtElementGet (inSpecificationList,inElement=None):
lResult=None
#Получить родительский объект если на вход ничего не поступило
lResultList=PywinautoExtElementsGet(inSpecificationList,inElement)
if len(lResultList)>0:
lResult=lResultList[0]
return lResult return lResult
################################ ################################
#Функция повторяющегося таймера #Функция повторяющегося таймера
@ -432,13 +512,18 @@ def GUISearchRun(inSpecificationArray):
############################################################# #############################################################
#Поиск элементов #Поиск элементов
############################################################# #############################################################
def GUISearchElementByRootXY(inRootElement,inX,inY): #inHierarchyList: [{"index":<>,"element":<>}]
#
#Вернуть словарь [{"index":<>,"element":<>}]
#Последний элемент - искомый
def GUISearchElementByRootXY(inRootElement,inX,inY,inHierarchyList=[]):
#Инициализация результирующего значения #Инициализация результирующего значения
lResultElement = None lResultElement = None
lResultElementX1 = None lResultElementX1 = None
lResultElementX2 = None lResultElementX2 = None
lResultElementY1 = None lResultElementY1 = None
lResultElementY2 = None lResultElementY2 = None
lResultHierarchyList=[{'index':None,'element':None}]
#Получить координаты текущего объекта #Получить координаты текущего объекта
try: try:
lRootElementRectX1=inRootElement.element_info.rectangle.left lRootElementRectX1=inRootElement.element_info.rectangle.left
@ -452,9 +537,21 @@ def GUISearchElementByRootXY(inRootElement,inX,inY):
lResultElementX2 = lRootElementRectX2 lResultElementX2 = lRootElementRectX2
lResultElementY1 = lRootElementRectY1 lResultElementY1 = lRootElementRectY1
lResultElementY2 = lRootElementRectY2 lResultElementY2 = lRootElementRectY2
#Сформировать результирующий обьъект
lParentHierarchy = inHierarchyList
if len(lParentHierarchy)==0:
lParentHierarchy.append({"index":None,"element":lResultElement})
else:
lParentHierarchy[-1]["element"] = lResultElement
lResultHierarchyList=lParentHierarchy
#Получить список детей и добавить в карту #Получить список детей и добавить в карту
lChildIterator=0
for lChildElement in inRootElement.children(): for lChildElement in inRootElement.children():
lChildFoundedElement = GUISearchElementByRootXY(lChildElement,inX,inY) #Сформировать результирующий массив
lChildFoundedHierarchyList = lParentHierarchy.copy()
lChildFoundedHierarchyList.append({'index': lChildIterator})
lChildFoundedHierarchyList = GUISearchElementByRootXY(lChildElement,inX,inY, lChildFoundedHierarchyList)
lChildFoundedElement = lChildFoundedHierarchyList[-1]["element"]
#Установить обнаруженный элемент, если текущий результат пустой #Установить обнаруженный элемент, если текущий результат пустой
if lResultElement is None and lChildFoundedElement is not None: if lResultElement is None and lChildFoundedElement is not None:
lResultElement = lChildFoundedElement lResultElement = lChildFoundedElement
@ -462,6 +559,7 @@ def GUISearchElementByRootXY(inRootElement,inX,inY):
lResultElementX2 = lResultElement.element_info.rectangle.right lResultElementX2 = lResultElement.element_info.rectangle.right
lResultElementY1 = lResultElement.element_info.rectangle.top lResultElementY1 = lResultElement.element_info.rectangle.top
lResultElementY2 = lResultElement.element_info.rectangle.bottom lResultElementY2 = lResultElement.element_info.rectangle.bottom
lResultHierarchyList = lChildFoundedHierarchyList
#Выполнить сверку lChildFoundedElement и lResultElement если оба имеются #Выполнить сверку lChildFoundedElement и lResultElement если оба имеются
elif lResultElement is not None and lChildFoundedElement is not None: elif lResultElement is not None and lChildFoundedElement is not None:
#Правила перезатирания карты, если имеется старый объект #Правила перезатирания карты, если имеется старый объект
@ -488,6 +586,7 @@ def GUISearchElementByRootXY(inRootElement,inX,inY):
lResultElementX2 = lChildFoundedElementX2 lResultElementX2 = lChildFoundedElementX2
lResultElementY1 = lChildFoundedElementY1 lResultElementY1 = lChildFoundedElementY1
lResultElementY2 = lChildFoundedElementY2 lResultElementY2 = lChildFoundedElementY2
lResultHierarchyList = lChildFoundedHierarchyList
#Проверка вхождения по типу 2 #Проверка вхождения по типу 2
else: else:
lResultElement = lChildFoundedElement lResultElement = lChildFoundedElement
@ -495,9 +594,11 @@ def GUISearchElementByRootXY(inRootElement,inX,inY):
lResultElementX2 = lChildFoundedElementX2 lResultElementX2 = lChildFoundedElementX2
lResultElementY1 = lChildFoundedElementY1 lResultElementY1 = lChildFoundedElementY1
lResultElementY2 = lChildFoundedElementY2 lResultElementY2 = lChildFoundedElementY2
lResultHierarchyList = lChildFoundedHierarchyList
lChildIterator=lChildIterator+1
except Exception as e: except Exception as e:
False == False False == False
return lResultElement return lResultHierarchyList
#Техническая функция #Техническая функция
def GUISearchBitmapCreate (inElement,inBitmapDict={}): def GUISearchBitmapCreate (inElement,inBitmapDict={}):
@ -918,6 +1019,26 @@ def draw_outline_new(lWrapperObject,colour='green',thickness=2,fill=win32defines
#Аналог подсвечивания + установка фокуса #Аналог подсвечивания + установка фокуса
def draw_outline_new_focus(lWrapperObject,colour='green',thickness=2,fill=win32defines.BS_NULL,rect=None): def draw_outline_new_focus(lWrapperObject,colour='green',thickness=2,fill=win32defines.BS_NULL,rect=None):
draw_outline_new(lWrapperObject,'green',2,win32defines.BS_NULL,None,True) draw_outline_new(lWrapperObject,'green',2,win32defines.BS_NULL,None,True)
################
###GeneralClipboardGet
################
def GeneralClipboardGet():
win32clipboard.OpenClipboard()
lResult = win32clipboard.GetClipboardData()
win32clipboard.CloseClipboard()
return lResult
################
###GeneralClipboardSet
################
def GeneralClipboardSet(inText):
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardText(inText)
win32clipboard.CloseClipboard()
#run() #run()
lText = "Bitness:" + str(struct.calcsize("P") * 8) lText = "Bitness:" + str(struct.calcsize("P") * 8)
#for line in sys.stdin: #for line in sys.stdin:
@ -941,7 +1062,7 @@ if not mFlagIsDebug:
ProcessParentWriteObject(lJSONInput) ProcessParentWriteObject(lJSONInput)
except Exception as e: except Exception as e:
#Вывод ошибки в родительский поток #Вывод ошибки в родительский поток
ProcessParentWriteObject({'Error':str(e), 'ArgObject':str(lJSONInputString)}) ProcessParentWriteObject({'Error':str(e) + traceback.format_exc(), 'ArgObject':str(lJSONInputString)})
#ctypes.windll.user32.MessageBoxW(0, str(e), "Your title", 1) #ctypes.windll.user32.MessageBoxW(0, str(e), "Your title", 1)
else: else:
print('Debug mode is turned on!') print('Debug mode is turned on!')

Loading…
Cancel
Save