from pyautogui import * import pyscreeze import ctypes from pyOpenRPA.Tools import CrossOS if CrossOS.IS_WINDOWS_BOOL: from pywinauto import win32defines, win32structures, win32functions def BoxCreate(inTopInt:int, inLeftInt:int, inHeightInt:int, inWidthInt:int) -> pyscreeze.Box: """Создать экземпляр прямоугольной области. !ВНИМАНИЕ! Координаты inTopInt, inLeftInt определяют верхний левый край прямоугольной области. :param inTopInt: Координата левой верхней точки в пикселях по оси X (горизонталь) :type inTopInt: int :param inLeftInt: Координата левой верхней точки в пикселях по оси Y (вертикаль) :type inLeftInt: int :param inHeightInt: Расстояние вниз от левой верхней точки в пикселях :type inHeightInt: int :param inWidthInt: Расстояние вправо от левой верхней точки в пикселях :type inWidthInt: int """ return pyscreeze.Box(top = inTopInt, left = inLeftInt, height = inHeightInt, width = inWidthInt) def BoxNormalize(*inArgList, **inAgrDict) -> list: pass def BoxMoveTo(inBox, inDXInt=None, inDYInt=None): """Переместить прямоугольную область (сохранить длину/ширину). !ВНИМАНИЕ! ПОДДЕРЖИВАЕТ ПАКЕТНУЮ ОБРАТКУ ПРИ ПЕРЕДАЧЕ СПИСКА ЭКЗЕМПЛЯРОВ BOX .. code-block:: python # Screen: Взаимодействие с экраном from pyOpenRPA.Robot import Screen # Вариант изменения 1-го элемента # Создать пробную прямоугольную область lBox = Screen.BoxCreate(inTopInt=10, inLeftInt=10, inHeightInt=10, inWidthInt=10) # Переместить пробную прямоугольную область lBox = Screen.BoxMoveTo(lBox, inDXInt=100, inDYInt=200) :param inBox: Экземпляр класса прямоугольной области Box :type inBox: pyscreeze.Box :param inDXInt: Смещение левой верхней координаты по оси X в пикселях (горизонтальная ось). :type inDXInt: int, опциональный :param inDYInt: Смещение левой верхней координаты по оси Y в пикселях (вертикальная ось). :type inDYInt: int, опциональный :return: Экземпляр класса прямоугольной области Box :rtype: pyscreeze.Box """ if type(inBox) is list: lResult = [] for lBox in inBox: lResult.append(BoxMoveTo(lBox, inDXInt=inDXInt, inDYInt=inDYInt)) return lResult else: lTopInt = inBox.top lLeftInt = inBox.left if inDXInt: lLeftInt = inBox.left + inDXInt if inDYInt: lTopInt = inBox.top + inDYInt return BoxCreate(inTopInt=lTopInt, inLeftInt=lLeftInt, inHeightInt=inBox.height, inWidthInt=inBox.width) def BoxModify(inBox, inDWidthInt=None, inDHeightInt=None, inAnchorStr="CC"): """Изменить ширину / высоту прямоугольной области. !ВНИМАНИЕ! ПОДДЕРЖИВАЕТ ПАКЕТНУЮ ОБРАТКУ ПРИ ПЕРЕДАЧЕ СПИСКА ЭКЗЕМПЛЯРОВ BOX !ВНИМАНИЕ! ЕСЛИ СМЕЩЕНИЕ ПРИВЕДЕТ К ОБРАЗОВАНИЮ ДРОБНОГО ЧИСЛА, БУДЕТ ВЫПОЛНЕНО ОКРУГЛЕНИЕ ПО МАТЕМАТИЧЕСКИМ ПРАВИЛАМ .. code-block:: python # Screen: Взаимодействие с экраном from pyOpenRPA.Robot import Screen # Вариант изменения 1-го элемента # Создать пробную прямоугольную область lBox = Screen.BoxCreate(inTopInt=10, inLeftInt=10, inHeightInt=10, inWidthInt=10) # Скорректировать пробную прямоугольную область lBox2 = Screen.BoxModify(lBox,10,10,"CC"); print(lBox2) lBox2 = Screen.BoxModify(lBox,10,10,"LU"); print(lBox2) lBox2 = Screen.BoxModify(lBox,10,10,"LD"); print(lBox2) lBox2 = Screen.BoxModify(lBox,10,10,"RU"); print(lBox2) lBox2 = Screen.BoxModify(lBox,10,10,"RD"); print(lBox2) :param inBox: Экземпляр класса прямоугольной области Box :type inBox: pyscreeze.Box :param inDXInt: Смещение левой верхней координаты по оси X в пикселях (горизонтальная ось). :type inDXInt: int, опциональный :param inDYInt: Смещение левой верхней координаты по оси Y в пикселях (вертикальная ось). :type inDYInt: int, опциональный :param inAnchorStr: Символьное указание точки (подробнее см. выше), относительно которой выполнить изменение прямоугольной области. Допустимые значения: "CC" (по умолчанию), "LU", "LD", "RD", "RU" :type inAnchorStr: str, опциональный :return: Экземпляр класса прямоугольной области Box :rtype: pyscreeze.Box """ if type(inBox) is list: lResult = [] for lBox in inBox: lResult.append(BoxModify(lBox, inDWidthInt=inDWidthInt, inDHeightInt=inDHeightInt, inAnchorStr=inAnchorStr)) return lResult else: lTopInt = inBox.top lLeftInt = inBox.left lWidthInt = inBox.width + inDWidthInt lHeightInt = inBox.height + inDHeightInt inAnchorStr = inAnchorStr.upper() # ВЕРХНИЙ РЕГИСТР if inDWidthInt: # Изменения по ширине if "C" in inAnchorStr: lLeftInt = round(lLeftInt - inDWidthInt / 2) elif "R" in inAnchorStr: lLeftInt = lLeftInt - inDWidthInt if inDHeightInt: # Изменения по высоте if "C" in inAnchorStr: lTopInt = round(lTopInt - inDHeightInt / 2) elif "D" in inAnchorStr: lTopInt = lTopInt - inDHeightInt return BoxCreate(inTopInt=lTopInt, inLeftInt=lLeftInt, inHeightInt=lHeightInt, inWidthInt=lWidthInt) def BoxDraw(inBox, inColorStr='green',inThicknessInt = 2): """ Выполнить подсветку прямоугольной области inBox на экране !ВНИМАНИЕ! РАБОТАЕТ ТОЛЬКО НА ОС WINDOWS !ВНИМАНИЕ! ПОДДЕРЖИВАЕТ ПАКЕТНУЮ ОБРАТКУ ПРИ ПЕРЕДАЧЕ СПИСКА ЭКЗЕМПЛЯРОВ BOX .. code-block:: python # Screen: Взаимодействие с экраном from pyOpenRPA.Robot import Screen # ВАРИАНТ ОТРИСОВКИ 1ГО ЭЛЕМЕНТА # Создать пробную прямоугольную область lBox = Screen.BoxCreate(inTopInt=10, inLeftInt=10, inHeightInt=10, inWidthInt=10) Screen.BoxDraw(lBox) # ВАРИАНТ ПАКЕТНОЙ ОТРИСОВКИ # Создать пробную прямоугольную область lBox = Screen.BoxCreate(inTopInt=10, inLeftInt=10, inHeightInt=100, inWidthInt=100) lBox2 = Screen.BoxCreate(inTopInt=60, inLeftInt=60, inHeightInt=100, inWidthInt=100) Screen.BoxDraw([lBox, lBox2]) :param inBox: UIO объект, который будет подсвечен :type inBox: object UIO, обязательный :param inColorStr: цвет подсветки UIO объекта. Варианты: 'red', 'green', 'blue'. По умолчанию 'green' :type inColorStr: str, необязательный :param inThicknessInt: толщина подсветки UIO объекта. По умолчанию 2 :type inThicknessInt: int, необязательный """ if type(inBox) is list: for lBox in inBox: BoxDraw(inBox=lBox, inColorStr=inColorStr,inThicknessInt = inThicknessInt) else: fill = win32defines.BS_NULL if inBox is not None: """ Draw an outline around the window. * **inColorStr** can be either an integer or one of 'red', 'green', 'blue' (default 'green') * **inThicknessInt** inThicknessInt of rectangle (default 2) * **fill** how to fill in the rectangle (default BS_NULL) """ # 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 inColorStr in colours: inColorStr = colours[inColorStr] # create the pen(outline) pen_handle = win32functions.CreatePen( win32defines.PS_SOLID, inThicknessInt, inColorStr) # 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, inBox.left, inBox.top, inBox.left+inBox.width, inBox.top+inBox.height) # 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)