def WindowFromPoint(x: int, y: int) -> int:

return ctypes.windll.user32.WindowFromPoint(ctypes.wintypes.POINT(x, y))<EOL>

WindowFromPoint from Win32.
Return int, a native window handle.


point = ctypes.wintypes.POINT(<NUM_LIT:0>, <NUM_LIT:0>)<EOL>ctypes.windll.user32.GetCursorPos(ctypes.byref(point))<EOL>return point.x, point.y<EOL>

GetCursorPos from Win32.
Get current mouse cursor positon.
Return tuple, two ints tuple (x, y).


def SetCursorPos(x: int, y: int) -> bool:

return bool(ctypes.windll.user32.SetCursorPos(x, y))<EOL>

SetCursorPos from Win32.
Set mouse cursor to point x, y.
x: int.
y: int.
Return bool, True if succeed otherwise False.


return ctypes.windll.user32.GetDoubleClickTime()<EOL>

GetDoubleClickTime from Win32.
Return int, in milliseconds.


def mouse_event(dwFlags: int, dx: int, dy: int, dwData: int, dwExtraInfo: int) -> None:

ctypes.windll.user32.mouse_event(dwFlags, dx, dy, dwData, dwExtraInfo)<EOL>


def keybd_event(bVk: int, bScan: int, dwFlags: int, dwExtraInfo: int) -> None:

ctypes.windll.user32.keybd_event(bVk, bScan, dwFlags, dwExtraInfo)<EOL>


def PostMessage(handle: int, msg: int, wParam: int, lParam: int) -> bool:

return bool(ctypes.windll.user32.PostMessageW(ctypes.c_void_p(handle), msg, wParam, lParam))<EOL>

PostMessage from Win32.
Return bool, True if succeed otherwise False.


def SendMessage(handle: int, msg: int, wParam: int, lParam: int) -> int:

return ctypes.windll.user32.SendMessageW(ctypes.c_void_p(handle), msg, wParam, lParam)<EOL>

SendMessage from Win32.
Return int, the return value specifies the result of the message processing;
            it depends on the message sent.


def Click(x: int, y: int, waitTime: float = OPERATION_WAIT_TIME) -> None:

SetCursorPos(x, y)<EOL>screenWidth, screenHeight = GetScreenSize()<EOL>mouse_event(MouseEventFlag.LeftDown | MouseEventFlag.Absolute, x * <NUM_LIT> // screenWidth, y * <NUM_LIT> // screenHeight, <NUM_LIT:0>, <NUM_LIT:0>)<EOL>time.sleep(<NUM_LIT>)<EOL>mouse_event(MouseEventFlag.LeftUp | MouseEventFlag.Absolute, x * <NUM_LIT> // screenWidth, y * <NUM_LIT> // screenHeight, <NUM_LIT:0>, <NUM_LIT:0>)<EOL>time.sleep(waitTime)<EOL>

Simulate mouse click at point x, y.
x: int.
y: int.
waitTime: float.


def MiddleClick(x: int, y: int, waitTime: float = OPERATION_WAIT_TIME) -> None:

SetCursorPos(x, y)<EOL>screenWidth, screenHeight = GetScreenSize()<EOL>mouse_event(MouseEventFlag.MiddleDown | MouseEventFlag.Absolute, x * <NUM_LIT> // screenWidth, y * <NUM_LIT> // screenHeight, <NUM_LIT:0>, <NUM_LIT:0>)<EOL>time.sleep(<NUM_LIT>)<EOL>mouse_event(MouseEventFlag.MiddleUp | MouseEventFlag.Absolute, x * <NUM_LIT> // screenWidth, y * <NUM_LIT> // screenHeight, <NUM_LIT:0>, <NUM_LIT:0>)<EOL>time.sleep(waitTime)<EOL>

Simulate mouse middle click at point x, y.
x: int.
y: int.
waitTime: float.


def RightClick(x: int, y: int, waitTime: float = OPERATION_WAIT_TIME) -> None:

SetCursorPos(x, y)<EOL>screenWidth, screenHeight = GetScreenSize()<EOL>mouse_event(MouseEventFlag.RightDown | MouseEventFlag.Absolute, x * <NUM_LIT> // screenWidth, y * <NUM_LIT> // screenHeight, <NUM_LIT:0>, <NUM_LIT:0>)<EOL>time.sleep(<NUM_LIT>)<EOL>mouse_event(MouseEventFlag.RightUp | MouseEventFlag.Absolute, x * <NUM_LIT> // screenWidth, y * <NUM_LIT> // screenHeight, <NUM_LIT:0>, <NUM_LIT:0>)<EOL>time.sleep(waitTime)<EOL>

Simulate mouse right click at point x, y.
x: int.
y: int.
waitTime: float.


def PressMouse(x: int, y: int, waitTime: float = OPERATION_WAIT_TIME) -> None:

SetCursorPos(x, y)<EOL>screenWidth, screenHeight = GetScreenSize()<EOL>mouse_event(MouseEventFlag.LeftDown | MouseEventFlag.Absolute, x * <NUM_LIT> // screenWidth, y * <NUM_LIT> // screenHeight, <NUM_LIT:0>, <NUM_LIT:0>)<EOL>time.sleep(waitTime)<EOL>

Press left mouse.
x: int.
y: int.
waitTime: float.


def ReleaseMouse(waitTime: float = OPERATION_WAIT_TIME) -> None:

x, y = GetCursorPos()<EOL>screenWidth, screenHeight = GetScreenSize()<EOL>mouse_event(MouseEventFlag.LeftUp | MouseEventFlag.Absolute, x * <NUM_LIT> // screenWidth, y * <NUM_LIT> // screenHeight, <NUM_LIT:0>, <NUM_LIT:0>)<EOL>time.sleep(waitTime)<EOL>


def RightPressMouse(x: int, y: int, waitTime: float = OPERATION_WAIT_TIME) -> None:

SetCursorPos(x, y)<EOL>screenWidth, screenHeight = GetScreenSize()<EOL>mouse_event(MouseEventFlag.RightDown | MouseEventFlag.Absolute, x * <NUM_LIT> // screenWidth, y * <NUM_LIT> // screenHeight, <NUM_LIT:0>, <NUM_LIT:0>)<EOL>time.sleep(waitTime)<EOL>

Press right mouse.
x: int.
y: int.
waitTime: float.


def RightReleaseMouse(waitTime: float = OPERATION_WAIT_TIME) -> None:

x, y = GetCursorPos()<EOL>screenWidth, screenHeight = GetScreenSize()<EOL>mouse_event(MouseEventFlag.RightUp | MouseEventFlag.Absolute, x * <NUM_LIT> // screenWidth, y * <NUM_LIT> // screenHeight, <NUM_LIT:0>, <NUM_LIT:0>)<EOL>time.sleep(waitTime)<EOL>


def MoveTo(x: int, y: int, moveSpeed: float = <NUM_LIT:1>, waitTime: float = OPERATION_WAIT_TIME) -> None:

if moveSpeed <= <NUM_LIT:0>:<EOL><INDENT>moveTime = <NUM_LIT:0><EOL><DEDENT>else:<EOL><INDENT>moveTime = MAX_MOVE_SECOND / moveSpeed<EOL><DEDENT>curX, curY = GetCursorPos()<EOL>xCount = abs(x - curX)<EOL>yCount = abs(y - curY)<EOL>maxPoint = max(xCount, yCount)<EOL>screenWidth, screenHeight = GetScreenSize()<EOL>maxSide = max(screenWidth, screenHeight)<EOL>minSide = min(screenWidth, screenHeight)<EOL>if maxPoint > minSide:<EOL><INDENT>maxPoint = minSide<EOL><DEDENT>if maxPoint < maxSide:<EOL><INDENT>maxPoint = <NUM_LIT:100> + int((maxSide - <NUM_LIT:100>) / maxSide * maxPoint)<EOL>moveTime = moveTime * maxPoint * <NUM_LIT:1.0> / maxSide<EOL><DEDENT>stepCount = maxPoint // <NUM_LIT:20><EOL>if stepCount > <NUM_LIT:1>:<EOL><INDENT>xStep = (x - curX) * <NUM_LIT:1.0> / stepCount<EOL>yStep = (y - curY) * <NUM_LIT:1.0> / stepCount<EOL>interval = moveTime / stepCount<EOL>for i in range(stepCount):<EOL><INDENT>cx = curX + int(xStep * i)<EOL>cy = curY + int(yStep * i)<EOL>SetCursorPos(cx, cy)<EOL>time.sleep(interval)<EOL><DEDENT><DEDENT>SetCursorPos(x, y)<EOL>time.sleep(waitTime)<EOL>

Simulate mouse move to point x, y from current cursor.
x: int.
y: int.
moveSpeed: float, 1 normal speed, < 1 move slower, > 1 move faster.
waitTime: float.


def DragDrop(x1: int, y1: int, x2: int, y2: int, moveSpeed: float = <NUM_LIT:1>, waitTime: float = OPERATION_WAIT_TIME) -> None:

PressMouse(x1, y1, <NUM_LIT>)<EOL>MoveTo(x2, y2, moveSpeed, <NUM_LIT>)<EOL>ReleaseMouse(waitTime)<EOL>

Simulate mouse left button drag from point x1, y1 drop to point x2, y2.
x1: int.
y1: int.
x2: int.
y2: int.
moveSpeed: float, 1 normal speed, < 1 move slower, > 1 move faster.
waitTime: float.


def RightDragDrop(x1: int, y1: int, x2: int, y2: int, moveSpeed: float = <NUM_LIT:1>, waitTime: float = OPERATION_WAIT_TIME) -> None:

RightPressMouse(x1, y1, <NUM_LIT>)<EOL>MoveTo(x2, y2, moveSpeed, <NUM_LIT>)<EOL>RightReleaseMouse(waitTime)<EOL>

Simulate mouse right button drag from point x1, y1 drop to point x2, y2.
x1: int.
y1: int.
x2: int.
y2: int.
moveSpeed: float, 1 normal speed, < 1 move slower, > 1 move faster.
waitTime: float.


def WheelDown(wheelTimes: int = <NUM_LIT:1>, interval: float = <NUM_LIT>, waitTime: float = OPERATION_WAIT_TIME) -> None:

for i in range(wheelTimes):<EOL><INDENT>mouse_event(MouseEventFlag.Wheel, <NUM_LIT:0>, <NUM_LIT:0>, -<NUM_LIT>, <NUM_LIT:0>)    <EOL>time.sleep(interval)<EOL><DEDENT>time.sleep(waitTime)<EOL>

Simulate mouse wheel down.
wheelTimes: int.
interval: float.
waitTime: float.


def WheelUp(wheelTimes: int = <NUM_LIT:1>, interval: float = <NUM_LIT>, waitTime: float = OPERATION_WAIT_TIME) -> None:

for i in range(wheelTimes):<EOL><INDENT>mouse_event(MouseEventFlag.Wheel, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT>, <NUM_LIT:0>) <EOL>time.sleep(interval)<EOL><DEDENT>time.sleep(waitTime)<EOL>

Simulate mouse wheel up.
wheelTimes: int.
interval: float.
waitTime: float.


SM_CXSCREEN = <NUM_LIT:0><EOL>SM_CYSCREEN = <NUM_LIT:1><EOL>w = ctypes.windll.user32.GetSystemMetrics(SM_CXSCREEN)<EOL>h = ctypes.windll.user32.GetSystemMetrics(SM_CYSCREEN)<EOL>return w, h<EOL>

Return tuple, two ints tuple (width, height).


def GetPixelColor(x: int, y: int, handle: int = <NUM_LIT:0>) -> int:

hdc = ctypes.windll.user32.GetWindowDC(ctypes.c_void_p(handle))<EOL>bgr = ctypes.windll.gdi32.GetPixel(hdc, x, y)<EOL>ctypes.windll.user32.ReleaseDC(ctypes.c_void_p(handle), hdc)<EOL>return bgr<EOL>

Get pixel color of a native window.
x: int.
y: int.
handle: int, the handle of a native window.
Return int, the bgr value of point (x,y).
r = bgr & 0x0000FF
g = (bgr & 0x00FF00) >> 8
b = (bgr & 0xFF0000) >> 16
If handle is 0, get pixel from Desktop window(root control).
Note:
Not all devices support GetPixel.
An application should call GetDeviceCaps to determine whether a specified device supports this function.
For example, console window doesn't support.


def MessageBox(content: str, title: str, flags: int = MB.Ok) -> int:

return ctypes.windll.user32.MessageBoxW(ctypes.c_void_p(<NUM_LIT:0>), ctypes.c_wchar_p(content), ctypes.c_wchar_p(title), flags)<EOL>

MessageBox from Win32.
content: str.
title: str.
flags: int, a value or some combined values in class `MB`.
Return int, a value in MB whose name starts with Id, such as MB.IdOk


def SetForegroundWindow(handle: int) -> bool:

return bool(ctypes.windll.user32.SetForegroundWindow(ctypes.c_void_p(handle)))<EOL>

SetForegroundWindow from Win32.
handle: int, the handle of a native window.
Return bool, True if succeed otherwise False.


def BringWindowToTop(handle: int) -> bool:

return bool(ctypes.windll.user32.BringWindowToTop(ctypes.c_void_p(handle)))<EOL>

BringWindowToTop from Win32.
handle: int, the handle of a native window.
Return bool, True if succeed otherwise False.


def SwitchToThisWindow(handle: int) -> None:

ctypes.windll.user32.SwitchToThisWindow(ctypes.c_void_p(handle), <NUM_LIT:1>)<EOL>

SwitchToThisWindow from Win32.
handle: int, the handle of a native window.


def GetAncestor(handle: int, flag: int) -> int:

return ctypes.windll.user32.GetAncestor(ctypes.c_void_p(handle), flag)<EOL>

GetAncestor from Win32.
handle: int, the handle of a native window.
index: int, a value in class `GAFlag`.
Return int, a native window handle.


def IsTopLevelWindow(handle: int) -> bool:

return bool(ctypes.windll.user32.IsTopLevelWindow(ctypes.c_void_p(handle)))<EOL>

IsTopLevelWindow from Win32.
handle: int, the handle of a native window.
Return bool.
Only available on Windows 7 or Higher.


def GetWindowLong(handle: int, index: int) -> int:

return ctypes.windll.user32.GetWindowLongW(ctypes.c_void_p(handle), index)<EOL>

GetWindowLong from Win32.
handle: int, the handle of a native window.
index: int.


def SetWindowLong(handle: int, index: int, value: int) -> int:

return ctypes.windll.user32.SetWindowLongW(ctypes.c_void_p(handle), index, value)<EOL>

SetWindowLong from Win32.
handle: int, the handle of a native window.
index: int.
value: int.
Return int, the previous value before set.


return bool(ctypes.windll.user32.IsIconic(ctypes.c_void_p(handle)))<EOL>

IsIconic from Win32.
Determine whether a native window is minimized.
handle: int, the handle of a native window.
Return bool.


return bool(ctypes.windll.user32.IsZoomed(ctypes.c_void_p(handle)))<EOL>

IsZoomed from Win32.
Determine whether a native window is maximized.
handle: int, the handle of a native window.
Return bool.


def IsWindowVisible(handle: int) -> bool:

return bool(ctypes.windll.user32.IsWindowVisible(ctypes.c_void_p(handle)))<EOL>

IsWindowVisible from Win32.
handle: int, the handle of a native window.
Return bool.


def ShowWindow(handle: int, cmdShow: int) -> bool:

return ctypes.windll.user32.ShowWindow(ctypes.c_void_p(handle), cmdShow)<EOL>

ShowWindow from Win32.
handle: int, the handle of a native window.
cmdShow: int, a value in clas `SW`.
Return bool, True if succeed otherwise False.


def MoveWindow(handle: int, x: int, y: int, width: int, height: int, repaint: int = <NUM_LIT:1>) -> bool:

return bool(ctypes.windll.user32.MoveWindow(ctypes.c_void_p(handle), x, y, width, height, repaint))<EOL>

MoveWindow from Win32.
handle: int, the handle of a native window.
x: int.
y: int.
width: int.
height: int.
repaint: int, use 1 or 0.
Return bool, True if succeed otherwise False.


def SetWindowPos(handle: int, hWndInsertAfter: int, x: int, y: int, width: int, height: int, flags: int) -> bool:

return ctypes.windll.user32.SetWindowPos(ctypes.c_void_p(handle), ctypes.c_void_p(hWndInsertAfter), x, y, width, height, flags)<EOL>

SetWindowPos from Win32.
handle: int, the handle of a native window.
hWndInsertAfter: int, a value whose name starts with 'HWND' in class SWP.
x: int.
y: int.
width: int.
height: int.
flags: int, values whose name starts with 'SWP' in class `SWP`.
Return bool, True if succeed otherwise False.


def SetWindowTopmost(handle: int, isTopmost: bool) -> bool:

topValue = SWP.HWND_Topmost if isTopmost else SWP.HWND_NoTopmost<EOL>return bool(SetWindowPos(handle, topValue, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, SWP.SWP_NoSize | SWP.SWP_NoMove))<EOL>

handle: int, the handle of a native window.
isTopmost: bool
Return bool, True if succeed otherwise False.


arrayType = ctypes.c_wchar * MAX_PATH<EOL>values = arrayType()<EOL>ctypes.windll.user32.GetWindowTextW(ctypes.c_void_p(handle), values, MAX_PATH)<EOL>return values.value<EOL>

GetWindowText from Win32.
handle: int, the handle of a native window.
Return str.


def SetWindowText(handle: int, text: str) -> bool:

return bool(ctypes.windll.user32.SetWindowTextW(ctypes.c_void_p(handle), ctypes.c_wchar_p(text)))<EOL>

SetWindowText from Win32.
handle: int, the handle of a native window.
text: str.
Return bool, True if succeed otherwise False.


textLen = SendMessage(handle, <NUM_LIT>, <NUM_LIT:0>, <NUM_LIT:0>) + <NUM_LIT:1>  <EOL>arrayType = ctypes.c_wchar * textLen<EOL>values = arrayType()<EOL>SendMessage(handle, <NUM_LIT>, textLen, values)  <EOL>return values.value<EOL>

Get text of a native Win32 Edit.
handle: int, the handle of a native window.
Return str.


if IsNT6orHigher:<EOL><INDENT>arrayType = ctypes.c_wchar * MAX_PATH<EOL>values = arrayType()<EOL>ctypes.windll.kernel32.GetConsoleOriginalTitleW(values, MAX_PATH)<EOL>return values.value<EOL><DEDENT>else:<EOL><INDENT>raise RuntimeError('<STR_LIT>')<EOL><DEDENT>

GetConsoleOriginalTitle from Win32.
Return str.
Only available on Windows Vista or higher.


arrayType = ctypes.c_wchar * MAX_PATH<EOL>values = arrayType()<EOL>ctypes.windll.kernel32.GetConsoleTitleW(values, MAX_PATH)<EOL>return values.value<EOL>


return bool(ctypes.windll.kernel32.SetConsoleTitleW(ctypes.c_wchar_p(text)))<EOL>

SetConsoleTitle from Win32.
text: str.
Return bool, True if succeed otherwise False.


return ctypes.windll.user32.GetForegroundWindow()<EOL>

GetForegroundWindow from Win32.
Return int, the native handle of the foreground window.


isLocked = False<EOL>desk = ctypes.windll.user32.OpenDesktopW(ctypes.c_wchar_p('<STR_LIT>'), <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT>)  <EOL>if desk:<EOL><INDENT>isLocked = not ctypes.windll.user32.SwitchDesktop(desk)<EOL>ctypes.windll.user32.CloseDesktop(desk)<EOL><DEDENT>return isLocked<EOL>

Check if desktop is locked.
Return bool.
Desktop is locked if press Win+L, Ctrl+Alt+Del or in remote desktop mode.


def PlayWaveFile(filePath: str = r'<STR_LIT>', isAsync: bool = False, isLoop: bool = False) -> bool:

if filePath:<EOL><INDENT>SND_ASYNC = <NUM_LIT><EOL>SND_NODEFAULT = <NUM_LIT><EOL>SND_LOOP = <NUM_LIT><EOL>SND_FILENAME = <NUM_LIT><EOL>flags = SND_NODEFAULT | SND_FILENAME<EOL>if isAsync:<EOL><INDENT>flags |= SND_ASYNC<EOL><DEDENT>if isLoop:<EOL><INDENT>flags |= SND_LOOP<EOL>flags |= SND_ASYNC<EOL><DEDENT>return bool(ctypes.windll.winmm.PlaySoundW(ctypes.c_wchar_p(filePath), ctypes.c_void_p(<NUM_LIT:0>), flags))<EOL><DEDENT>else:<EOL><INDENT>return bool(ctypes.windll.winmm.PlaySoundW(ctypes.c_wchar_p(<NUM_LIT:0>), ctypes.c_void_p(<NUM_LIT:0>), <NUM_LIT:0>))<EOL><DEDENT>

Call PlaySound from Win32.
filePath: str, if emtpy, stop playing the current sound.
isAsync: bool, if True, the sound is played asynchronously and returns immediately.
isLoop: bool, if True, the sound plays repeatedly until PlayWaveFile(None) is called again, must also set isAsync to True.
Return bool, True if succeed otherwise False.


def IsProcess64Bit(processId: int) -> bool:

try:<EOL><INDENT>func = ctypes.windll.ntdll.ZwWow64ReadVirtualMemory64  <EOL><DEDENT>except Exception as ex:<EOL><INDENT>return False<EOL><DEDENT>try:<EOL><INDENT>IsWow64Process = ctypes.windll.kernel32.IsWow64Process<EOL>IsWow64Process.argtypes = (ctypes.c_void_p, ctypes.POINTER(ctypes.c_int))<EOL><DEDENT>except Exception as ex:<EOL><INDENT>return False<EOL><DEDENT>hProcess = ctypes.windll.kernel32.OpenProcess(<NUM_LIT>, <NUM_LIT:0>, processId)  <EOL>if hProcess:<EOL><INDENT>is64Bit = ctypes.c_int32()<EOL>if IsWow64Process(hProcess, ctypes.byref(is64Bit)):<EOL><INDENT>ctypes.windll.kernel32.CloseHandle(ctypes.c_void_p(hProcess))<EOL>return False if is64Bit.value else True<EOL><DEDENT>else:<EOL><INDENT>ctypes.windll.kernel32.CloseHandle(ctypes.c_void_p(hProcess))<EOL><DEDENT><DEDENT>

Return True if process is 64 bit.
Return False if process is 32 bit.
Return None if unknown, maybe caused by having no acess right to the process.


return bool(ctypes.windll.shell32.IsUserAnAdmin())<EOL>

IsUserAnAdmin from Win32.
Return bool.
Minimum supported OS: Windows XP, Windows Server 2003


def RunScriptAsAdmin(argv: list, workingDirectory: str = None, showFlag: int = SW.ShowNormal) -> bool:

args = '<STR_LIT:U+0020>'.join('<STR_LIT>'.format(arg) for arg in argv)<EOL>return ctypes.windll.shell32.ShellExecuteW(None, "<STR_LIT>", sys.executable, args, workingDirectory, showFlag) > <NUM_LIT:32><EOL>

Run a python script as administrator.
System will show a popup dialog askes you whether to elevate as administrator if UAC is enabled.
argv: list, a str list like sys.argv, argv[0] is the script file, argv[1:] are other arguments.
workingDirectory: str, the working directory for the script file.
showFlag: int, a value in class `SW`.
Return bool, True if succeed.


def SendKey(key: int, waitTime: float = OPERATION_WAIT_TIME) -> None:

keybd_event(key, <NUM_LIT:0>, KeyboardEventFlag.KeyDown | KeyboardEventFlag.ExtendedKey, <NUM_LIT:0>)<EOL>keybd_event(key, <NUM_LIT:0>, KeyboardEventFlag.KeyUp | KeyboardEventFlag.ExtendedKey, <NUM_LIT:0>)<EOL>time.sleep(waitTime)<EOL>

Simulate typing a key.
key: int, a value in class `Keys`.


def PressKey(key: int, waitTime: float = OPERATION_WAIT_TIME) -> None:

keybd_event(key, <NUM_LIT:0>, KeyboardEventFlag.KeyDown | KeyboardEventFlag.ExtendedKey, <NUM_LIT:0>)<EOL>time.sleep(waitTime)<EOL>

Simulate a key down for key.
key: int, a value in class `Keys`.
waitTime: float.


def ReleaseKey(key: int, waitTime: float = OPERATION_WAIT_TIME) -> None:

keybd_event(key, <NUM_LIT:0>, KeyboardEventFlag.KeyUp | KeyboardEventFlag.ExtendedKey, <NUM_LIT:0>)<EOL>time.sleep(waitTime)<EOL>

Simulate a key up for key.
key: int, a value in class `Keys`.
waitTime: float.


state = ctypes.windll.user32.GetAsyncKeyState(key)<EOL>return bool(state & <NUM_LIT>)<EOL>

key: int, a value in class `Keys`.
Return bool.


if isinstance(structure, MOUSEINPUT):<EOL><INDENT>return INPUT(InputType.Mouse, _INPUTUnion(mi=structure))<EOL><DEDENT>if isinstance(structure, KEYBDINPUT):<EOL><INDENT>return INPUT(InputType.Keyboard, _INPUTUnion(ki=structure))<EOL><DEDENT>if isinstance(structure, HARDWAREINPUT):<EOL><INDENT>return INPUT(InputType.Hardware, _INPUTUnion(hi=structure))<EOL><DEDENT>raise TypeError('<STR_LIT>')<EOL>

Create Win32 struct `INPUT` for `SendInput`.
Return `INPUT`.


def MouseInput(dx: int, dy: int, mouseData: int = <NUM_LIT:0>, dwFlags: int = MouseEventFlag.LeftDown, time_: int = <NUM_LIT:0>) -> INPUT:

return _CreateInput(MOUSEINPUT(dx, dy, mouseData, dwFlags, time_, None))<EOL>

Create Win32 struct `MOUSEINPUT` for `SendInput`.
Return `INPUT`.


def KeyboardInput(wVk: int, wScan: int, dwFlags: int = KeyboardEventFlag.KeyDown, time_: int = <NUM_LIT:0>) -> INPUT:

return _CreateInput(KEYBDINPUT(wVk, wScan, dwFlags, time_, None))<EOL>

Create Win32 struct `KEYBDINPUT` for `SendInput`.


def HardwareInput(uMsg: int, param: int = <NUM_LIT:0>) -> INPUT:

return _CreateInput(HARDWAREINPUT(uMsg, param & <NUM_LIT>, param >> <NUM_LIT:16> & <NUM_LIT>))<EOL>

Create Win32 struct `HARDWAREINPUT` for `SendInput`.


nInputs = len(inputs)<EOL>LPINPUT = INPUT * nInputs<EOL>pInputs = LPINPUT(*inputs)<EOL>cbSize = ctypes.c_int(ctypes.sizeof(INPUT))<EOL>return ctypes.windll.user32.SendInput(nInputs, pInputs, cbSize)<EOL>

SendInput from Win32.
input: `INPUT`.
Return int, the number of events that it successfully inserted into the keyboard or mouse input stream.
            If the function returns zero, the input was already blocked by another thread.


return SendInput(KeyboardInput(<NUM_LIT:0>, ord(char), KeyboardEventFlag.KeyUnicode | KeyboardEventFlag.KeyDown),<EOL>KeyboardInput(<NUM_LIT:0>, ord(char), KeyboardEventFlag.KeyUnicode | KeyboardEventFlag.KeyUp))<EOL>

Type a single unicode char.
char: str, len(char) must equal to 1.
Return int, the number of events that it successfully inserted into the keyboard or mouse input stream.
            If the function returns zero, the input was already blocked by another thread.


if key in _SCKeys:<EOL><INDENT>return _SCKeys[key]<EOL><DEDENT>scanCode = ctypes.windll.user32.MapVirtualKeyA(key, <NUM_LIT:0>)<EOL>if not scanCode:<EOL><INDENT>return <NUM_LIT:0><EOL><DEDENT>keyList = [Keys.VK_APPS, Keys.VK_CANCEL, Keys.VK_SNAPSHOT, Keys.VK_DIVIDE, Keys.VK_NUMLOCK]<EOL>if key in keyList:<EOL><INDENT>scanCode |= <NUM_LIT><EOL><DEDENT>return scanCode<EOL>

This function is only for internal use in SendKeys.
key: int, a value in class `Keys`.
Return int.


def SendKeys(text: str, interval: float = <NUM_LIT>, waitTime: float = OPERATION_WAIT_TIME, debug: bool = False) -> None:

holdKeys = ('<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>')<EOL>keys = []<EOL>printKeys = []<EOL>i = <NUM_LIT:0><EOL>insertIndex = <NUM_LIT:0><EOL>length = len(text)<EOL>hold = False<EOL>include = False<EOL>lastKeyValue = None<EOL>while True:<EOL><INDENT>if text[i] == '<STR_LIT:{>':<EOL><INDENT>rindex = text.find('<STR_LIT:}>', i)<EOL>if rindex == i + <NUM_LIT:1>:<EOL><INDENT>rindex = text.find('<STR_LIT:}>', i + <NUM_LIT:2>)<EOL><DEDENT>if rindex == -<NUM_LIT:1>:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>key = text[i + <NUM_LIT:1>:rindex]<EOL>key = [it for it in key.split('<STR_LIT:U+0020>') if it]<EOL>if not key:<EOL><INDENT>raise ValueError('<STR_LIT>'.format(text[i:rindex + <NUM_LIT:1>]))<EOL><DEDENT>if (len(key) == <NUM_LIT:2> and not key[<NUM_LIT:1>].isdigit()) or len(key) > <NUM_LIT:2>:<EOL><INDENT>raise ValueError('<STR_LIT>'.format(text[i:rindex + <NUM_LIT:1>]))<EOL><DEDENT>upperKey = key[<NUM_LIT:0>].upper()<EOL>count = <NUM_LIT:1><EOL>if len(key) > <NUM_LIT:1>:<EOL><INDENT>count = int(key[<NUM_LIT:1>])<EOL><DEDENT>for j in range(count):<EOL><INDENT>if hold:<EOL><INDENT>if upperKey in SpecialKeyNames:<EOL><INDENT>keyValue = SpecialKeyNames[upperKey]<EOL>if type(lastKeyValue) == type(keyValue) and lastKeyValue == keyValue:<EOL><INDENT>insertIndex += <NUM_LIT:1><EOL><DEDENT>printKeys.insert(insertIndex, (key[<NUM_LIT:0>], '<STR_LIT>'))<EOL>printKeys.insert(insertIndex + <NUM_LIT:1>, (key[<NUM_LIT:0>], '<STR_LIT>'))<EOL>keys.insert(insertIndex, (keyValue, KeyboardEventFlag.KeyDown | KeyboardEventFlag.ExtendedKey))<EOL>keys.insert(insertIndex + <NUM_LIT:1>, (keyValue, KeyboardEventFlag.KeyUp | KeyboardEventFlag.ExtendedKey))<EOL>lastKeyValue = keyValue<EOL><DEDENT>elif key[<NUM_LIT:0>] in CharacterCodes:<EOL><INDENT>keyValue = CharacterCodes[key[<NUM_LIT:0>]]<EOL>if type(lastKeyValue) == type(keyValue) and lastKeyValue == keyValue:<EOL><INDENT>insertIndex += <NUM_LIT:1><EOL><DEDENT>printKeys.insert(insertIndex, (key[<NUM_LIT:0>], '<STR_LIT>'))<EOL>printKeys.insert(insertIndex + <NUM_LIT:1>, (key[<NUM_LIT:0>], '<STR_LIT>'))<EOL>keys.insert(insertIndex, (keyValue, KeyboardEventFlag.KeyDown | KeyboardEventFlag.ExtendedKey))<EOL>keys.insert(insertIndex + <NUM_LIT:1>, (keyValue, KeyboardEventFlag.KeyUp | KeyboardEventFlag.ExtendedKey))<EOL>lastKeyValue = keyValue<EOL><DEDENT>else:<EOL><INDENT>printKeys.insert(insertIndex, (key[<NUM_LIT:0>], '<STR_LIT>'))<EOL>keys.insert(insertIndex, (key[<NUM_LIT:0>], '<STR_LIT>'))<EOL>lastKeyValue = key[<NUM_LIT:0>]<EOL><DEDENT>if include:<EOL><INDENT>insertIndex += <NUM_LIT:1><EOL><DEDENT>else:<EOL><INDENT>if upperKey in holdKeys:<EOL><INDENT>insertIndex += <NUM_LIT:1><EOL><DEDENT>else:<EOL><INDENT>hold = False<EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>if upperKey in SpecialKeyNames:<EOL><INDENT>keyValue = SpecialKeyNames[upperKey]<EOL>printKeys.append((key[<NUM_LIT:0>], '<STR_LIT>'))<EOL>printKeys.append((key[<NUM_LIT:0>], '<STR_LIT>'))<EOL>keys.append((keyValue, KeyboardEventFlag.KeyDown | KeyboardEventFlag.ExtendedKey))<EOL>keys.append((keyValue, KeyboardEventFlag.KeyUp | KeyboardEventFlag.ExtendedKey))<EOL>lastKeyValue = keyValue<EOL>if upperKey in holdKeys:<EOL><INDENT>hold = True<EOL>insertIndex = len(keys) - <NUM_LIT:1><EOL><DEDENT>else:<EOL><INDENT>hold = False<EOL><DEDENT><DEDENT>else:<EOL><INDENT>printKeys.append((key[<NUM_LIT:0>], '<STR_LIT>'))<EOL>keys.append((key[<NUM_LIT:0>], '<STR_LIT>'))<EOL>lastKeyValue = key[<NUM_LIT:0>]<EOL><DEDENT><DEDENT><DEDENT>i = rindex + <NUM_LIT:1><EOL><DEDENT>elif text[i] == '<STR_LIT:(>':<EOL><INDENT>if hold:<EOL><INDENT>include = True<EOL><DEDENT>else:<EOL><INDENT>printKeys.append((text[i], '<STR_LIT>'))<EOL>keys.append((text[i], '<STR_LIT>'))<EOL>lastKeyValue = text[i]<EOL><DEDENT>i += <NUM_LIT:1><EOL><DEDENT>elif text[i] == '<STR_LIT:)>':<EOL><INDENT>if hold:<EOL><INDENT>include = False<EOL>hold = False<EOL><DEDENT>else:<EOL><INDENT>printKeys.append((text[i], '<STR_LIT>'))<EOL>keys.append((text[i], '<STR_LIT>'))<EOL>lastKeyValue = text[i]<EOL><DEDENT>i += <NUM_LIT:1><EOL><DEDENT>else:<EOL><INDENT>if hold:<EOL><INDENT>if text[i] in CharacterCodes:<EOL><INDENT>keyValue = CharacterCodes[text[i]]<EOL>if include and type(lastKeyValue) == type(keyValue) and lastKeyValue == keyValue:<EOL><INDENT>insertIndex += <NUM_LIT:1><EOL><DEDENT>printKeys.insert(insertIndex, (text[i], '<STR_LIT>'))<EOL>printKeys.insert(insertIndex + <NUM_LIT:1>, (text[i], '<STR_LIT>'))<EOL>keys.insert(insertIndex, (keyValue, KeyboardEventFlag.KeyDown | KeyboardEventFlag.ExtendedKey))<EOL>keys.insert(insertIndex + <NUM_LIT:1>, (keyValue, KeyboardEventFlag.KeyUp | KeyboardEventFlag.ExtendedKey))<EOL>lastKeyValue = keyValue<EOL><DEDENT>else:<EOL><INDENT>printKeys.append((text[i], '<STR_LIT>'))<EOL>keys.append((text[i], '<STR_LIT>'))<EOL>lastKeyValue = text[i]<EOL><DEDENT>if include:<EOL><INDENT>insertIndex += <NUM_LIT:1><EOL><DEDENT>else:<EOL><INDENT>hold = False<EOL><DEDENT><DEDENT>else:<EOL><INDENT>printKeys.append((text[i], '<STR_LIT>'))<EOL>keys.append((text[i], '<STR_LIT>'))<EOL>lastKeyValue = text[i]<EOL><DEDENT>i += <NUM_LIT:1><EOL><DEDENT>if i >= length:<EOL><INDENT>break<EOL><DEDENT><DEDENT>hotkeyInterval = <NUM_LIT><EOL>for i, key in enumerate(keys):<EOL><INDENT>if key[<NUM_LIT:1>] == '<STR_LIT>':<EOL><INDENT>SendUnicodeChar(key[<NUM_LIT:0>])<EOL>time.sleep(interval)<EOL>if debug:<EOL><INDENT>Logger.ColorfullyWrite('<STR_LIT>'.format(printKeys[i], interval), writeToFile=False)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>scanCode = _VKtoSC(key[<NUM_LIT:0>])<EOL>keybd_event(key[<NUM_LIT:0>], scanCode, key[<NUM_LIT:1>], <NUM_LIT:0>)<EOL>if debug:<EOL><INDENT>Logger.Write(printKeys[i], ConsoleColor.DarkGreen, writeToFile=False)<EOL><DEDENT>if i + <NUM_LIT:1> == len(keys):<EOL><INDENT>time.sleep(interval)<EOL>if debug:<EOL><INDENT>Logger.Write('<STR_LIT>'.format(interval), writeToFile=False)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>if key[<NUM_LIT:1>] & KeyboardEventFlag.KeyUp:<EOL><INDENT>if keys[i + <NUM_LIT:1>][<NUM_LIT:1>] == '<STR_LIT>' or keys[i + <NUM_LIT:1>][<NUM_LIT:1>] & KeyboardEventFlag.KeyUp == <NUM_LIT:0>:<EOL><INDENT>time.sleep(interval)<EOL>if debug:<EOL><INDENT>Logger.Write('<STR_LIT>'.format(interval), writeToFile=False)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>time.sleep(hotkeyInterval)  <EOL>if debug:<EOL><INDENT>Logger.Write('<STR_LIT>'.format(hotkeyInterval), writeToFile=False)<EOL><DEDENT><DEDENT><DEDENT>else:  <EOL><INDENT>time.sleep(hotkeyInterval)<EOL>if debug:<EOL><INDENT>Logger.Write('<STR_LIT>'.format(hotkeyInterval), writeToFile=False)<EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>time.sleep(waitTime)<EOL>

Simulate typing keys on keyboard.
text: str, keys to type.
interval: float, seconds between keys.
waitTime: float.
debug: bool, if True, print the keys.
Examples:
{Ctrl}, {Delete} ... are special keys' name in SpecialKeyNames.
SendKeys('{Ctrl}a{Delete}{Ctrl}v{Ctrl}s{Ctrl}{Shift}s{Win}e{PageDown}') #press Ctrl+a, Delete, Ctrl+v, Ctrl+s, Ctrl+Shift+s, Win+e, PageDown
SendKeys('{Ctrl}(AB)({Shift}(123))') #press Ctrl+A+B, type (, press Shift+1+2+3, type ), if () follows a hold key, hold key won't release util )
SendKeys('{Ctrl}{a 3}') #press Ctrl+a at the same time, release Ctrl+a, then type a 2 times
SendKeys('{a 3}{B 5}') #type a 3 times, type B 5 times
SendKeys('{{}Hello{}}abc {a}{b}{c} test{} 3}{!}{a} (){(}{)}') #type: {Hello}abc abc test}}}!a ()()
SendKeys('0123456789{Enter}')
SendKeys('ABCDEFGHIJKLMNOPQRSTUVWXYZ{Enter}')
SendKeys('abcdefghijklmnopqrstuvwxyz{Enter}')
SendKeys('`~!@#$%^&*()-_=+{Enter}')
SendKeys('[]{{}{}}\\|;:\'\",<.>/?{Enter}')


Get pattern COM interface by pattern id.
patternId: int, a value in class `PatternId`.
Return comtypes._cominterface_meta.


def CreatePattern(patternId: int, pattern: ctypes.POINTER(comtypes.IUnknown)):

subPattern = pattern.QueryInterface(GetPatternIdInterface(patternId))<EOL>if subPattern:<EOL><INDENT>return PatternConstructors[patternId](pattern=subPattern)<EOL><DEDENT>

Create a concreate pattern by pattern id and pattern(POINTER(IUnknown)).


def SetGlobalSearchTimeout(seconds: float) -> None:

global TIME_OUT_SECOND<EOL>TIME_OUT_SECOND = seconds<EOL>

seconds: float.
To make this available, you need explicitly import uiautomation:
    from uiautomation import uiautomation as auto
    auto.SetGlobalSearchTimeout(10)


def WaitForExist(control: Control, timeout: float) -> bool:

return control.Exists(timeout, <NUM_LIT:1>)<EOL>

Check if control exists in timeout seconds.
control: `Control` or its subclass.
timeout: float.
Return bool.


def WaitForDisappear(control: Control, timeout: float) -> bool:

return control.Disappears(timeout, <NUM_LIT:1>)<EOL>

Check if control disappears in timeout seconds.
control: `Control` or its subclass.
timeout: float.
Return bool.


def WalkTree(top, getChildren: Callable = None, getFirstChild: Callable = None, getNextSibling: Callable = None, yieldCondition: Callable = None, includeTop: bool = False, maxDepth: int = <NUM_LIT>):

if maxDepth <= <NUM_LIT:0>:<EOL><INDENT>return<EOL><DEDENT>depth = <NUM_LIT:0><EOL>if getChildren:<EOL><INDENT>if includeTop:<EOL><INDENT>if not yieldCondition or yieldCondition(top, <NUM_LIT:0>):<EOL><INDENT>yield top, <NUM_LIT:0>, <NUM_LIT:0><EOL><DEDENT><DEDENT>children = getChildren(top)<EOL>childList = [children]<EOL>while depth >= <NUM_LIT:0>:   <EOL><INDENT>lastItems = childList[-<NUM_LIT:1>]<EOL>if lastItems:<EOL><INDENT>if not yieldCondition or yieldCondition(lastItems[<NUM_LIT:0>], depth + <NUM_LIT:1>):<EOL><INDENT>yield lastItems[<NUM_LIT:0>], depth + <NUM_LIT:1>, len(lastItems) - <NUM_LIT:1><EOL><DEDENT>if depth + <NUM_LIT:1> < maxDepth:<EOL><INDENT>children = getChildren(lastItems[<NUM_LIT:0>])<EOL>if children:<EOL><INDENT>depth += <NUM_LIT:1><EOL>childList.append(children)<EOL><DEDENT><DEDENT>del lastItems[<NUM_LIT:0>]<EOL><DEDENT>else:<EOL><INDENT>del childList[depth]<EOL>depth -= <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT>elif getFirstChild and getNextSibling:<EOL><INDENT>if includeTop:<EOL><INDENT>if not yieldCondition or yieldCondition(top, <NUM_LIT:0>):<EOL><INDENT>yield top, <NUM_LIT:0><EOL><DEDENT><DEDENT>child = getFirstChild(top)<EOL>childList = [child]<EOL>while depth >= <NUM_LIT:0>:  <EOL><INDENT>lastItem = childList[-<NUM_LIT:1>]<EOL>if lastItem:<EOL><INDENT>if not yieldCondition or yieldCondition(lastItem, depth + <NUM_LIT:1>):<EOL><INDENT>yield lastItem, depth + <NUM_LIT:1><EOL><DEDENT>child = getNextSibling(lastItem)<EOL>childList[depth] = child<EOL>if depth + <NUM_LIT:1> < maxDepth:<EOL><INDENT>child = getFirstChild(lastItem)<EOL>if child:<EOL><INDENT>depth += <NUM_LIT:1><EOL>childList.append(child)<EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>del childList[depth]<EOL>depth -= <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT>

Walk a tree not using recursive algorithm.
top: a tree node.
getChildren: function(treeNode) -> list.
getNextSibling: function(treeNode) -> treeNode.
getNextSibling: function(treeNode) -> treeNode.
yieldCondition: function(treeNode, depth) -> bool.
includeTop: bool, if True yield top first.
maxDepth: int, enum depth.

If getChildren is valid, ignore getFirstChild and getNextSibling,
    yield 3 items tuple: (treeNode, depth, remain children count in current depth).
If getChildren is not valid, using getFirstChild and getNextSibling,
    yield 2 items tuple: (treeNode, depth).
If yieldCondition is not None, only yield tree nodes that yieldCondition(treeNode, depth)->bool returns True.

For example:
def GetDirChildren(dir_):
    if os.path.isdir(dir_):
        return [os.path.join(dir_, it) for it in os.listdir(dir_)]
for it, depth, leftCount in WalkTree('D:\\', getChildren= GetDirChildren):
    print(it, depth, leftCount)


return Control.CreateControlFromElement(_AutomationClient.instance().IUIAutomation.GetRootElement())<EOL>

Get root control, the Desktop window.
Return `PaneControl`.


return Control.CreateControlFromElement(_AutomationClient.instance().IUIAutomation.GetFocusedElement())<EOL>


return ControlFromHandle(GetForegroundWindow())<EOL>


def GetConsoleWindow() -> WindowControl:

return ControlFromHandle(ctypes.windll.kernel32.GetConsoleWindow())<EOL>

Return `WindowControl`, a console window that runs python.


def ControlFromPoint(x: int, y: int) -> Control:

element = _AutomationClient.instance().IUIAutomation.ElementFromPoint(ctypes.wintypes.POINT(x, y))<EOL>return Control.CreateControlFromElement(element)<EOL>

Call IUIAutomation ElementFromPoint x,y. May return None if mouse is over cmd's title bar icon.
Return `Control` subclass or None.


def ControlFromPoint2(x: int, y: int) -> Control:

return Control.CreateControlFromElement(_AutomationClient.instance().IUIAutomation.ElementFromHandle(WindowFromPoint(x, y)))<EOL>

Get a native handle from point x,y and call IUIAutomation.ElementFromHandle.
Return `Control` subclass.


x, y = GetCursorPos()<EOL>return ControlFromPoint(x, y)<EOL>

Call ControlFromPoint with current cursor point.
Return `Control` subclass.


x, y = GetCursorPos()<EOL>return ControlFromPoint2(x, y)<EOL>

Call ControlFromPoint2 with current cursor point.
Return `Control` subclass.


def ControlFromHandle(handle: int) -> Control:

return Control.CreateControlFromElement(_AutomationClient.instance().IUIAutomation.ElementFromHandle(handle))<EOL>

Call IUIAutomation.ElementFromHandle with a native handle.
handle: int, a native window handle.
Return `Control` subclass.


def ControlsAreSame(control1: Control, control2: Control) -> bool:

return bool(_AutomationClient.instance().IUIAutomation.CompareElements(control1.Element, control2.Element))<EOL>

control1: `Control` or its subclass.
control2: `Control` or its subclass.
Return bool, True if control1 and control2 represent the same control otherwise False.


def WalkControl(control: Control, includeTop: bool = False, maxDepth: int = <NUM_LIT>):

if includeTop:<EOL><INDENT>yield control, <NUM_LIT:0><EOL><DEDENT>if maxDepth <= <NUM_LIT:0>:<EOL><INDENT>return<EOL><DEDENT>depth = <NUM_LIT:0><EOL>child = control.GetFirstChildControl()<EOL>controlList = [child]<EOL>while depth >= <NUM_LIT:0>:<EOL><INDENT>lastControl = controlList[-<NUM_LIT:1>]<EOL>if lastControl:<EOL><INDENT>yield lastControl, depth + <NUM_LIT:1><EOL>child = lastControl.GetNextSiblingControl()<EOL>controlList[depth] = child<EOL>if depth + <NUM_LIT:1> < maxDepth:<EOL><INDENT>child = lastControl.GetFirstChildControl()<EOL>if child:<EOL><INDENT>depth += <NUM_LIT:1><EOL>controlList.append(child)<EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>del controlList[depth]<EOL>depth -= <NUM_LIT:1><EOL><DEDENT><DEDENT>

control: `Control` or its subclass.
includeTop: bool, if True, yield (control, 0) first.
maxDepth: int, enum depth.
Yield 2 items tuple(control: Control, depth: int).


def LogControl(control: Control, depth: int = <NUM_LIT:0>, showAllName: bool = True) -> None:

def getKeyName(theDict, theValue):<EOL><INDENT>for key in theDict:<EOL><INDENT>if theValue == theDict[key]:<EOL><INDENT>return key<EOL><DEDENT><DEDENT><DEDENT>indent = '<STR_LIT:U+0020>' * depth * <NUM_LIT:4><EOL>Logger.Write('<STR_LIT>'.format(indent))<EOL>Logger.Write(control.ControlTypeName, ConsoleColor.DarkGreen)<EOL>Logger.Write('<STR_LIT>')<EOL>Logger.Write(control.ClassName, ConsoleColor.DarkGreen)<EOL>Logger.Write('<STR_LIT>')<EOL>Logger.Write(control.AutomationId, ConsoleColor.DarkGreen)<EOL>Logger.Write('<STR_LIT>')<EOL>Logger.Write(control.BoundingRectangle, ConsoleColor.DarkGreen)<EOL>Logger.Write('<STR_LIT>')<EOL>Logger.Write(control.Name, ConsoleColor.DarkGreen, printTruncateLen=<NUM_LIT:0> if showAllName else <NUM_LIT:30>)<EOL>Logger.Write('<STR_LIT>')<EOL>Logger.Write('<STR_LIT>'.format(control.NativeWindowHandle), ConsoleColor.DarkGreen)<EOL>Logger.Write('<STR_LIT>')<EOL>Logger.Write(depth, ConsoleColor.DarkGreen)<EOL>supportedPatterns = list(filter(lambda t: t[<NUM_LIT:0>], ((control.GetPattern(id_), name) for id_, name in PatternIdNames.items())))<EOL>for pt, name in supportedPatterns:<EOL><INDENT>if isinstance(pt, ValuePattern):<EOL><INDENT>Logger.Write('<STR_LIT>')<EOL>Logger.Write(pt.Value, ConsoleColor.DarkGreen, printTruncateLen=<NUM_LIT:0> if showAllName else <NUM_LIT:30>)<EOL><DEDENT>elif isinstance(pt, RangeValuePattern):<EOL><INDENT>Logger.Write('<STR_LIT>')<EOL>Logger.Write(pt.Value, ConsoleColor.DarkGreen)<EOL><DEDENT>elif isinstance(pt, TogglePattern):<EOL><INDENT>Logger.Write('<STR_LIT>')<EOL>Logger.Write('<STR_LIT>' + getKeyName(ToggleState.__dict__, pt.ToggleState), ConsoleColor.DarkGreen)<EOL><DEDENT>elif isinstance(pt, SelectionItemPattern):<EOL><INDENT>Logger.Write('<STR_LIT>')<EOL>Logger.Write(pt.IsSelected, ConsoleColor.DarkGreen)<EOL><DEDENT>elif isinstance(pt, ExpandCollapsePattern):<EOL><INDENT>Logger.Write('<STR_LIT>')<EOL>Logger.Write('<STR_LIT>' + getKeyName(ExpandCollapseState.__dict__, pt.ExpandCollapseState), ConsoleColor.DarkGreen)<EOL><DEDENT>elif isinstance(pt, ScrollPattern):<EOL><INDENT>Logger.Write('<STR_LIT>')<EOL>Logger.Write(pt.HorizontalScrollPercent, ConsoleColor.DarkGreen)<EOL>Logger.Write('<STR_LIT>')<EOL>Logger.Write(pt.VerticalScrollPercent, ConsoleColor.DarkGreen)<EOL><DEDENT>elif isinstance(pt, GridPattern):<EOL><INDENT>Logger.Write('<STR_LIT>')<EOL>Logger.Write(pt.RowCount, ConsoleColor.DarkGreen)<EOL>Logger.Write('<STR_LIT>')<EOL>Logger.Write(pt.ColumnCount, ConsoleColor.DarkGreen)<EOL><DEDENT>elif isinstance(pt, GridItemPattern):<EOL><INDENT>Logger.Write('<STR_LIT>')<EOL>Logger.Write(pt.Column, ConsoleColor.DarkGreen)<EOL>Logger.Write('<STR_LIT>')<EOL>Logger.Write(pt.Column, ConsoleColor.DarkGreen)<EOL><DEDENT>elif isinstance(pt, TextPattern):<EOL><INDENT>Logger.Write('<STR_LIT>')<EOL>Logger.Write(pt.DocumentRange.GetText(<NUM_LIT:30>), ConsoleColor.DarkGreen)<EOL><DEDENT><DEDENT>Logger.Write('<STR_LIT>')<EOL>for pt, name in supportedPatterns:<EOL><INDENT>Logger.Write('<STR_LIT:U+0020>' + name, ConsoleColor.DarkGreen)<EOL><DEDENT>Logger.Write('<STR_LIT:\n>')<EOL>

Print and log control's properties.
control: `Control` or its subclass.
depth: int, current depth.
showAllName: bool, if False, print the first 30 characters of control.Name.


def EnumAndLogControl(control: Control, maxDepth: int = <NUM_LIT>, showAllName: bool = True, startDepth: int = <NUM_LIT:0>) -> None:

for c, d in WalkControl(control, True, maxDepth):<EOL><INDENT>LogControl(c, d + startDepth, showAllName)<EOL><DEDENT>

Print and log control and its descendants' propertyies.
control: `Control` or its subclass.
maxDepth: int, enum depth.
showAllName: bool, if False, print the first 30 characters of control.Name.
startDepth: int, control's current depth.


def EnumAndLogControlAncestors(control: Control, showAllName: bool = True) -> None:

lists = []<EOL>while control:<EOL><INDENT>lists.insert(<NUM_LIT:0>, control)<EOL>control = control.GetParentControl()<EOL><DEDENT>for i, control in enumerate(lists):<EOL><INDENT>LogControl(control, i, showAllName)<EOL><DEDENT>

Print and log control and its ancestors' propertyies.
control: `Control` or its subclass.
showAllName: bool, if False, print the first 30 characters of control.Name.


def FindControl(control: Control, compare: Callable, maxDepth: int = <NUM_LIT>, findFromSelf: bool = False, foundIndex: int = <NUM_LIT:1>) -> Control:

foundCount = <NUM_LIT:0><EOL>if not control:<EOL><INDENT>control = GetRootControl()<EOL><DEDENT>traverseCount = <NUM_LIT:0><EOL>for child, depth in WalkControl(control, findFromSelf, maxDepth):<EOL><INDENT>traverseCount += <NUM_LIT:1><EOL>if compare(child, depth):<EOL><INDENT>foundCount += <NUM_LIT:1><EOL>if foundCount == foundIndex:<EOL><INDENT>child.traverseCount = traverseCount<EOL>return child<EOL><DEDENT><DEDENT><DEDENT>

control: `Control` or its subclass.
compare: compare function with parameters (control: Control, depth: int) which returns bool.
maxDepth: int, enum depth.
findFromSelf: bool, if False, do not compare self.
foundIndex: int, starts with 1, >= 1.
Return `Control` subclass or None if not find.


def ShowDesktop(waitTime: float = <NUM_LIT:1>) -> None:

SendKeys('<STR_LIT>')<EOL>time.sleep(waitTime)<EOL>


def InitializeUIAutomationInCurrentThread() -> None:

comtypes.CoInitializeEx()<EOL>

Initialize UIAutomation in a new thread.
If you want to use functionalities related to Controls and Patterns in a new thread.
You must call this function first in the new thread.
But you can't use use a Control or a Pattern created in a different thread.
So you can't create a Control or a Pattern in main thread and then pass it to a new thread and use it.


def UninitializeUIAutomationInCurrentThread() -> None:

comtypes.CoUninitialize()<EOL>

Uninitialize UIAutomation in a new thread after calling InitializeUIAutomationInCurrentThread.
You must call this function when the new thread exits if you have called InitializeUIAutomationInThisThread in the same thread.


def WaitHotKeyReleased(hotkey: tuple) -> None:

mod = {ModifierKey.Alt: Keys.VK_MENU,<EOL>ModifierKey.Control: Keys.VK_CONTROL,<EOL>ModifierKey.Shift: Keys.VK_SHIFT,<EOL>ModifierKey.Win: Keys.VK_LWIN<EOL>}<EOL>while True:<EOL><INDENT>time.sleep(<NUM_LIT>)<EOL>if IsKeyPressed(hotkey[<NUM_LIT:1>]):<EOL><INDENT>continue<EOL><DEDENT>for k, v in mod.items():<EOL><INDENT>if k & hotkey[<NUM_LIT:0>]:<EOL><INDENT>if IsKeyPressed(v):<EOL><INDENT>break<EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>break<EOL><DEDENT><DEDENT>

hotkey: tuple, two ints tuple(modifierKey, key)


def RunByHotKey(keyFunctions: dict, stopHotKey: tuple = None, exitHotKey: tuple = (ModifierKey.Control, Keys.VK_D), waitHotKeyReleased: bool = True) -> None:

from threading import Thread, Event, currentThread<EOL>import traceback<EOL>def getModName(theDict, theValue):<EOL><INDENT>name = '<STR_LIT>'<EOL>for key in theDict:<EOL><INDENT>if isinstance(theDict[key], int) and theValue & theDict[key]:<EOL><INDENT>if name:<EOL><INDENT>name += '<STR_LIT:|>'<EOL><DEDENT>name += key<EOL><DEDENT><DEDENT>return name<EOL><DEDENT>def getKeyName(theDict, theValue):<EOL><INDENT>for key in theDict:<EOL><INDENT>if theValue == theDict[key]:<EOL><INDENT>return key<EOL><DEDENT><DEDENT><DEDENT>def releaseAllKey():<EOL><INDENT>for key, value in Keys.__dict__.items():<EOL><INDENT>if isinstance(value, int) and key.startswith('<STR_LIT>'):<EOL><INDENT>if IsKeyPressed(value):<EOL><INDENT>ReleaseKey(value)<EOL><DEDENT><DEDENT><DEDENT><DEDENT>def threadFunc(function, stopEvent, hotkey, hotkeyName):<EOL><INDENT>if waitHotKeyReleased:<EOL><INDENT>WaitHotKeyReleased(hotkey)<EOL><DEDENT>try:<EOL><INDENT>function(stopEvent)<EOL><DEDENT>except Exception as ex:<EOL><INDENT>Logger.ColorfullyWrite('<STR_LIT>'.format(<EOL>ex.__class__.__name__, hotkeyName), writeToFile=False)<EOL>print(traceback.format_exc())<EOL><DEDENT>finally:<EOL><INDENT>releaseAllKey()  <EOL>Logger.ColorfullyWrite('<STR_LIT>'.format(<EOL>currentThread(), function.__name__, hotkeyName), ConsoleColor.DarkYellow, writeToFile=False)<EOL><DEDENT><DEDENT>stopHotKeyId = <NUM_LIT:1><EOL>exitHotKeyId = <NUM_LIT:2><EOL>hotKeyId = <NUM_LIT:3><EOL>registed = True<EOL>id2HotKey = {}<EOL>id2Function = {}<EOL>id2Thread = {}<EOL>id2Name = {}<EOL>for hotkey in keyFunctions:<EOL><INDENT>id2HotKey[hotKeyId] = hotkey<EOL>id2Function[hotKeyId] = keyFunctions[hotkey]<EOL>id2Thread[hotKeyId] = None<EOL>modName = getModName(ModifierKey.__dict__, hotkey[<NUM_LIT:0>])<EOL>keyName = getKeyName(Keys.__dict__, hotkey[<NUM_LIT:1>])<EOL>id2Name[hotKeyId] = str((modName, keyName))<EOL>if ctypes.windll.user32.RegisterHotKey(<NUM_LIT:0>, hotKeyId, hotkey[<NUM_LIT:0>], hotkey[<NUM_LIT:1>]):<EOL><INDENT>Logger.ColorfullyWrite('<STR_LIT>'.format((modName, keyName)), writeToFile=False)<EOL><DEDENT>else:<EOL><INDENT>registed = False<EOL>Logger.ColorfullyWrite('<STR_LIT>'.format((modName, keyName)), writeToFile=False)<EOL><DEDENT>hotKeyId += <NUM_LIT:1><EOL><DEDENT>if stopHotKey and len(stopHotKey) == <NUM_LIT:2>:<EOL><INDENT>modName = getModName(ModifierKey.__dict__, stopHotKey[<NUM_LIT:0>])<EOL>keyName = getKeyName(Keys.__dict__, stopHotKey[<NUM_LIT:1>])<EOL>if ctypes.windll.user32.RegisterHotKey(<NUM_LIT:0>, stopHotKeyId, stopHotKey[<NUM_LIT:0>], stopHotKey[<NUM_LIT:1>]):<EOL><INDENT>Logger.ColorfullyWrite('<STR_LIT>'.format((modName, keyName)), writeToFile=False)<EOL><DEDENT>else:<EOL><INDENT>registed = False<EOL>Logger.ColorfullyWrite('<STR_LIT>'.format((modName, keyName)), writeToFile=False)<EOL><DEDENT><DEDENT>if not registed:<EOL><INDENT>return<EOL><DEDENT>if exitHotKey and len(exitHotKey) == <NUM_LIT:2>:<EOL><INDENT>modName = getModName(ModifierKey.__dict__, exitHotKey[<NUM_LIT:0>])<EOL>keyName = getKeyName(Keys.__dict__, exitHotKey[<NUM_LIT:1>])<EOL>if ctypes.windll.user32.RegisterHotKey(<NUM_LIT:0>, exitHotKeyId, exitHotKey[<NUM_LIT:0>], exitHotKey[<NUM_LIT:1>]):<EOL><INDENT>Logger.ColorfullyWrite('<STR_LIT>'.format((modName, keyName)), writeToFile=False)<EOL><DEDENT>else:<EOL><INDENT>Logger.ColorfullyWrite('<STR_LIT>'.format((modName, keyName)), writeToFile=False)<EOL><DEDENT><DEDENT>funcThread = None<EOL>livingThreads = []<EOL>stopEvent = Event()<EOL>msg = ctypes.wintypes.MSG()<EOL>while ctypes.windll.user32.GetMessageW(ctypes.byref(msg), ctypes.c_void_p(<NUM_LIT:0>), <NUM_LIT:0>, <NUM_LIT:0>) != <NUM_LIT:0>:<EOL><INDENT>if msg.message == <NUM_LIT>: <EOL><INDENT>if msg.wParam in id2HotKey:<EOL><INDENT>if msg.lParam & <NUM_LIT> == id2HotKey[msg.wParam][<NUM_LIT:0>] and msg.lParam >> <NUM_LIT:16> & <NUM_LIT> == id2HotKey[msg.wParam][<NUM_LIT:1>]:<EOL><INDENT>Logger.ColorfullyWrite('<STR_LIT>'.format(id2Name[msg.wParam]), writeToFile=False)<EOL>if not id2Thread[msg.wParam]:<EOL><INDENT>stopEvent.clear()<EOL>funcThread = Thread(None, threadFunc, args=(id2Function[msg.wParam], stopEvent, id2HotKey[msg.wParam], id2Name[msg.wParam]))<EOL>funcThread.start()<EOL>id2Thread[msg.wParam] = funcThread<EOL><DEDENT>else:<EOL><INDENT>if id2Thread[msg.wParam].is_alive():<EOL><INDENT>Logger.WriteLine('<STR_LIT>'.format(id2Thread[msg.wParam], id2Name[msg.wParam]), ConsoleColor.Yellow, writeToFile=False)<EOL><DEDENT>else:<EOL><INDENT>stopEvent.clear()<EOL>funcThread = Thread(None, threadFunc, args=(id2Function[msg.wParam], stopEvent, id2HotKey[msg.wParam], id2Name[msg.wParam]))<EOL>funcThread.start()<EOL>id2Thread[msg.wParam] = funcThread<EOL><DEDENT><DEDENT><DEDENT><DEDENT>elif stopHotKeyId == msg.wParam:<EOL><INDENT>if msg.lParam & <NUM_LIT> == stopHotKey[<NUM_LIT:0>] and msg.lParam >> <NUM_LIT:16> & <NUM_LIT> == stopHotKey[<NUM_LIT:1>]:<EOL><INDENT>Logger.Write('<STR_LIT>', ConsoleColor.DarkYellow, writeToFile=False)<EOL>stopEvent.set()<EOL>for id_ in id2Thread:<EOL><INDENT>if id2Thread[id_]:<EOL><INDENT>if id2Thread[id_].is_alive():<EOL><INDENT>livingThreads.append((id2Thread[id_], id2Name[id_]))<EOL><DEDENT>id2Thread[id_] = None<EOL><DEDENT><DEDENT><DEDENT><DEDENT>elif exitHotKeyId == msg.wParam:<EOL><INDENT>if msg.lParam & <NUM_LIT> == exitHotKey[<NUM_LIT:0>] and msg.lParam >> <NUM_LIT:16> & <NUM_LIT> == exitHotKey[<NUM_LIT:1>]:<EOL><INDENT>Logger.Write('<STR_LIT>', ConsoleColor.DarkYellow, writeToFile=False)<EOL>stopEvent.set()<EOL>for id_ in id2Thread:<EOL><INDENT>if id2Thread[id_]:<EOL><INDENT>if id2Thread[id_].is_alive():<EOL><INDENT>livingThreads.append((id2Thread[id_], id2Name[id_]))<EOL><DEDENT>id2Thread[id_] = None<EOL><DEDENT><DEDENT>break<EOL><DEDENT><DEDENT><DEDENT><DEDENT>for thread, hotkeyName in livingThreads:<EOL><INDENT>if thread.is_alive():<EOL><INDENT>Logger.Write('<STR_LIT>'.format(thread, hotkeyName), ConsoleColor.DarkYellow, writeToFile=False)<EOL>thread.join(<NUM_LIT:2>)<EOL><DEDENT><DEDENT>os._exit(<NUM_LIT:0>)<EOL>

Bind functions with hotkeys, the function will be run or stopped in another thread when the hotkey is pressed.
keyFunctions: hotkey function dict, like {(uiautomation.ModifierKey.Control, uiautomation.Keys.VK_1) : func}
stopHotKey: hotkey tuple
exitHotKey: hotkey tuple
waitHotKeyReleased: bool, if True, hotkey function will be triggered after the hotkey is released

def main(stopEvent):
    while True:
        if stopEvent.is_set(): # must check stopEvent.is_set() if you want to stop when stop hotkey is pressed
            break
        print(n)
        n += 1
        stopEvent.wait(1)
    print('main exit')

uiautomation.RunByHotKey({(uiautomation.ModifierKey.Control, uiautomation.Keys.VK_1) : main}
                    , (uiautomation.ModifierKey.Control | uiautomation.ModifierKey.Shift, uiautomation.Keys.VK_2))


@classmethod<EOL><INDENT>def instance(cls) -> '<STR_LIT>':<DEDENT>

if cls._instance is None:<EOL><INDENT>cls._instance = cls()<EOL><DEDENT>return cls._instance<EOL>

Singleton instance (this prevents com creation on import).


@staticmethod<EOL><INDENT>def Write(log: Any, consoleColor: int = ConsoleColor.Default, writeToFile: bool = True, printToStdout: bool = True, logFile: str = None, printTruncateLen: int = <NUM_LIT:0>) -> None:<DEDENT>

if not isinstance(log, str):<EOL><INDENT>log = str(log)<EOL><DEDENT>if printToStdout and sys.stdout:<EOL><INDENT>isValidColor = (consoleColor >= ConsoleColor.Black and consoleColor <= ConsoleColor.White)<EOL>if isValidColor:<EOL><INDENT>SetConsoleColor(consoleColor)<EOL><DEDENT>try:<EOL><INDENT>if printTruncateLen > <NUM_LIT:0> and len(log) > printTruncateLen:<EOL><INDENT>sys.stdout.write(log[:printTruncateLen] + '<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>sys.stdout.write(log)<EOL><DEDENT><DEDENT>except Exception as ex:<EOL><INDENT>SetConsoleColor(ConsoleColor.Red)<EOL>isValidColor = True<EOL>sys.stdout.write(ex.__class__.__name__ + '<STR_LIT>')<EOL>if log.endswith('<STR_LIT:\n>'):<EOL><INDENT>sys.stdout.write('<STR_LIT:\n>')<EOL><DEDENT><DEDENT>if isValidColor:<EOL><INDENT>ResetConsoleColor()<EOL><DEDENT>sys.stdout.flush()<EOL><DEDENT>if not writeToFile:<EOL><INDENT>return<EOL><DEDENT>fileName = logFile if logFile else Logger.FileName<EOL>try:<EOL><INDENT>fout = open(fileName, '<STR_LIT>', encoding='<STR_LIT:utf-8>')<EOL>fout.write(log)<EOL><DEDENT>except Exception as ex:<EOL><INDENT>if sys.stdout:<EOL><INDENT>sys.stdout.write(ex.__class__.__name__ + '<STR_LIT>')<EOL><DEDENT><DEDENT>finally:<EOL><INDENT>if fout:<EOL><INDENT>fout.close()<EOL><DEDENT><DEDENT>

log: any type.
consoleColor: int, a value in class `ConsoleColor`, such as `ConsoleColor.DarkGreen`.
writeToFile: bool.
printToStdout: bool.
logFile: str, log file path.
printTruncateLen: int, if <= 0, log is not truncated when print.


@staticmethod<EOL><INDENT>def WriteLine(log: Any, consoleColor: int = -<NUM_LIT:1>, writeToFile: bool = True, printToStdout: bool = True, logFile: str = None) -> None:<DEDENT>

Logger.Write('<STR_LIT>'.format(log), consoleColor, writeToFile, printToStdout, logFile)<EOL>

log: any type.
consoleColor: int, a value in class `ConsoleColor`, such as `ConsoleColor.DarkGreen`.
writeToFile: bool.
printToStdout: bool.
logFile: str, log file path.


@staticmethod<EOL><INDENT>def ColorfullyWrite(log: str, consoleColor: int = -<NUM_LIT:1>, writeToFile: bool = True, printToStdout: bool = True, logFile: str = None) -> None:<DEDENT>

text = []<EOL>start = <NUM_LIT:0><EOL>while True:<EOL><INDENT>index1 = log.find('<STR_LIT>', start)<EOL>if index1 >= <NUM_LIT:0>:<EOL><INDENT>if index1 > start:<EOL><INDENT>text.append((log[start:index1], consoleColor))<EOL><DEDENT>index2 = log.find('<STR_LIT:>>', index1)<EOL>colorName = log[index1+<NUM_LIT:7>:index2]<EOL>index3 = log.find('<STR_LIT>', index2 + <NUM_LIT:1>)<EOL>text.append((log[index2 + <NUM_LIT:1>:index3], Logger.ColorNames[colorName]))<EOL>start = index3 + <NUM_LIT:8><EOL><DEDENT>else:<EOL><INDENT>if start < len(log):<EOL><INDENT>text.append((log[start:], consoleColor))<EOL><DEDENT>break<EOL><DEDENT><DEDENT>for t, c in text:<EOL><INDENT>Logger.Write(t, c, writeToFile, printToStdout, logFile)<EOL><DEDENT>

log: str.
consoleColor: int, a value in class `ConsoleColor`, such as `ConsoleColor.DarkGreen`.
writeToFile: bool.
printToStdout: bool.
logFile: str, log file path.
ColorfullyWrite('Hello <Color=Green>Green</Color> !!!'), color name must be in Logger.ColorNames.


@staticmethod<EOL><INDENT>def ColorfullyWriteLine(log: str, consoleColor: int = -<NUM_LIT:1>, writeToFile: bool = True, printToStdout: bool = True, logFile: str = None) -> None:<DEDENT>

Logger.ColorfullyWrite(log + '<STR_LIT:\n>', consoleColor, writeToFile, printToStdout, logFile)<EOL>

log: str.
consoleColor: int, a value in class `ConsoleColor`, such as `ConsoleColor.DarkGreen`.
writeToFile: bool.
printToStdout: bool.
logFile: str, log file path.

ColorfullyWriteLine('Hello <Color=Green>Green</Color> !!!'), color name must be in Logger.ColorNames.


@staticmethod<EOL><INDENT>def Log(log: Any = '<STR_LIT>', consoleColor: int = -<NUM_LIT:1>, writeToFile: bool = True, printToStdout: bool = True, logFile: str = None) -> None:<DEDENT>

t = datetime.datetime.now()<EOL>frame = sys._getframe(<NUM_LIT:1>)<EOL>log = '<STR_LIT>'.format(t.year, t.month, t.day,<EOL>t.hour, t.minute, t.second, t.microsecond // <NUM_LIT:1000>, frame.f_code.co_name, frame.f_lineno, log)<EOL>Logger.Write(log, consoleColor, writeToFile, printToStdout, logFile)<EOL>


@staticmethod<EOL><INDENT>def ColorfullyLog(log: str = '<STR_LIT>', consoleColor: int = -<NUM_LIT:1>, writeToFile: bool = True, printToStdout: bool = True, logFile: str = None) -> None:<DEDENT>

t = datetime.datetime.now()<EOL>frame = sys._getframe(<NUM_LIT:1>)<EOL>log = '<STR_LIT>'.format(t.year, t.month, t.day,<EOL>t.hour, t.minute, t.second, t.microsecond // <NUM_LIT:1000>, frame.f_code.co_name, frame.f_lineno, log)<EOL>Logger.ColorfullyWrite(log, consoleColor, writeToFile, printToStdout, logFile)<EOL>

log: any type.
consoleColor: int, a value in class ConsoleColor, such as ConsoleColor.DarkGreen.
writeToFile: bool.
printToStdout: bool.
logFile: str, log file path.

ColorfullyLog('Hello <Color=Green>Green</Color> !!!'), color name must be in Logger.ColorNames


@staticmethod<EOL><INDENT>def DeleteLog() -> None:<DEDENT>

if os.path.exists(Logger.FileName):<EOL><INDENT>os.remove(Logger.FileName)<EOL><DEDENT>


def __init__(self, width: int = <NUM_LIT:0>, height: int = <NUM_LIT:0>):

self._width = width<EOL>self._height = height<EOL>self._bitmap = <NUM_LIT:0><EOL>if width > <NUM_LIT:0> and height > <NUM_LIT:0>:<EOL><INDENT>self._bitmap = _DllClient.instance().dll.BitmapCreate(width, height)<EOL><DEDENT>

Create a black bimap of size(width, height).


@property<EOL><INDENT>def Width(self) -> int:<DEDENT>

return self._width<EOL>


@property<EOL><INDENT>def Height(self) -> int:<DEDENT>

return self._height<EOL>


def FromHandle(self, hwnd: int, left: int = <NUM_LIT:0>, top: int = <NUM_LIT:0>, right: int = <NUM_LIT:0>, bottom: int = <NUM_LIT:0>) -> bool:

self.Release()<EOL>root = GetRootControl()<EOL>rect = ctypes.wintypes.RECT()<EOL>ctypes.windll.user32.GetWindowRect(hwnd, ctypes.byref(rect))<EOL>left, top, right, bottom = left + rect.left, top + rect.top, right + rect.left, bottom + rect.top<EOL>self._bitmap = _DllClient.instance().dll.BitmapFromWindow(root.NativeWindowHandle, left, top, right, bottom)<EOL>self._getsize()<EOL>return self._bitmap > <NUM_LIT:0><EOL>

Capture a native window to Bitmap by its handle.
hwnd: int, the handle of a native window.
left: int.
top: int.
right: int.
bottom: int.
left, top, right and bottom are control's internal postion(from 0,0).
Return bool, True if succeed otherwise False.


def FromControl(self, control: '<STR_LIT>', x: int = <NUM_LIT:0>, y: int = <NUM_LIT:0>, width: int = <NUM_LIT:0>, height: int = <NUM_LIT:0>) -> bool:

rect = control.BoundingRectangle<EOL>while rect.width() == <NUM_LIT:0> or rect.height() == <NUM_LIT:0>:<EOL><INDENT>control = control.GetParentControl()<EOL>if not control:<EOL><INDENT>return False<EOL><DEDENT>rect = control.BoundingRectangle<EOL><DEDENT>if width <= <NUM_LIT:0>:<EOL><INDENT>width = rect.width() + width<EOL><DEDENT>if height <= <NUM_LIT:0>:<EOL><INDENT>height = rect.height() + height<EOL><DEDENT>handle = control.NativeWindowHandle<EOL>if handle:<EOL><INDENT>left = x<EOL>top = y<EOL>right = left + width<EOL>bottom = top + height<EOL><DEDENT>else:<EOL><INDENT>while True:<EOL><INDENT>control = control.GetParentControl()<EOL>handle = control.NativeWindowHandle<EOL>if handle:<EOL><INDENT>pRect = control.BoundingRectangle<EOL>left = rect.left - pRect.left + x<EOL>top = rect.top - pRect.top + y<EOL>right = left + width<EOL>bottom = top + height<EOL>break<EOL><DEDENT><DEDENT><DEDENT>return self.FromHandle(handle, left, top, right, bottom)<EOL>

Capture a control to Bitmap.
control: `Control` or its subclass.
x: int.
y: int.
width: int.
height: int.
x, y: the point in control's internal position(from 0,0)
width, height: image's width and height from x, y, use 0 for entire area,
If width(or height) < 0, image size will be control's width(or height) - width(or height).
Return bool, True if succeed otherwise False.


def FromFile(self, filePath: str) -> bool:

self.Release()<EOL>self._bitmap = _DllClient.instance().dll.BitmapFromFile(ctypes.c_wchar_p(filePath))<EOL>self._getsize()<EOL>return self._bitmap > <NUM_LIT:0><EOL>

Load image from a file.
filePath: str.
Return bool, True if succeed otherwise False.


def ToFile(self, savePath: str) -> bool:

name, ext = os.path.splitext(savePath)<EOL>extMap = {'<STR_LIT>': '<STR_LIT>'<EOL>, '<STR_LIT>': '<STR_LIT>'<EOL>, '<STR_LIT>': '<STR_LIT>'<EOL>, '<STR_LIT>': '<STR_LIT>'<EOL>, '<STR_LIT>': '<STR_LIT>'<EOL>, '<STR_LIT>': '<STR_LIT>'<EOL>, '<STR_LIT>': '<STR_LIT>'<EOL>}<EOL>gdiplusImageFormat = extMap.get(ext.lower(), '<STR_LIT>')<EOL>return bool(_DllClient.instance().dll.BitmapToFile(self._bitmap, ctypes.c_wchar_p(savePath), ctypes.c_wchar_p(gdiplusImageFormat)))<EOL>

Save to a file.
savePath: str, should end with .bmp, .jpg, .jpeg, .png, .gif, .tif, .tiff.
Return bool, True if succeed otherwise False.


def GetPixelColor(self, x: int, y: int) -> int:

return _DllClient.instance().dll.BitmapGetPixel(self._bitmap, x, y)<EOL>

Get color value of a pixel.
x: int.
y: int.
Return int, argb color.
b = argb & 0x0000FF
g = (argb & 0x00FF00) >> 8
r = (argb & 0xFF0000) >> 16
a = (argb & 0xFF0000) >> 24


def SetPixelColor(self, x: int, y: int, argb: int) -> bool:

return _DllClient.instance().dll.BitmapSetPixel(self._bitmap, x, y, argb)<EOL>

Set color value of a pixel.
x: int.
y: int.
argb: int, color value.
Return bool, True if succeed otherwise False.


def GetPixelColorsHorizontally(self, x: int, y: int, count: int) -> ctypes.Array:

arrayType = ctypes.c_uint32 * count<EOL>values = arrayType()<EOL>_DllClient.instance().dll.BitmapGetPixelsHorizontally(ctypes.c_size_t(self._bitmap), x, y, values, count)<EOL>return values<EOL>

x: int.
y: int.
count: int.
Return `ctypes.Array`, an iterable array of int values in argb form point x,y horizontally.


def SetPixelColorsHorizontally(self, x: int, y: int, colors: Iterable) -> bool:

count = len(colors)<EOL>arrayType = ctypes.c_uint32 * count<EOL>values = arrayType(*colors)<EOL>return _DllClient.instance().dll.BitmapSetPixelsHorizontally(ctypes.c_size_t(self._bitmap), x, y, values, count)<EOL>

Set pixel colors form x,y horizontally.
x: int.
y: int.
colors: Iterable, an iterable list of int color values in argb.
Return bool, True if succeed otherwise False.


def GetPixelColorsVertically(self, x: int, y: int, count: int) -> ctypes.Array:

arrayType = ctypes.c_uint32 * count<EOL>values = arrayType()<EOL>_DllClient.instance().dll.BitmapGetPixelsVertically(ctypes.c_size_t(self._bitmap), x, y, values, count)<EOL>return values<EOL>

x: int.
y: int.
count: int.
Return `ctypes.Array`, an iterable array of int values in argb form point x,y vertically.


def SetPixelColorsVertically(self, x: int, y: int, colors: Iterable) -> bool:

count = len(colors)<EOL>arrayType = ctypes.c_uint32 * count<EOL>values = arrayType(*colors)<EOL>return _DllClient.instance().dll.BitmapSetPixelsVertically(ctypes.c_size_t(self._bitmap), x, y, values, count)<EOL>

Set pixel colors form x,y vertically.
x: int.
y: int.
colors: Iterable, an iterable list of int color values in argb.
Return bool, True if succeed otherwise False.


def GetPixelColorsOfRow(self, y: int) -> ctypes.Array:

return self.GetPixelColorsOfRect(<NUM_LIT:0>, y, self.Width, <NUM_LIT:1>)<EOL>

y: int, row index.
Return `ctypes.Array`, an iterable array of int values in argb of y row.


def GetPixelColorsOfColumn(self, x: int) -> ctypes.Array:

return self.GetPixelColorsOfRect(x, <NUM_LIT:0>, <NUM_LIT:1>, self.Height)<EOL>

x: int, column index.
Return `ctypes.Array`, an iterable array of int values in argb of x column.


def GetPixelColorsOfRect(self, x: int, y: int, width: int, height: int) -> ctypes.Array:

arrayType = ctypes.c_uint32 * (width * height)<EOL>values = arrayType()<EOL>_DllClient.instance().dll.BitmapGetPixelsOfRect(ctypes.c_size_t(self._bitmap), x, y, width, height, values)<EOL>return values<EOL>

x: int.
y: int.
width: int.
height: int.
Return `ctypes.Array`, an iterable array of int values in argb of the input rect.


def SetPixelColorsOfRect(self, x: int, y: int, width: int, height: int, colors: Iterable) -> bool:

arrayType = ctypes.c_uint32 * (width * height)<EOL>values = arrayType(*colors)<EOL>return bool(_DllClient.instance().dll.BitmapSetPixelsOfRect(ctypes.c_size_t(self._bitmap), x, y, width, height, values))<EOL>

x: int.
y: int.
width: int.
height: int.
colors: Iterable, an iterable list of int values, it's length must equal to width*height.
Return `ctypes.Array`, an iterable array of int values in argb of the input rect.


def GetPixelColorsOfRects(self, rects: list) -> list:

rects2 = [(x, y, x + width, y + height) for x, y, width, height in rects]<EOL>left, top, right, bottom = zip(*rects2)<EOL>left, top, right, bottom = min(left), min(top), max(right), max(bottom)<EOL>width, height = right - left, bottom - top<EOL>allColors = self.GetPixelColorsOfRect(left, top, width, height)<EOL>colorsOfRects = []<EOL>for x, y, w, h in rects:<EOL><INDENT>x -= left<EOL>y -= top<EOL>colors = []<EOL>for row in range(h):<EOL><INDENT>colors.extend(allColors[(y + row) * width + x:(y + row) * width + x + w])<EOL><DEDENT>colorsOfRects.append(colors)<EOL><DEDENT>return colorsOfRects<EOL>

rects: a list of rects, such as [(0,0,10,10), (10,10,20,20),(x,y,width,height)].
Return list, a list whose elements are ctypes.Array which is an iterable array of int values in argb.


def GetAllPixelColors(self) -> ctypes.Array:

return self.GetPixelColorsOfRect(<NUM_LIT:0>, <NUM_LIT:0>, self.Width, self.Height)<EOL>

Return `ctypes.Array`, an iterable array of int values in argb.


def GetSubBitmap(self, x: int, y: int, width: int, height: int) -> '<STR_LIT>':

colors = self.GetPixelColorsOfRect(x, y, width, height)<EOL>bitmap = Bitmap(width, height)<EOL>bitmap.SetPixelColorsOfRect(<NUM_LIT:0>, <NUM_LIT:0>, width, height, colors)<EOL>return bitmap<EOL>

x: int.
y: int.
width: int.
height: int.
Return `Bitmap`, a sub bitmap of the input rect.


self.pattern = pattern<EOL>


@property<EOL><INDENT>def AnnotationTypeId(self) -> int:<DEDENT>

return self.pattern.CurrentAnnotationTypeId<EOL>

Property AnnotationTypeId.
Call IUIAutomationAnnotationPattern::get_CurrentAnnotationTypeId.
Return int, a value in class `AnnotationType`.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationannotationpattern-get_currentannotationtypeid


@property<EOL><INDENT>def AnnotationTypeName(self) -> str:<DEDENT>

return self.pattern.CurrentAnnotationTypeName<EOL>


@property<EOL><INDENT>def Author(self) -> str:<DEDENT>

return self.pattern.CurrentAuthor<EOL>


@property<EOL><INDENT>def DateTime(self) -> str:<DEDENT>

return self.pattern.CurrentDateTime<EOL>


@property<EOL><INDENT>def Target(self) -> '<STR_LIT>':<DEDENT>

ele = self.pattern.CurrentTarget<EOL>return Control.CreateControlFromElement(ele)<EOL>

Property Target.
Call IUIAutomationAnnotationPattern::get_CurrentTarget.
Return `Control` subclass, the element that is being annotated.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationannotationpattern-get_currenttarget


def Navigate(self, direction: int) -> '<STR_LIT>':

ele = self.pattern.Navigate(direction)<EOL>return Control.CreateControlFromElement(ele)<EOL>

Call IUIAutomationCustomNavigationPattern::Navigate.
Get the next control in the specified direction within the logical UI tree.
direction: int, a value in class `NavigateDirection`.
Return `Control` subclass or None.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationcustomnavigationpattern-navigate


@property<EOL><INDENT>def DockPosition(self) -> int:<DEDENT>

return self.pattern.CurrentDockPosition<EOL>

Property DockPosition.
Call IUIAutomationDockPattern::get_CurrentDockPosition.
Return int, a value in class `DockPosition`.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationdockpattern-get_currentdockposition


def SetDockPosition(self, dockPosition: int, waitTime: float = OPERATION_WAIT_TIME) -> int:

ret = self.pattern.SetDockPosition(dockPosition)<EOL>time.sleep(waitTime)<EOL>return ret<EOL>

Call IUIAutomationDockPattern::SetDockPosition.
dockPosition: int, a value in class `DockPosition`.
waitTime: float.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationdockpattern-setdockposition


@property<EOL><INDENT>def DropEffect(self) -> str:<DEDENT>

return self.pattern.CurrentDropEffect<EOL>

Property DropEffect.
Call IUIAutomationDragPattern::get_CurrentDropEffect.
Return str, a localized string that indicates what happens
            when the user drops this element as part of a drag-drop operation.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationdragpattern-get_currentdropeffect


@property<EOL><INDENT>def DropEffects(self) -> list:<DEDENT>

return self.pattern.CurrentDropEffects<EOL>

Property DropEffects.
Call IUIAutomationDragPattern::get_CurrentDropEffects, todo SAFEARRAY.
Return list, a list of localized strings that enumerate the full set of effects
             that can happen when this element as part of a drag-and-drop operation.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationdragpattern-get_currentdropeffects


@property<EOL><INDENT>def IsGrabbed(self) -> bool:<DEDENT>

return bool(self.pattern.CurrentIsGrabbed)<EOL>

Property IsGrabbed.
Call IUIAutomationDragPattern::get_CurrentIsGrabbed.
Return bool, indicates whether the user has grabbed this element as part of a drag-and-drop operation.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationdragpattern-get_currentisgrabbed


eleArray = self.pattern.GetCurrentGrabbedItems()<EOL>if eleArray:<EOL><INDENT>controls = []<EOL>for i in range(eleArray.Length):<EOL><INDENT>ele = eleArray.GetElement(i)<EOL>con = Control.CreateControlFromElement(element=ele)<EOL>if con:<EOL><INDENT>controls.append(con)<EOL><DEDENT><DEDENT>return controls<EOL><DEDENT>return []<EOL>

Call IUIAutomationDragPattern::GetCurrentGrabbedItems.
Return list, a list of `Control` subclasses that represent the full set of items
             that the user is dragging as part of a drag operation.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationdragpattern-getcurrentgrabbeditems


@property<EOL><INDENT>def DropTargetEffect(self) -> str:<DEDENT>

return self.pattern.CurrentDropTargetEffect<EOL>

Property DropTargetEffect.
Call IUIAutomationDropTargetPattern::get_CurrentDropTargetEffect.
Return str, a localized string that describes what happens
            when the user drops the grabbed element on this drop target.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationdragpattern-get_currentdroptargeteffect


@property<EOL><INDENT>def DropTargetEffects(self) -> list:<DEDENT>

return self.pattern.CurrentDropTargetEffects<EOL>

Property DropTargetEffects.
Call IUIAutomationDropTargetPattern::get_CurrentDropTargetEffects, todo SAFEARRAY.
Return list, a list of localized strings that enumerate the full set of effects
             that can happen when the user drops a grabbed element on this drop target
             as part of a drag-and-drop operation.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationdragpattern-get_currentdroptargeteffects


@property<EOL><INDENT>def ExpandCollapseState(self) -> int:<DEDENT>

return self.pattern.CurrentExpandCollapseState<EOL>

Property ExpandCollapseState.
Call IUIAutomationExpandCollapsePattern::get_CurrentExpandCollapseState.
Return int, a value in class ExpandCollapseState.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationexpandcollapsepattern-get_currentexpandcollapsestate


def Collapse(self, waitTime: float = OPERATION_WAIT_TIME) -> bool:

ret = self.pattern.Collapse() == S_OK<EOL>time.sleep(waitTime)<EOL>return ret<EOL>

Call IUIAutomationExpandCollapsePattern::Collapse.
waitTime: float.
Return bool, True if succeed otherwise False.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationexpandcollapsepattern-collapse


def Expand(self, waitTime: float = OPERATION_WAIT_TIME) -> bool:

ret = self.pattern.Expand() == S_OK<EOL>time.sleep(waitTime)<EOL>return ret<EOL>

Call IUIAutomationExpandCollapsePattern::Expand.
waitTime: float.
Return bool, True if succeed otherwise False.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationexpandcollapsepattern-collapse


self.pattern = pattern<EOL>


@property<EOL><INDENT>def Column(self) -> int:<DEDENT>

return self.pattern.CurrentColumn<EOL>

Property Column.
Call IUIAutomationGridItemPattern::get_CurrentColumn.
Return int, the zero-based index of the column that contains the item.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationgriditempattern-get_currentcolumn


@property<EOL><INDENT>def ColumnSpan(self) -> int:<DEDENT>

return self.pattern.CurrentColumnSpan<EOL>

Property ColumnSpan.
Call IUIAutomationGridItemPattern::get_CurrentColumnSpan.
Return int, the number of columns spanned by the grid item.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationgriditempattern-get_currentcolumnspan


@property<EOL><INDENT>def ContainingGrid(self) -> '<STR_LIT>':<DEDENT>

return Control.CreateControlFromElement(self.pattern.CurrentContainingGrid)<EOL>

Property ContainingGrid.
Call IUIAutomationGridItemPattern::get_CurrentContainingGrid.
Return `Control` subclass, the element that contains the grid item.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationgriditempattern-get_currentcontaininggrid


@property<EOL><INDENT>def Row(self) -> int:<DEDENT>

return self.pattern.CurrentRow<EOL>

Property Row.
Call IUIAutomationGridItemPattern::get_CurrentRow.
Return int, the zero-based index of the row that contains the grid item.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationgriditempattern-get_currentrow


@property<EOL><INDENT>def RowSpan(self) -> int:<DEDENT>

return self.pattern.CurrentRowSpan<EOL>

Property RowSpan.
Call IUIAutomationGridItemPattern::get_CurrentRowSpan.
Return int, the number of rows spanned by the grid item.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationgriditempattern-get_currentrowspan


@property<EOL><INDENT>def ColumnCount(self) -> int:<DEDENT>

return self.pattern.CurrentColumnCount<EOL>

Property ColumnCount.
Call IUIAutomationGridPattern::get_CurrentColumnCount.
Return int, the number of columns in the grid.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationgridpattern-get_currentcolumncount


@property<EOL><INDENT>def RowCount(self) -> int:<DEDENT>

return self.pattern.CurrentRowCount<EOL>

Property RowCount.
Call IUIAutomationGridPattern::get_CurrentRowCount.
Return int, the number of rows in the grid.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationgridpattern-get_currentrowcount


return Control.CreateControlFromElement(self.pattern.GetItem())<EOL>

Call IUIAutomationGridPattern::GetItem.
Return `Control` subclass, a control representing an item in the grid.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationgridpattern-getitem


def Invoke(self, waitTime: float = OPERATION_WAIT_TIME) -> bool:

ret = self.pattern.Invoke() == S_OK<EOL>time.sleep(waitTime)<EOL>return ret<EOL>

Call IUIAutomationInvokePattern::Invoke.
Invoke the action of a control, such as a button click.
waitTime: float.
Return bool, True if succeed otherwise False.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationinvokepattern-invoke


def FindItemByProperty(control: '<STR_LIT>', propertyId: int, propertyValue) -> '<STR_LIT>':

ele = self.pattern.FindItemByProperty(control.Element, propertyId, propertyValue)<EOL>return Control.CreateControlFromElement(ele)<EOL>

Call IUIAutomationItemContainerPattern::FindItemByProperty.
control: `Control` or its subclass.
propertyValue: COM VARIANT according to propertyId? todo.
propertyId: int, a value in class `PropertyId`.
Return `Control` subclass, a control within a containing element, based on a specified property value.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationitemcontainerpattern-finditembyproperty


@property<EOL><INDENT>def ChildId(self) -> int:<DEDENT>

return self.pattern.CurrentChildId<EOL>

Property ChildId.
Call IUIAutomationLegacyIAccessiblePattern::get_CurrentChildId.
Return int, the Microsoft Active Accessibility child identifier for the element.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationlegacyiaccessiblepattern-get_currentchildid


@property<EOL><INDENT>def DefaultAction(self) -> str:<DEDENT>

return self.pattern.CurrentDefaultAction<EOL>

Property DefaultAction.
Call IUIAutomationLegacyIAccessiblePattern::get_CurrentDefaultAction.
Return str, the Microsoft Active Accessibility current default action for the element.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationlegacyiaccessiblepattern-get_currentdefaultaction


@property<EOL><INDENT>def Description(self) -> str:<DEDENT>

return self.pattern.CurrentDescription<EOL>

Property Description.
Call IUIAutomationLegacyIAccessiblePattern::get_CurrentDescription.
Return str, the Microsoft Active Accessibility description of the element.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationlegacyiaccessiblepattern-get_currentdescription


@property<EOL><INDENT>def Help(self) -> str:<DEDENT>

return self.pattern.CurrentHelp<EOL>

Property Help.
Call IUIAutomationLegacyIAccessiblePattern::get_CurrentHelp.
Return str, the Microsoft Active Accessibility help string for the element.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationlegacyiaccessiblepattern-get_currenthelp


@property<EOL><INDENT>def KeyboardShortcut(self) -> str:<DEDENT>

return self.pattern.CurrentKeyboardShortcut<EOL>

Property KeyboardShortcut.
Call IUIAutomationLegacyIAccessiblePattern::get_CurrentKeyboardShortcut.
Return str, the Microsoft Active Accessibility keyboard shortcut property for the element.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationlegacyiaccessiblepattern-get_currentkeyboardshortcut


@property<EOL><INDENT>def Name(self) -> str:<DEDENT>

return self.pattern.CurrentName or '<STR_LIT>'<EOL>

Property Name.
Call IUIAutomationLegacyIAccessiblePattern::get_CurrentName.
Return str, the Microsoft Active Accessibility name property of the element.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationlegacyiaccessiblepattern-get_currentname


@property<EOL><INDENT>def Role(self) -> int:<DEDENT>

return self.pattern.CurrentRole<EOL>

Property Role.
Call IUIAutomationLegacyIAccessiblePattern::get_CurrentRole.
Return int, a value in calss `AccessibleRole`, the Microsoft Active Accessibility role identifier.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationlegacyiaccessiblepattern-get_currentrole


@property<EOL><INDENT>def State(self) -> int:<DEDENT>

return self.pattern.CurrentState<EOL>

Property State.
Call IUIAutomationLegacyIAccessiblePattern::get_CurrentState.
Return int, a value in calss `AccessibleState`, the Microsoft Active Accessibility state identifier.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationlegacyiaccessiblepattern-get_currentstate


@property<EOL><INDENT>def Value(self) -> str:<DEDENT>

return self.pattern.CurrentValue<EOL>

Property Value.
Call IUIAutomationLegacyIAccessiblePattern::get_CurrentValue.
Return str, the Microsoft Active Accessibility value property.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationlegacyiaccessiblepattern-get_currentvalue


def DoDefaultAction(self, waitTime: float = OPERATION_WAIT_TIME) -> bool:

ret = self.pattern.DoDefaultAction() == S_OK<EOL>time.sleep(waitTime)<EOL>return ret<EOL>

Call IUIAutomationLegacyIAccessiblePattern::DoDefaultAction.
Perform the Microsoft Active Accessibility default action for the element.
waitTime: float.
Return bool, True if succeed otherwise False.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationlegacyiaccessiblepattern-dodefaultaction


eleArray = self.pattern.GetCurrentSelection()<EOL>if eleArray:<EOL><INDENT>controls = []<EOL>for i in range(eleArray.Length):<EOL><INDENT>ele = eleArray.GetElement(i)<EOL>con = Control.CreateControlFromElement(element=ele)<EOL>if con:<EOL><INDENT>controls.append(con)<EOL><DEDENT><DEDENT>return controls<EOL><DEDENT>return []<EOL>

Call IUIAutomationLegacyIAccessiblePattern::GetCurrentSelection.
Return list, a list of `Control` subclasses,
             the Microsoft Active Accessibility property that identifies the selected children of this element.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationlegacyiaccessiblepattern-getcurrentselection


return self.pattern.GetIAccessible()<EOL>

Call IUIAutomationLegacyIAccessiblePattern::GetIAccessible, todo.
Return an IAccessible object that corresponds to the Microsoft UI Automation element.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationlegacyiaccessiblepattern-getiaccessible
Refer https://docs.microsoft.com/en-us/windows/desktop/api/oleacc/nn-oleacc-iaccessible


def Select(self, flagsSelect: int, waitTime: float = OPERATION_WAIT_TIME) -> bool:

ret = self.pattern.Select(flagsSelect) == S_OK<EOL>time.sleep(waitTime)<EOL>return ret<EOL>

Call IUIAutomationLegacyIAccessiblePattern::Select.
Perform a Microsoft Active Accessibility selection.
flagsSelect: int, a value in `AccessibleSelection`.
waitTime: float.
Return bool, True if succeed otherwise False.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationlegacyiaccessiblepattern-select


def SetValue(self, value: str, waitTime: float = OPERATION_WAIT_TIME) -> bool:

ret = self.pattern.SetValue(value) == S_OK<EOL>time.sleep(waitTime)<EOL>return ret<EOL>

Call IUIAutomationLegacyIAccessiblePattern::SetValue.
Set the Microsoft Active Accessibility value property for the element.
value: str.
waitTime: float.
Return bool, True if succeed otherwise False.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationlegacyiaccessiblepattern-setvalue


self.pattern = pattern<EOL>


@property<EOL><INDENT>def CurrentView(self) -> int:<DEDENT>

return self.pattern.CurrentCurrentView<EOL>

Property CurrentView.
Call IUIAutomationMultipleViewPattern::get_CurrentCurrentView.
Return int, the control-specific identifier of the current view of the control.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationmultipleviewpattern-get_currentcurrentview


return self.pattern.GetCurrentSupportedViews()<EOL>

Call IUIAutomationMultipleViewPattern::GetCurrentSupportedViews, todo.
Return list, a list of int, control-specific view identifiers.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationmultipleviewpattern-getcurrentsupportedviews


def GetViewName(self, view: int) -> str:

return self.pattern.GetViewName(view)<EOL>

Call IUIAutomationMultipleViewPattern::GetViewName.
view: int, the control-specific view identifier.
Return str, the name of a control-specific view.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationmultipleviewpattern-getviewname


return self.pattern.SetCurrentView(view) == S_OK<EOL>

Call IUIAutomationMultipleViewPattern::SetCurrentView.
Set the view of the control.
view: int, the control-specific view identifier.
Return bool, True if succeed otherwise False.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationmultipleviewpattern-getviewname


def GetUnderlyingObjectModel(self) -> ctypes.POINTER(comtypes.IUnknown):

return self.pattern.GetUnderlyingObjectModel()<EOL>

Call IUIAutomationObjectModelPattern::GetUnderlyingObjectModel, todo.
Return `ctypes.POINTER(comtypes.IUnknown)`, an interface used to access the underlying object model of the provider.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationobjectmodelpattern-getunderlyingobjectmodel


@property<EOL><INDENT>def IsReadOnly(self) -> bool:<DEDENT>

return self.pattern.CurrentIsReadOnly<EOL>

Property IsReadOnly.
Call IUIAutomationRangeValuePattern::get_CurrentIsReadOnly.
Return bool, indicates whether the value of the element can be changed.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationrangevaluepattern-get_currentisreadonly


@property<EOL><INDENT>def LargeChange(self) -> float:<DEDENT>

return self.pattern.CurrentLargeChange<EOL>

Property LargeChange.
Call IUIAutomationRangeValuePattern::get_CurrentLargeChange.
Return float, the value that is added to or subtracted from the value of the control
              when a large change is made, such as when the PAGE DOWN key is pressed.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationrangevaluepattern-get_currentlargechange


@property<EOL><INDENT>def Maximum(self) -> float:<DEDENT>

return self.pattern.CurrentMaximum<EOL>

Property Maximum.
Call IUIAutomationRangeValuePattern::get_CurrentMaximum.
Return float, the maximum value of the control.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationrangevaluepattern-get_currentmaximum


@property<EOL><INDENT>def Minimum(self) -> float:<DEDENT>

return self.pattern.CurrentMinimum<EOL>

Property Minimum.
Call IUIAutomationRangeValuePattern::get_CurrentMinimum.
Return float, the minimum value of the control.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationrangevaluepattern-get_currentminimum


@property<EOL><INDENT>def SmallChange(self) -> float:<DEDENT>

return self.pattern.CurrentSmallChange<EOL>

Property SmallChange.
Call IUIAutomationRangeValuePattern::get_CurrentSmallChange.
Return float, the value that is added to or subtracted from the value of the control
              when a small change is made, such as when an arrow key is pressed.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationrangevaluepattern-get_currentsmallchange


@property<EOL><INDENT>def Value(self) -> float:<DEDENT>

return self.pattern.CurrentValue<EOL>

Property Value.
Call IUIAutomationRangeValuePattern::get_CurrentValue.
Return float, the value of the control.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationrangevaluepattern-get_currentvalue


def SetValue(self, value: float, waitTime: float = OPERATION_WAIT_TIME) -> bool:

Call IUIAutomationRangeValuePattern::SetValue.
Set the value of the control.
value: int.
waitTime: float.
Return bool, True if succeed otherwise False.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationrangevaluepattern-setvalue


def ScrollIntoView(self, waitTime: float = OPERATION_WAIT_TIME) -> bool:

ret = self.pattern.ScrollIntoView() == S_OK<EOL>time.sleep(waitTime)<EOL>return ret<EOL>

Call IUIAutomationScrollItemPattern::ScrollIntoView.
waitTime: float.
Return bool, True if succeed otherwise False.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationscrollitempattern-scrollintoview


@property<EOL><INDENT>def HorizontallyScrollable(self) -> bool:<DEDENT>

return bool(self.pattern.CurrentHorizontallyScrollable)<EOL>

Property HorizontallyScrollable.
Call IUIAutomationScrollPattern::get_CurrentHorizontallyScrollable.
Return bool, indicates whether the element can scroll horizontally.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationscrollpattern-get_currenthorizontallyscrollable


@property<EOL><INDENT>def HorizontalScrollPercent(self) -> float:<DEDENT>

return self.pattern.CurrentHorizontalScrollPercent<EOL>

Property HorizontalScrollPercent.
Call IUIAutomationScrollPattern::get_CurrentHorizontalScrollPercent.
Return float, the horizontal scroll position.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationscrollpattern-get_currenthorizontalscrollpercent


@property<EOL><INDENT>def HorizontalViewSize(self) -> float:<DEDENT>

return self.pattern.CurrentHorizontalViewSize<EOL>

Property HorizontalViewSize.
Call IUIAutomationScrollPattern::get_CurrentHorizontalViewSize.
Return float, the horizontal size of the viewable region of a scrollable element.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationscrollpattern-get_currenthorizontalviewsize


@property<EOL><INDENT>def VerticallyScrollable(self) -> bool:<DEDENT>

return bool(self.pattern.CurrentVerticallyScrollable)<EOL>

Property VerticallyScrollable.
Call IUIAutomationScrollPattern::get_CurrentVerticallyScrollable.
Return bool, indicates whether the element can scroll vertically.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationscrollpattern-get_currentverticallyscrollable


@property<EOL><INDENT>def VerticalScrollPercent(self) -> float:<DEDENT>

return self.pattern.CurrentVerticalScrollPercent<EOL>

Property VerticalScrollPercent.
Call IUIAutomationScrollPattern::get_CurrentVerticalScrollPercent.
Return float, the vertical scroll position.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationscrollpattern-get_currentverticalscrollpercent


@property<EOL><INDENT>def VerticalViewSize(self) -> float:<DEDENT>

return self.pattern.CurrentVerticalViewSize<EOL>

Property VerticalViewSize.
Call IUIAutomationScrollPattern::get_CurrentVerticalViewSize.
Return float, the vertical size of the viewable region of a scrollable element.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationscrollpattern-get_currentverticalviewsize


def Scroll(self, horizontalAmount: int, verticalAmount: int, waitTime: float = OPERATION_WAIT_TIME) -> bool:

ret = self.pattern.Scroll(horizontalAmount, verticalAmount) == S_OK<EOL>time.sleep(waitTime)<EOL>return ret<EOL>

Call IUIAutomationScrollPattern::Scroll.
Scroll the visible region of the content area horizontally and vertically.
horizontalAmount: int, a value in ScrollAmount.
verticalAmount: int, a value in ScrollAmount.
waitTime: float.
Return bool, True if succeed otherwise False.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationscrollpattern-scroll


def SetScrollPercent(self, horizontalPercent: float, verticalPercent: float, waitTime: float = OPERATION_WAIT_TIME) -> bool:

ret = self.pattern.SetScrollPercent(horizontalPercent, verticalPercent) == S_OK<EOL>time.sleep(waitTime)<EOL>return ret<EOL>

Call IUIAutomationScrollPattern::SetScrollPercent.
Set the horizontal and vertical scroll positions as a percentage of the total content area within the UI Automation element.
horizontalPercent: float or int, a value in [0, 100] or ScrollPattern.NoScrollValue(-1) if no scroll.
verticalPercent: float or int, a value  in [0, 100] or ScrollPattern.NoScrollValue(-1) if no scroll.
waitTime: float.
Return bool, True if succeed otherwise False.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationscrollpattern-setscrollpercent


self.pattern = pattern<EOL>


def AddToSelection(self, waitTime: float = OPERATION_WAIT_TIME) -> bool:

ret = self.pattern.AddToSelection() == S_OK<EOL>time.sleep(waitTime)<EOL>return ret<EOL>

Call IUIAutomationSelectionItemPattern::AddToSelection.
Add the current element to the collection of selected items.
waitTime: float.
Return bool, True if succeed otherwise False.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationselectionitempattern-addtoselection


@property<EOL><INDENT>def IsSelected(self) -> bool:<DEDENT>

return bool(self.pattern.CurrentIsSelected)<EOL>

Property IsSelected.
Call IUIAutomationScrollPattern::get_CurrentIsSelected.
Return bool, indicates whether this item is selected.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationscrollpattern-get_currentisselected


@property<EOL><INDENT>def SelectionContainer(self) -> '<STR_LIT>':<DEDENT>

ele = self.pattern.CurrentSelectionContainer<EOL>return Control.CreateControlFromElement(ele)<EOL>

Property SelectionContainer.
Call IUIAutomationScrollPattern::get_CurrentSelectionContainer.
Return `Control` subclass, the element that supports IUIAutomationSelectionPattern and acts as the container for this item.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationscrollpattern-get_currentselectioncontainer


def RemoveFromSelection(self, waitTime: float = OPERATION_WAIT_TIME) -> bool:

ret = self.pattern.RemoveFromSelection() == S_OK<EOL>time.sleep(waitTime)<EOL>return ret<EOL>

Call IUIAutomationSelectionItemPattern::RemoveFromSelection.
Remove this element from the selection.
waitTime: float.
Return bool, True if succeed otherwise False.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationselectionitempattern-removefromselection


def Select(self, waitTime: float = OPERATION_WAIT_TIME) -> bool:

ret = self.pattern.Select() == S_OK<EOL>time.sleep(waitTime)<EOL>return ret<EOL>

Call IUIAutomationSelectionItemPattern::Select.
Clear any selected items and then select the current element.
waitTime: float.
Return bool, True if succeed otherwise False.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationselectionitempattern-select


@property<EOL><INDENT>def CanSelectMultiple(self) -> bool:<DEDENT>

return bool(self.pattern.CurrentCanSelectMultiple)<EOL>

Property CanSelectMultiple.
Call IUIAutomationSelectionPattern::get_CurrentCanSelectMultiple.
Return bool, indicates whether more than one item in the container can be selected at one time.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationselectionpattern-get_currentcanselectmultiple


@property<EOL><INDENT>def IsSelectionRequired(self) -> bool:<DEDENT>

return bool(self.pattern.CurrentIsSelectionRequired)<EOL>

Property IsSelectionRequired.
Call IUIAutomationSelectionPattern::get_CurrentIsSelectionRequired.
Return bool, indicates whether at least one item must be selected at all times.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationselectionpattern-get_currentisselectionrequired


eleArray = self.pattern.GetCurrentSelection()<EOL>if eleArray:<EOL><INDENT>controls = []<EOL>for i in range(eleArray.Length):<EOL><INDENT>ele = eleArray.GetElement(i)<EOL>con = Control.CreateControlFromElement(element=ele)<EOL>if con:<EOL><INDENT>controls.append(con)<EOL><DEDENT><DEDENT>return controls<EOL><DEDENT>return []<EOL>

Call IUIAutomationSelectionPattern::GetCurrentSelection.
Return list, a list of `Control` subclasses, the selected elements in the container..
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationselectionpattern-getcurrentselection


@property<EOL><INDENT>def Formula(self) -> str:<DEDENT>

return self.pattern.CurrentFormula<EOL>

Property Formula.
Call IUIAutomationSpreadsheetItemPattern::get_CurrentFormula.
Return str, the formula for this cell.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationspreadsheetitempattern-get_currentformula


eleArray = self.pattern.GetCurrentAnnotationObjects()<EOL>if eleArray:<EOL><INDENT>controls = []<EOL>for i in range(eleArray.Length):<EOL><INDENT>ele = eleArray.GetElement(i)<EOL>con = Control.CreateControlFromElement(element=ele)<EOL>if con:<EOL><INDENT>controls.append(con)<EOL><DEDENT><DEDENT>return controls<EOL><DEDENT>return []<EOL>

Call IUIAutomationSelectionPattern::GetCurrentAnnotationObjects.
Return list, a list of `Control` subclasses representing the annotations associated with this spreadsheet cell.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationspreadsheetitempattern-getcurrentannotationobjects


return self.pattern.GetCurrentAnnotationTypes()<EOL>

Call IUIAutomationSelectionPattern::GetCurrentAnnotationTypes.
Return list, a list of int values in class `AnnotationType`,
             indicating the types of annotations that are associated with this spreadsheet cell.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationselectionpattern-getcurrentannotationtypes


def GetItemByName(self, name: str) -> '<STR_LIT>':

ele = self.pattern.GetItemByName(name)<EOL>return Control.CreateControlFromElement(element=ele)<EOL>

Call IUIAutomationSpreadsheetPattern::GetItemByName.
name: str.
Return `Control` subclass or None, represents the spreadsheet cell that has the specified name..
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationspreadsheetpattern-getitembyname


@property<EOL><INDENT>def ExtendedProperties(self) -> str:<DEDENT>

return self.pattern.CurrentExtendedProperties<EOL>

Property ExtendedProperties.
Call IUIAutomationStylesPattern::get_CurrentExtendedProperties.
Return str, a localized string that contains the list of extended properties for an element in a document.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationstylespattern-get_currentextendedproperties


@property<EOL><INDENT>def FillColor(self) -> int:<DEDENT>

return self.pattern.CurrentFillColor<EOL>

Property FillColor.
Call IUIAutomationStylesPattern::get_CurrentFillColor.
Return int, the fill color of an element in a document.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationstylespattern-get_currentfillcolor


@property<EOL><INDENT>def FillPatternColor(self) -> int:<DEDENT>

return self.pattern.CurrentFillPatternColor<EOL>

Property FillPatternColor.
Call IUIAutomationStylesPattern::get_CurrentFillPatternColor.
Return int, the color of the pattern used to fill an element in a document.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationstylespattern-get_currentfillpatterncolor


@property<EOL><INDENT>def Shape(self) -> str:<DEDENT>

return self.pattern.CurrentShape<EOL>

Property Shape.
Call IUIAutomationStylesPattern::get_CurrentShape.
Return str, the shape of an element in a document.
Refer https://docs.microsoft.com/en-us/windows/desktop/api/uiautomationclient/nf-uiautomationclient-iuiautomationstylespattern-get_currentshape