@ -460,109 +460,13 @@ def UIOSelector_Get_UIOInfo(inControlSpecificationArray):
lResultList . append ( ElementInfoExportObject ( lTempObjectInfo ) ) ;
lResultList . append ( ElementInfoExportObject ( lTempObjectInfo ) ) ;
return lResultList
return lResultList
############################
#Старая версия
############################
mFlagIsDebug = False
##################################
############################################
###Модуль поиска объекта на экране
############################################
#Инициализация глобальных переменных
mBitmap = { }
mGUISearchElementSelected = { }
def GUISearchEvent_on_move ( lX , lY ) :
global mBitmap
global mGUISearchElementSelected
if ( lX , lY ) in mBitmap :
if mGUISearchElementSelected != mBitmap [ lX , lY ] :
mGUISearchElementSelected = mBitmap [ lX , lY ]
mBitmap [ lX , lY ] . draw_outline ( )
def GUISearchEvent_on_click ( x , y , button , pressed ) :
global mBitmap
global mGUISearchElementSelected
print ( ' {0} at {1} ' . format (
' Pressed ' if pressed else ' Released ' ,
( x , y ) ) )
print ( str ( len ( mBitmap ) ) )
if not pressed :
# Stop listener
del mBitmap
mBitmap = { }
del mGUISearchElementSelected
mGUISearchElementSelected = { }
return False
def GUISearchEvent_on_scroll ( x , y , dx , dy ) :
print ( ' Scrolled {0} at {1} ' . format (
' down ' if dy < 0 else ' up ' ,
( x , y ) ) )
#Создать bitmap карту объектов
#GUISearchBitmapCreate
#inElement - wrapper_object()
# dict: x_y_ : elementObject
def GUISearchRun ( inSpecificationArray ) :
lBitmap = { }
lGUISearchElementSelected = None
#Создать карту пикселей и элементов
lBitmap = GUISearchBitmapCreate ( GetControl ( inSpecificationArray ) , lBitmap )
#Выдать сообщение, что поиск готов к использованию
#print("GUISearch: Ready for search!")
#mBitmap=lBitmap
# Collect events until released
#Версия с Events (занимает поток, чтобы использовать общие переменные)
#with mouse.Listener(
# on_move=GUISearchEvent_on_move,
# on_click=GUISearchEvent_on_click,
# on_scroll=GUISearchEvent_on_scroll) as listener:
#listener.join()
# True == False
#####################
###Версия с таймером
#####################
#mTimer = RepeatedTimer(0.5, GUISearchDraw, lBitmap) # it auto-starts, no need of rt.start()
#mTimer.start()
###########
#Версия с задержкой
###########
#Сбросить нажатие Ctrl, если оно было
bool ( win32api . GetAsyncKeyState ( 17 ) )
lTimeSleepSeconds = 0.7
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 ]
lBitmap [ lX , lY ] . draw_outline ( )
else :
lGUISearchElementSelected = None
else :
#Была нажата клавиша Ctrl - выйти из цикла
lFlagLoop = False ;
#Заснуть до следующего цикла
time . sleep ( lTimeSleepSeconds )
#Вернуть результат поиска
return lGUISearchElementSelected
#############################################################
####################################################################################################
#Поиск элементов
#Search child UIO by the: Parent UIO, X, Y
#############################################################
#inHierarchyList: [{"index":<>,"element":<>}] - technical argument for internal purpose
#inHierarchyList: [{"index":<>,"element":<>}]
#result -List of dict [{"index":<>,"element":<>}] -- list of element hierarchy specifications
#
#old name - GUISearchElementByRootXY
#Вернуть словарь [{"index":<>,"element":<>}]
def UIOXY_SearchChild_ListDict ( inRootElement , inX , inY , inHierarchyList = [ ] ) :
#Последний элемент - искомый
def GUISearchElementByRootXY ( inRootElement , inX , inY , inHierarchyList = [ ] ) :
#Инициализация результирующего значения
#Инициализация результирующего значения
lResultElement = None
lResultElement = None
lResultElementX1 = None
lResultElementX1 = None
@ -645,92 +549,12 @@ def GUISearchElementByRootXY(inRootElement,inX,inY,inHierarchyList=[]):
except Exception as e :
except Exception as e :
False == False
False == False
return lResultHierarchyList
return lResultHierarchyList
#Техническая функция
def GUISearchBitmapCreate ( inElement , inBitmapDict = { } ) :
#Добавить в карту информацию о текущем объекте
inBitmapDict = GUISearchBitmapElementFill ( inElement , inBitmapDict )
#Получить список детей и добавить в карту
for lItem in inElement . children ( ) :
inBitmapDict = GUISearchBitmapCreate ( lItem , inBitmapDict )
return inBitmapDict
#GUISearchBitmapElementFill
###################################################################################################
def GUISearchBitmapElementFill ( inElement , inBitmapDict ) :
#Get list of child UIO's by Parent UIOSelector
lElementInfo = inElement . element_info
#inControlSpecificationArray- UIOSelector
#pdb.set_trace()
#old name - ElementGetChildElementList
#Получить параметры прямоугольника
def UIOSelector_GetChildList_UIOList ( inControlSpecificationArray = [ ] ) :
lElementRectX1 = 0
lElementRectX2 = 0
lElementRectY1 = 0
lElementRectY2 = 0
lFlagHasRect = True
try :
lElementRectX1 = lElementInfo . rectangle . left
lElementRectX2 = lElementInfo . rectangle . right
lElementRectY1 = lElementInfo . rectangle . top
lElementRectY2 = lElementInfo . rectangle . bottom
#Выполнить установку элемента, если прямоугольник получить удалось
if lFlagHasRect :
lX = lElementRectX1
#Циклический обход по оси X
while lX < = lElementRectX2 :
lY = lElementRectY1
#Циклический обход по Оси Y
while lY < = lElementRectY2 :
######################
#Если объект в карте есть
if ( lX , lY ) in inBitmapDict :
if inBitmapDict [ lX , lY ] is not None :
#Правила перезатирания карты, если имеется старый объект
#[Накладываемый объект] - Н О - ElementNew
#[Имеющийся объект] - ИО - ElementOld
#3 типа вхождения объектов
#тип 1 - [имеющийся объект] полностью входит в [накладываемый объект] (ИО X1 Y1 >= Н О X1 Y1; ИО X2 Y2 <= Н О X2 Y2) - не вносить Н О в bitmap в эти диапазоны
#тип 2 - [имеющийся объект] полностью выходит за пределы [накладываемого объекта] (ИО X1 Y1 < Н О X1 Y1; ИО X2 Y2 > Н О X2 Y2) - вносить Н О в bitmap
#тип 3 - [имеющийся объект] частично входит в [накладываемый объект] (все остальные случаи)- вносить Н О в bitmap
#Получить координаты ИО
lElementOldInfo = inBitmapDict [ lX , lY ] . element_info
#lElementNew = inElement
lElementOldX1 = lElementOldInfo . rectangle . left
lElementOldX2 = lElementOldInfo . rectangle . right
lElementOldY1 = lElementOldInfo . rectangle . top
lElementOldY2 = lElementOldInfo . rectangle . bottom
#Проверка вхождения по типу 1
if ( lElementOldX1 > = lElementRectX1 ) and ( lElementOldY1 > = lElementRectY1 ) and ( lElementOldX2 < = lElementRectX2 ) and ( lElementOldY2 < = lElementRectY2 ) :
#Выполнить корректировку каретки по lY, чтобы не проходить по всем пикселям в рамках этой линии
lY = lElementOldY2 + 1
#Проверка вхождения по типу 3
elif ( lElementOldX1 < lElementRectX1 ) and ( lElementOldY1 < lElementRectY1 ) and ( lElementOldX2 > lElementRectX2 ) and ( lElementOldY2 > lElementRectY2 ) :
#Установка элемента по адресу [<x>,<y>]
inBitmapDict [ lX , lY ] = inElement
#Инкремент y
lY = lY + 1
#Проверка вхождения по типу 2
else :
#Установка элемента по адресу [<x>,<y>]
inBitmapDict [ lX , lY ] = inElement
#Инкремент y
lY = lY + 1
#Если объекта в карте нет
else :
#Установка элемента по адресу [<x>,<y>]
inBitmapDict [ lX , lY ] = inElement
#Инкремент y
lY = lY + 1
else :
#Установка элемента по адресу [<x>,<y>]
inBitmapDict [ lX , lY ] = inElement
#Инкремент y
lY = lY + 1
######################
#Инкремент X
lX = lX + 1
except Exception as e :
lFlagHasRect = False
return inBitmapDict
#debug
def ElementGetChildElementList ( inControlSpecificationArray = [ ] ) :
#Подготовка входного массива
#Подготовка входного массива
inControlSpecificationArray = ElementSpecificationArraySearchPrepare ( inControlSpecificationArray )
inControlSpecificationArray = ElementSpecificationArraySearchPrepare ( inControlSpecificationArray )
#Выполнить идентификацию объектов, если передан массив
#Выполнить идентификацию объектов, если передан массив
@ -755,64 +579,13 @@ def ElementGetChildElementList(inControlSpecificationArray=[]):
else :
else :
lResultList = GetRootElementList ( )
lResultList = GetRootElementList ( )
return lResultList
return lResultList
#Подготовить спецификацию для поиска элемента
def ElementSpecificationListNormalize ( inElementSpecification ) :
lResult = [ ]
#Циклический обход
for lSpecificationItem in inElementSpecification :
lSpecificationItemNew = lSpecificationItem . copy ( )
#Перебор всех элементов
for lItemKey , lItemValue in lSpecificationItem . items ( ) :
#Флаг удаления атрибута
lFlagRemoveAttribute = False
#############################
#Если является вложенным словарем - удалить
if type ( lItemValue ) is dict :
lFlagRemoveAttribute = True
#Является типом None
if lItemValue is None :
lFlagRemoveAttribute = True
#Проверка допустимого ключевого слова
if (
lItemKey == " class_name " or
lItemKey == " class_name_re " or
lItemKey == " parent " or
lItemKey == " title " or
lItemKey == " title_re " or
lItemKey == " top_level_only " or
lItemKey == " visible_only " or
lItemKey == " enabled_only " or
lItemKey == " best_match " or
lItemKey == " handle " or
lItemKey == " ctrl_index " or
lItemKey == " found_index " or
lItemKey == " predicate_func " or
lItemKey == " active_only " or
lItemKey == " control_id " or
lItemKey == " control_type " or
lItemKey == " auto_id " or
lItemKey == " framework_id " or
lItemKey == " backend " ) :
True == True
else :
lFlagRemoveAttribute = True
#############################
####################################################################################################
#Конструкция по удалению ключа из словаря
if lFlagRemoveAttribute :
lSpecificationItemNew . pop ( lItemKey )
#Проверит наличие ctrl_index - если он есть, то удалить control_id и control_type из-за того, что они мешают друг другу
if ' ctrl_index ' in lSpecificationItemNew :
if " control_id " in lSpecificationItemNew :
lSpecificationItemNew . pop ( " control_id " )
if " control_type " in lSpecificationItemNew :
lSpecificationItemNew . pop ( " control_type " )
#Добавить строку в результирующий массив
lResult . append ( lSpecificationItemNew )
#Вернуть результат
return lResult
#Подготовить массив для обращшения к поиску элемементов
#Подготовить массив для обращшения к поиску элемементов
def ElementSpecificationArraySearchPrepare ( inControlSpecificationArray ) :
#inControlSpecificationArray - UIOSelector (can be dirty)
#old name 1 - ElementSpecificationArraySearchPrepare
#old name 2 - ElementSpecificationListNormalize
def UIOSelector_SearchNormalize_UIOSelector ( inControlSpecificationArray ) :
lResult = [ ]
lResult = [ ]
#Циклический обход
#Циклический обход
for lSpecificationItem in inControlSpecificationArray :
for lSpecificationItem in inControlSpecificationArray :
@ -869,66 +642,16 @@ def ElementSpecificationArraySearchPrepare(inControlSpecificationArray):
lResult . append ( lSpecificationItemNew )
lResult . append ( lSpecificationItemNew )
#Вернуть результат
#Вернуть результат
return lResult
return lResult
###############################
####Нормализация под JSON (в JSON нельзя передавать классы - только null, числа, строки, словари и массивы)
###############################
#Нормализация словаря под JSON
############################
def JSONNormalizeDictionary ( inDictionary ) :
#Старая версия
#Сделать копию объекта
############################
lResult = inDictionary . copy ( )
mFlagIsDebug = False
#Перебор всех элементов
for lItemKey , lItemValue in inDictionary . items ( ) :
#Флаг удаления атрибута
lFlagRemoveAttribute = False
#Если строка или число или массив или объект или None - оставить
if (
type ( lItemValue ) is dict or
type ( lItemValue ) is int or
type ( lItemValue ) is str or
type ( lItemValue ) is list or
lItemValue is None ) :
True == True
else :
lFlagRemoveAttribute = True
#Рекурсивный вызов, если объект является словарем
if type ( lItemValue ) is dict :
lResult [ lItemKey ] = JSONNormalizeDictionary ( lItemValue )
#Рекурсивный вызов, если объект является списком
if type ( lItemValue ) is list :
lResult [ lItemKey ] = JSONNormalizeList ( lItemValue )
#############################
#Конструкция по удалению ключа из словаря
if lFlagRemoveAttribute :
lResult . pop ( lItemKey )
#Вернуть результат
return lResult
#Нормализация массива под JSON
def JSONNormalizeList ( inList ) :
lResult = [ ]
#Циклический обход
for lItemValue in inList :
#Если строка или число или массив или объект или None - оставить
if (
type ( lItemValue ) is int or
type ( lItemValue ) is str or
lItemValue is None ) :
lResult . append ( lItemValue )
#Если является словарем - вызвать функцию нормализации словаря
if type ( lItemValue ) is dict :
lResult . append ( JSONNormalizeDictionary ( lItemValue ) )
#Если является массиваом - вызвать функцию нормализации массива
if type ( lItemValue ) is list :
lResult . append ( JSONNormalizeList ( lItemValue ) )
#Вернуть результат
return lResult
#Определить объект - dict or list - и нормализовать е г о для JSON
def JSONNormalizeDictList ( inDictList ) :
lResult = { }
if type ( inDictList ) is dict :
lResult = JSONNormalizeDictionary ( inDictList )
if type ( inDictList ) is list :
lResult = JSONNormalizeList ( inDictList )
return lResult ;
#Получить объект из атрибутов, которые удалось прочитать
#Получить объект из атрибутов, которые удалось прочитать
def ElementInfoExportObject ( inElementInfo ) :
def ElementInfoExportObject ( inElementInfo ) :
#Подготовить выходную структуру данных
#Подготовить выходную структуру данных