You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
329 lines
14 KiB
329 lines
14 KiB
6 years ago
|
# GUI Application automation and testing library
|
||
|
# Copyright (C) 2006-2018 Mark Mc Mahon and Contributors
|
||
|
# https://github.com/pywinauto/pywinauto/graphs/contributors
|
||
|
# http://pywinauto.readthedocs.io/en/latest/credits.html
|
||
|
# All rights reserved.
|
||
|
#
|
||
|
# Redistribution and use in source and binary forms, with or without
|
||
|
# modification, are permitted provided that the following conditions are met:
|
||
|
#
|
||
|
# * Redistributions of source code must retain the above copyright notice, this
|
||
|
# list of conditions and the following disclaimer.
|
||
|
#
|
||
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||
|
# this list of conditions and the following disclaimer in the documentation
|
||
|
# and/or other materials provided with the distribution.
|
||
|
#
|
||
|
# * Neither the name of pywinauto nor the names of its
|
||
|
# contributors may be used to endorse or promote products derived from
|
||
|
# this software without specific prior written permission.
|
||
|
#
|
||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
||
|
"""Defines Windows(tm) functions"""
|
||
|
|
||
|
import ctypes
|
||
|
from ctypes import wintypes
|
||
|
from . import win32defines, win32structures
|
||
|
from .actionlogger import ActionLogger
|
||
|
from ctypes import c_uint, c_short, c_long
|
||
|
|
||
|
import sys
|
||
|
if sys.platform == "cygwin":
|
||
|
windll = ctypes.cdll
|
||
|
HRESULT = c_long
|
||
|
|
||
|
|
||
|
UINT = c_uint
|
||
|
SHORT = c_short
|
||
|
|
||
|
|
||
|
CreateBrushIndirect = ctypes.windll.gdi32.CreateBrushIndirect
|
||
|
CreateDC = ctypes.windll.gdi32.CreateDCW
|
||
|
CreateFontIndirect = ctypes.windll.gdi32.CreateFontIndirectW
|
||
|
CreatePen = ctypes.windll.gdi32.CreatePen
|
||
|
DeleteDC = ctypes.windll.gdi32.DeleteDC
|
||
|
GetObject = ctypes.windll.gdi32.GetObjectW
|
||
|
DeleteObject = ctypes.windll.gdi32.DeleteObject
|
||
|
DrawText = ctypes.windll.user32.DrawTextW
|
||
|
TextOut = ctypes.windll.gdi32.TextOutW
|
||
|
Rectangle = ctypes.windll.gdi32.Rectangle
|
||
|
SelectObject = ctypes.windll.gdi32.SelectObject
|
||
|
GetStockObject = ctypes.windll.gdi32.GetStockObject
|
||
|
GetSystemMetrics = ctypes.windll.user32.GetSystemMetrics
|
||
|
GetSystemMetrics.restype = ctypes.c_int
|
||
|
GetSystemMetrics.argtypes = (ctypes.c_int, )
|
||
|
GetTextMetrics = ctypes.windll.gdi32.GetTextMetricsW
|
||
|
|
||
|
|
||
|
EnumChildWindows = ctypes.windll.user32.EnumChildWindows
|
||
|
EnumDesktopWindows = ctypes.windll.user32.EnumDesktopWindows
|
||
|
EnumWindows = ctypes.windll.user32.EnumWindows
|
||
|
GetDC = ctypes.windll.user32.GetDC
|
||
|
GetDesktopWindow = ctypes.windll.user32.GetDesktopWindow
|
||
|
|
||
|
|
||
|
SendInput = ctypes.windll.user32.SendInput
|
||
|
SetCursorPos = ctypes.windll.user32.SetCursorPos
|
||
|
GetCursorPos = ctypes.windll.user32.GetCursorPos
|
||
|
GetCaretPos = ctypes.windll.user32.GetCaretPos
|
||
|
|
||
|
# menu functions
|
||
|
DrawMenuBar = ctypes.windll.user32.DrawMenuBar
|
||
|
GetMenu = ctypes.windll.user32.GetMenu
|
||
|
GetMenuBarInfo = ctypes.windll.user32.GetMenuBarInfo
|
||
|
GetMenuInfo = ctypes.windll.user32.GetMenuInfo
|
||
|
GetMenuItemCount = ctypes.windll.user32.GetMenuItemCount
|
||
|
GetMenuItemInfo = ctypes.windll.user32.GetMenuItemInfoW
|
||
|
SetMenuItemInfo = ctypes.windll.user32.SetMenuItemInfoW
|
||
|
GetMenuItemRect = ctypes.windll.user32.GetMenuItemRect
|
||
|
CheckMenuItem = ctypes.windll.user32.CheckMenuItem
|
||
|
GetMenuState = ctypes.windll.user32.GetMenuState
|
||
|
GetSubMenu = ctypes.windll.user32.GetSubMenu
|
||
|
GetSystemMenu = ctypes.windll.user32.GetSystemMenu
|
||
|
HiliteMenuItem = ctypes.windll.user32.HiliteMenuItem
|
||
|
IsMenu = ctypes.windll.user32.IsMenu
|
||
|
MenuItemFromPoint = ctypes.windll.user32.MenuItemFromPoint
|
||
|
|
||
|
BringWindowToTop = ctypes.windll.user32.BringWindowToTop
|
||
|
|
||
|
GetVersion = ctypes.windll.kernel32.GetVersion
|
||
|
|
||
|
GetParent = ctypes.windll.user32.GetParent
|
||
|
GetWindow = ctypes.windll.user32.GetWindow
|
||
|
ShowWindow = ctypes.windll.user32.ShowWindow
|
||
|
GetWindowContextHelpId = ctypes.windll.user32.GetWindowContextHelpId
|
||
|
GetWindowLong = ctypes.windll.user32.GetWindowLongW
|
||
|
GetWindowPlacement = ctypes.windll.user32.GetWindowPlacement
|
||
|
GetWindowRect = ctypes.windll.user32.GetWindowRect
|
||
|
GetWindowText = ctypes.windll.user32.GetWindowTextW
|
||
|
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
|
||
|
GetClassName = ctypes.windll.user32.GetClassNameW
|
||
|
GetClientRect = ctypes.windll.user32.GetClientRect
|
||
|
IsChild = ctypes.windll.user32.IsChild
|
||
|
IsWindow = ctypes.windll.user32.IsWindow
|
||
|
IsWindowUnicode = ctypes.windll.user32.IsWindowUnicode
|
||
|
IsWindowVisible = ctypes.windll.user32.IsWindowVisible
|
||
|
IsWindowEnabled = ctypes.windll.user32.IsWindowEnabled
|
||
|
ClientToScreen = ctypes.windll.user32.ClientToScreen
|
||
|
ScreenToClient = ctypes.windll.user32.ScreenToClient
|
||
|
|
||
|
GetCurrentThreadId = ctypes.windll.Kernel32.GetCurrentThreadId
|
||
|
GetWindowThreadProcessId = ctypes.windll.user32.GetWindowThreadProcessId
|
||
|
GetGUIThreadInfo = ctypes.windll.user32.GetGUIThreadInfo
|
||
|
AttachThreadInput = ctypes.windll.user32.AttachThreadInput
|
||
|
AttachThreadInput.restype = win32structures.BOOL
|
||
|
AttachThreadInput.argtypes = [win32structures.DWORD, win32structures.DWORD, win32structures.BOOL]
|
||
|
#GetWindowThreadProcessId = ctypes.windll.user32.GetWindowThreadProcessId
|
||
|
GetLastError = ctypes.windll.kernel32.GetLastError
|
||
|
|
||
|
OpenProcess = ctypes.windll.kernel32.OpenProcess
|
||
|
CloseHandle = ctypes.windll.kernel32.CloseHandle
|
||
|
CreateProcess = ctypes.windll.kernel32.CreateProcessW
|
||
|
TerminateProcess = ctypes.windll.kernel32.TerminateProcess
|
||
|
ExitProcess = ctypes.windll.kernel32.ExitProcess
|
||
|
|
||
|
ReadProcessMemory = ctypes.windll.kernel32.ReadProcessMemory
|
||
|
GlobalAlloc = ctypes.windll.kernel32.GlobalAlloc
|
||
|
GlobalLock = ctypes.windll.kernel32.GlobalLock
|
||
|
GlobalUnlock = ctypes.windll.kernel32.GlobalUnlock
|
||
|
|
||
|
SendMessage = ctypes.windll.user32.SendMessageW
|
||
|
SendMessageTimeout = ctypes.windll.user32.SendMessageTimeoutW
|
||
|
SendMessageA = ctypes.windll.user32.SendMessageA
|
||
|
PostMessage = ctypes.windll.user32.PostMessageW
|
||
|
GetMessage = ctypes.windll.user32.GetMessageW
|
||
|
RegisterWindowMessage = ctypes.windll.user32.RegisterWindowMessageW
|
||
|
|
||
|
MoveWindow = ctypes.windll.user32.MoveWindow
|
||
|
EnableWindow = ctypes.windll.user32.EnableWindow
|
||
|
SetActiveWindow = ctypes.windll.user32.SetActiveWindow
|
||
|
GetFocus = ctypes.windll.user32.GetFocus
|
||
|
SetFocus = ctypes.windll.user32.SetFocus
|
||
|
SetForegroundWindow = ctypes.windll.user32.SetForegroundWindow
|
||
|
GetForegroundWindow = ctypes.windll.user32.GetForegroundWindow
|
||
|
SetWindowLong = ctypes.windll.user32.SetWindowLongW
|
||
|
try:
|
||
|
SetWindowLongPtr = ctypes.windll.user32.SetWindowLongPtrW
|
||
|
SetWindowLongPtr.argtypes = [win32structures.HWND, ctypes.c_int, win32structures.LONG_PTR]
|
||
|
SetWindowLongPtr.restype = win32structures.LONG_PTR
|
||
|
except AttributeError:
|
||
|
SetWindowLongPtr = SetWindowLong
|
||
|
SystemParametersInfo = ctypes.windll.user32.SystemParametersInfoW
|
||
|
VirtualAllocEx = ctypes.windll.kernel32.VirtualAllocEx
|
||
|
VirtualAllocEx.restype = ctypes.c_void_p
|
||
|
VirtualFreeEx = ctypes.windll.kernel32.VirtualFreeEx
|
||
|
DebugBreakProcess = ctypes.windll.kernel32.DebugBreakProcess
|
||
|
|
||
|
VirtualAlloc = ctypes.windll.kernel32.VirtualAlloc
|
||
|
VirtualFree = ctypes.windll.kernel32.VirtualFree
|
||
|
WriteProcessMemory = ctypes.windll.kernel32.WriteProcessMemory
|
||
|
GetActiveWindow = ctypes.windll.user32.GetActiveWindow
|
||
|
GetLastActivePopup = ctypes.windll.user32.GetLastActivePopup
|
||
|
FindWindow = ctypes.windll.user32.FindWindowW
|
||
|
GetTopWindow = ctypes.windll.user32.GetTopWindow
|
||
|
|
||
|
SetCapture = ctypes.windll.user32.SetCapture
|
||
|
ReleaseCapture = ctypes.windll.user32.ReleaseCapture
|
||
|
|
||
|
ShowOwnedPopups = ctypes.windll.user32.ShowOwnedPopups
|
||
|
WindowFromPoint = ctypes.windll.user32.WindowFromPoint
|
||
|
|
||
|
WideCharToMultiByte = ctypes.windll.kernel32.WideCharToMultiByte
|
||
|
GetACP = ctypes.windll.kernel32.GetACP
|
||
|
|
||
|
WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject
|
||
|
WaitForInputIdle = ctypes.windll.user32.WaitForInputIdle
|
||
|
|
||
|
IsHungAppWindow = ctypes.windll.user32.IsHungAppWindow
|
||
|
IsHungAppWindow.restype = win32structures.BOOL
|
||
|
IsHungAppWindow.argtypes = [win32structures.HWND]
|
||
|
|
||
|
GetModuleFileNameEx = ctypes.windll.psapi.GetModuleFileNameExW
|
||
|
|
||
|
GetClipboardData = ctypes.windll.user32.GetClipboardData
|
||
|
OpenClipboard = ctypes.windll.user32.OpenClipboard
|
||
|
EmptyClipboard = ctypes.windll.user32.EmptyClipboard
|
||
|
CloseClipboard = ctypes.windll.user32.CloseClipboard
|
||
|
CountClipboardFormats = ctypes.windll.user32.CountClipboardFormats
|
||
|
EnumClipboardFormats = ctypes.windll.user32.EnumClipboardFormats
|
||
|
GetClipboardFormatName = ctypes.windll.user32.GetClipboardFormatNameW
|
||
|
|
||
|
# DPIAware API funcs are not available on WinXP
|
||
|
try:
|
||
|
IsProcessDPIAware = ctypes.windll.user32.IsProcessDPIAware
|
||
|
SetProcessDPIAware = ctypes.windll.user32.SetProcessDPIAware
|
||
|
except AttributeError:
|
||
|
IsProcessDPIAware = None
|
||
|
SetProcessDPIAware = None
|
||
|
|
||
|
# DpiAwareness API funcs are available only from win 8.1 and greater
|
||
|
# Supported types of DPI awareness described here:
|
||
|
# https://msdn.microsoft.com/en-us/library/windows/desktop/dn280512(v=vs.85).aspx
|
||
|
# typedef enum _Process_DPI_Awareness {
|
||
|
# Process_DPI_Unaware = 0,
|
||
|
# Process_System_DPI_Aware = 1,
|
||
|
# Process_Per_Monitor_DPI_Aware = 2
|
||
|
# } Process_DPI_Awareness;
|
||
|
try:
|
||
|
shcore = ctypes.windll.LoadLibrary("Shcore.dll")
|
||
|
SetProcessDpiAwareness = shcore.SetProcessDpiAwareness
|
||
|
GetProcessDpiAwareness = shcore.GetProcessDpiAwareness
|
||
|
Process_DPI_Awareness = {
|
||
|
"Process_DPI_Unaware" : 0,
|
||
|
"Process_System_DPI_Aware" : 1,
|
||
|
"Process_Per_Monitor_DPI_Aware" : 2
|
||
|
}
|
||
|
except (OSError, AttributeError):
|
||
|
SetProcessDpiAwareness = None
|
||
|
GetProcessDpiAwareness = None
|
||
|
Process_DPI_Awareness = None
|
||
|
|
||
|
# Setup DPI awareness for the python process if any is supported
|
||
|
if SetProcessDpiAwareness:
|
||
|
ActionLogger().log("Call SetProcessDpiAwareness")
|
||
|
SetProcessDpiAwareness(
|
||
|
Process_DPI_Awareness["Process_Per_Monitor_DPI_Aware"])
|
||
|
elif SetProcessDPIAware:
|
||
|
ActionLogger().log("Call SetProcessDPIAware")
|
||
|
SetProcessDPIAware()
|
||
|
|
||
|
GetQueueStatus = ctypes.windll.user32.GetQueueStatus
|
||
|
|
||
|
LoadString = ctypes.windll.user32.LoadStringW
|
||
|
|
||
|
|
||
|
#def VkKeyScanW(p1):
|
||
|
# # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4225
|
||
|
# return VkKeyScanW._api_(p1)
|
||
|
#VkKeyScan = stdcall(SHORT, 'user32', [c_wchar]) (VkKeyScanW)
|
||
|
#
|
||
|
#def MapVirtualKeyExW(p1, p2, p3):
|
||
|
# # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4376
|
||
|
# return MapVirtualKeyExW._api_(p1, p2, p3)
|
||
|
#MapVirtualKeyEx = stdcall(
|
||
|
# UINT, 'user32', [c_uint, c_uint, c_long]) (MapVirtualKeyExW)
|
||
|
#
|
||
|
#def MapVirtualKeyW(p1, p2):
|
||
|
# # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4355
|
||
|
# return MapVirtualKeyW._api_(p1, p2)
|
||
|
#MapVirtualKey = stdcall(UINT, 'user32', [c_uint, c_uint]) (MapVirtualKeyW)
|
||
|
|
||
|
|
||
|
#====================================================================
|
||
|
def MakeLong(high, low):
|
||
|
"""Pack high into the high word of a long and low into the low word"""
|
||
|
|
||
|
# we need to AND each value with 0xFFFF to account for numbers
|
||
|
# greater then normal WORD (short) size
|
||
|
return ((high & 0xFFFF) << 16) | (low & 0xFFFF)
|
||
|
|
||
|
#====================================================================
|
||
|
def HiWord(value):
|
||
|
"""Return the high word from a long"""
|
||
|
#return (value & (~ 0xFFFF)) / 0xFFFF
|
||
|
return (value >> 16) & 0xffff
|
||
|
|
||
|
#====================================================================
|
||
|
def LoWord(value):
|
||
|
"""Return the low word from a long"""
|
||
|
return value & 0xFFFF
|
||
|
|
||
|
#====================================================================
|
||
|
def WaitGuiThreadIdle(handle):
|
||
|
"""Wait until the thread of the specified handle is ready"""
|
||
|
process_id = wintypes.DWORD(0)
|
||
|
GetWindowThreadProcessId(handle, ctypes.POINTER(wintypes.DWORD)(process_id))
|
||
|
|
||
|
# ask the control if it has finished processing the message
|
||
|
hprocess = OpenProcess(
|
||
|
win32defines.PROCESS_QUERY_INFORMATION,
|
||
|
0,
|
||
|
process_id.value)
|
||
|
|
||
|
# WaitForInputIdle call is removed because it's useful only
|
||
|
# while an app is starting (should be called only once)
|
||
|
if IsHungAppWindow(handle) == win32defines.TRUE:
|
||
|
raise RuntimeError('Window (hwnd={0}) is not responding!'.format(handle))
|
||
|
|
||
|
CloseHandle(hprocess)
|
||
|
|
||
|
#====================================================================
|
||
|
def GetDpiAwarenessByPid(pid):
|
||
|
"""Get DPI awareness properties of a process specified by ID"""
|
||
|
dpi_awareness = -1
|
||
|
hProcess = None
|
||
|
if GetProcessDpiAwareness and pid:
|
||
|
hProcess = OpenProcess(
|
||
|
win32defines.PROCESS_QUERY_INFORMATION,
|
||
|
0,
|
||
|
pid)
|
||
|
if not hProcess:
|
||
|
# process doesn't exist, exit with a default return value
|
||
|
return dpi_awareness
|
||
|
|
||
|
try:
|
||
|
dpi_awareness = ctypes.c_int()
|
||
|
hRes = GetProcessDpiAwareness(
|
||
|
hProcess,
|
||
|
ctypes.byref(dpi_awareness))
|
||
|
CloseHandle(hProcess)
|
||
|
if hRes == 0:
|
||
|
return dpi_awareness.value
|
||
|
finally:
|
||
|
if hProcess:
|
||
|
CloseHandle(hProcess)
|
||
|
|
||
|
# GetProcessDpiAwareness is not supported or pid is not specified,
|
||
|
# return a default value
|
||
|
return dpi_awareness
|