From 0a0bf30bf7a7880a8800301b25e783460494005b Mon Sep 17 00:00:00 2001 From: Ivan Maslov Date: Tue, 12 Mar 2019 20:30:47 +0000 Subject: [PATCH] Update winGUI.py --- winGUI.py | 342 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 342 insertions(+) create mode 100644 winGUI.py diff --git a/winGUI.py b/winGUI.py new file mode 100644 index 00000000..8f64bb12 --- /dev/null +++ b/winGUI.py @@ -0,0 +1,342 @@ +from http.server import BaseHTTPRequestHandler, HTTPServer +from pywinauto import win32defines, win32structures, win32functions +import pdb +import pywinauto +import json +import sys +import ctypes +import struct +import os +import select +import zlib + +#Флаг отладки напрямую (не выполнять чтение буфера stdin) +mFlagIsDebug=False + +#mPywinautoApplication=pywinauto.Application(backend="win32") +mPywinautoApplication=pywinauto.Application(backend="uia") +############################################ +####Межпроцессное взаимодействие +############################################ +#ProcessParentReadWaitString +def ProcessParentReadWaitString(): + #Выполнить чтение строки + #ctypes.windll.user32.MessageBoxW(0, "Hello", "Your title", 1) + lResult = sys.stdin.buffer.readline() + #Вернуть потенциальные \n + lResult = lResult.replace(b'{{n}}',b'\n') + lResult = zlib.decompress(lResult[0:-1]) + lResult = lResult.decode("utf-8") + #Вернуть результат + return lResult + +#ParentProcessWriteString +def ProcessParentWriteString(lString): + lByteString = zlib.compress(lString.encode("utf-8")) + #Выполнить отправку строки в родительский процесс + #Вернуть потенциальные \n + lByteString = lByteString.replace(b'\n',b'{{n}}') + sys.stdout.buffer.write(lByteString+bytes("\n","utf-8")) + sys.stdout.flush(); + return +#ProcessParentWriteObject +def ProcessParentWriteObject(inObject): + #Выполнить отправку сконвертированного объекта в JSON + ProcessParentWriteString(json.dumps(inObject)) + return +#ProcessParentReadWaitObject +def ProcessParentReadWaitObject(): + #Выполнить получение и разбор объекта + lResult=json.loads(ProcessParentReadWaitString()); + return lResult; + +################################## +###Методы взаимодействия с GUI интерфейсом +################################## +#pywinauto +def GetControl(inControlSpecificationArray): + #Подготовка взодного массива + inControlSpecificationArray=ElementSpecificationArraySearchPrepare(inControlSpecificationArray) + #Выполнить идентификацию объектов, если передан массив + lResultList=[]; + if len(inControlSpecificationArray) > 0: + #Выполнить подключение к объекту + lRPAApplication = mPywinautoApplication + #Проверка разрядности + + lRPAApplication.connect(**inControlSpecificationArray[0]) + lTempObject=lRPAApplication.window(**inControlSpecificationArray[0]) + + #Циклическое прохождение к недрам объекта + for lWindowSpecification in inControlSpecificationArray[1:]: + lTempObject=lTempObject.window(**lWindowSpecification) + return lTempObject + + +#Выполнить действие над элементом +def ElementRunAction(inControlSpecificationArray,inActionName,inArgumentList=[],inkwArgumentObject={}): + #Определить объект + lObject=GetControl(inControlSpecificationArray) + #Получить метод для вызова + lFunction = getattr(lObject.wrapper_object(), inActionName) + #Выполнить действие + lFunction(*inArgumentList,**inkwArgumentObject) + return + +def ElementGetInfo(inControlSpecificationArray): + #Подготовка входного массива + inControlSpecificationArray=ElementSpecificationArraySearchPrepare(inControlSpecificationArray) + #Выполнить идентификацию объектов, если передан массив + lResultList=[]; + if len(inControlSpecificationArray) > 0: + #Выполнить подключение к объекту + lRPAApplication = mPywinautoApplication + #Проверка разрядности + + lRPAApplication.connect(**inControlSpecificationArray[0]) + lTempObject=lRPAApplication.window(**inControlSpecificationArray[0]) + + #Циклическое прохождение к недрам объекта + for lWindowSpecification in inControlSpecificationArray[1:]: + lTempObject=lTempObject.window(**lWindowSpecification) + #Получить инфо объект + lTempObjectInfo = lTempObject.wrapper_object().element_info + #Добавить информацию об обнаруженом объекте + lResultList.append(ElementInfoExportObject(lTempObjectInfo)); + return lResultList +#debug +def ElementGetChildElementList(inControlSpecificationArray=[]): + #Подготовка входного массива + inControlSpecificationArray=ElementSpecificationArraySearchPrepare(inControlSpecificationArray) + #Выполнить идентификацию объектов, если передан массив + lResultList=[]; + #ctypes.windll.user32.MessageBoxW(0, str(inControlSpecificationArray), "Your title", 1) + if len(inControlSpecificationArray) > 0: + #Выполнить подключение к объекту + lRPAApplication = mPywinautoApplication + lRPAApplication.connect(**inControlSpecificationArray[0]) + lTempObject=lRPAApplication.window(**inControlSpecificationArray[0]) + + #Циклическое прохождение к недрам объекта + for lWindowSpecification in inControlSpecificationArray[1:]: + lTempObject=lTempObject.window(**lWindowSpecification) + #Получить список дочерних объектов + lTempChildList = lTempObject.wrapper_object().children() + #Подготовить результирующий объект + for lChild in lTempChildList: + lTempObjectInfo=lChild.element_info + #Добавить информацию об обнаруженом объекте + lResultList.append(ElementInfoExportObject(lTempObjectInfo)); + else: + lResultList=GetRootElementList() + return lResultList + +#Подготовить массив для обращшения к поиску элемементов +def ElementSpecificationArraySearchPrepare(inControlSpecificationArray): + lResult=[] + #Циклический обход + for lSpecificationItem in inControlSpecificationArray: + 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 == "process" 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) + #Добавить строку в результирующий массив + lResult.append(lSpecificationItemNew) + #Вернуть результат + return lResult + +#Получить объект из атрибутов, которые удалось прочитать +def ElementInfoExportObject(inElementInfo): + #Подготовить выходную структуру данных + lResult = {"name":None,"rich_text":None,"process_id":None,"handle":None,"class_name":None,"control_type":None,"control_id":None,"rectangle":{"left":None,"top":None,"right":None,"bottom":None}, 'runtime_id':None} + #Проверка name + try: + lResult['name']=inElementInfo.name + except Exception as e: + True == False + #Проверка rich_text + try: + lResult['rich_text']=inElementInfo.rich_text + except Exception as e: + True == False + #Проверка process_id + try: + lResult['process_id']=inElementInfo.process_id + except Exception as e: + True == False + #Проверка handle + try: + lResult['handle']=inElementInfo.handle + except Exception as e: + True == False + #Проверка class_name + try: + lResult['class_name']=inElementInfo.class_name + except Exception as e: + True == False + #Проверка control_type + try: + lResult['control_type']=inElementInfo.control_type + except Exception as e: + True == False + #Проверка control_id + try: + lResult['control_id']=inElementInfo.control_id + except Exception as e: + True == False + #Проверка rectangle left + try: + lResult['rectangle']['left']=inElementInfo.rectangle.left + except Exception as e: + True == False + #Проверка rectangle right + try: + lResult['rectangle']['right']=inElementInfo.rectangle.right + except Exception as e: + True == False + #Проверка rectangle top + try: + lResult['rectangle']['top']=inElementInfo.rectangle.top + except Exception as e: + True == False + #Проверка rectangle bottom + try: + lResult['rectangle']['bottom']=inElementInfo.rectangle.bottom + except Exception as e: + True == False + #Проверка runtime_id + try: + lResult['runtime_id']=inElementInfo.runtime_id + except Exception as e: + True == False + #Вернуть результат + return lResult + +def GetRootElementList(): + #Получить список объектов + lResultList=pywinauto.findwindows.find_elements() + lResultList2=[] + for lI in lResultList: + lTempObjectInfo=lI + lResultList2.append(ElementInfoExportObject(lI)); + return lResultList2 +def ElementDrawOutlineNew(inSpecificationArray): + draw_outline_new(GetControl(inSpecificationArray)) + return +def draw_outline_new(lWrapperObject,colour='green',thickness=2,fill=win32defines.BS_NULL,rect=None): + """ + Draw an outline around the window. + * **colour** can be either an integer or one of 'red', 'green', 'blue' + (default 'green') + * **thickness** thickness of rectangle (default 2) + * **fill** how to fill in the rectangle (default BS_NULL) + * **rect** the coordinates of the rectangle to draw (defaults to + the rectangle of the control) + """ + #pdb.set_trace() + # don't draw if dialog is not visible + #if not lWrapperObject.is_visible(): + # return + colours = { + "green": 0x00ff00, + "blue": 0xff0000, + "red": 0x0000ff, + } + # if it's a known colour + if colour in colours: + colour = colours[colour] + if rect is None: + rect = lWrapperObject.rectangle() + # create the pen(outline) + pen_handle = win32functions.CreatePen( + win32defines.PS_SOLID, thickness, colour) + # create the brush (inside) + brush = win32structures.LOGBRUSH() + brush.lbStyle = fill + brush.lbHatch = win32defines.HS_DIAGCROSS + brush_handle = win32functions.CreateBrushIndirect(ctypes.byref(brush)) + # get the Device Context + dc = win32functions.CreateDC("DISPLAY", None, None, None ) + # push our objects into it + win32functions.SelectObject(dc, brush_handle) + win32functions.SelectObject(dc, pen_handle) + # draw the rectangle to the DC + win32functions.Rectangle( + dc, rect.left, rect.top, rect.right, rect.bottom) + # Delete the brush and pen we created + win32functions.DeleteObject(brush_handle) + win32functions.DeleteObject(pen_handle) + # delete the Display context that we created + win32functions.DeleteDC(dc) + +#run() +lText = "Bitness:" + str(struct.calcsize("P") * 8) +#for line in sys.stdin: +# lText=lText+line; +#ctypes.windll.user32.MessageBoxW(0, lText, "Your title", 1) + +buffer = "" +lJSONInputString="" +#Выполнить чтение буфера, если не отладка библиотеки +if not mFlagIsDebug: + #{'functionName':'', 'argsArray':[]} + while True: + try: + lJSONInput = ProcessParentReadWaitObject() + lJSONInputString=str(lJSONInput) + #{'outputObject':''} + #Выполнить вызов функции + + lResult=locals()[lJSONInput['functionName']](*lJSONInput['argsArray']) + lJSONInput['outputObject']=lResult + ProcessParentWriteObject(lJSONInput) + except Exception as e: + #Вывод ошибки в родительский поток + ProcessParentWriteObject({'Error':str(e), 'ArgObject':str(lJSONInputString)}) +else: + print('Debug mode is turned on!') + +#if __name__ == '__main__': +# if len(sys.argv) > 1: +# lFunctionArgs = sys.argv[2:] +# print(locals()[sys.argv[1]](*lFunctionArgs)) + +