Skip to content

Commit

Permalink
issue_650: add signatures for WinAPI, unify usage of GetWindowThreadP…
Browse files Browse the repository at this point in the history
…rocessId

Add signatures for GetKeyboardState, GetWindowRect, GetWindowText,
GetWindowTextLength, GetClientRect, IsChild, IsWindow, ClientToScreen,
ScreenToClient, GetCurrentThreadId, GetWindowThreadProcessId, SendInput

Use win32functions.GetWindowThreadProcessId instead of a wrapper from win32process
  • Loading branch information
airelil committed Apr 27, 2019
1 parent 693db2d commit af261c8
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 41 deletions.
2 changes: 1 addition & 1 deletion pywinauto/base_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -945,7 +945,7 @@ def type_keys(

# attach the Python process with the process that self is in
if self.element_info.handle:
window_thread_id, _ = win32process.GetWindowThreadProcessId(int(self.handle))
window_thread_id = win32functions.GetWindowThreadProcessId(self.handle, None)
win32functions.AttachThreadInput(win32functions.GetCurrentThreadId(), window_thread_id, win32defines.TRUE)
# TODO: check return value of AttachThreadInput properly
else:
Expand Down
23 changes: 12 additions & 11 deletions pywinauto/controls/hwndwrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -546,15 +546,15 @@ def send_keystrokes(self,

win32gui.SendMessage(self.handle, win32con.WM_ACTIVATE,
win32con.WA_ACTIVE, 0)
target_thread_id = user32.GetWindowThreadProcessId(self.handle, None)
current_thread_id = win32api.GetCurrentThreadId()
attach_success = user32.AttachThreadInput(target_thread_id, current_thread_id, True) != 0
target_thread_id = win32functions.GetWindowThreadProcessId(self.handle, None)
current_thread_id = win32functions.GetCurrentThreadId()
attach_success = win32functions.AttachThreadInput(target_thread_id, current_thread_id, True) != 0
if not attach_success:
warnings.warn('Failed to attach app\'s thread to the current thread\'s message queue',
UserWarning, stacklevel=2)

keyboard_state_stack = [PBYTE256()]
user32.GetKeyboardState(ctypes.byref(keyboard_state_stack[-1]))
win32functions.GetKeyboardState(keyboard_state_stack[-1])

input_locale_id = ctypes.windll.User32.GetKeyboardLayout(0)
context_code = 0
Expand Down Expand Up @@ -1256,7 +1256,7 @@ def get_active(self):
"""Return a handle to the active window within the process"""
gui_info = win32structures.GUITHREADINFO()
gui_info.cbSize = ctypes.sizeof(gui_info)
window_thread_id, _ = win32process.GetWindowThreadProcessId(int(self.handle))
window_thread_id = win32functions.GetWindowThreadProcessId(self.handle, None)
ret = win32functions.GetGUIThreadInfo(
window_thread_id,
ctypes.byref(gui_info))
Expand All @@ -1278,7 +1278,7 @@ def get_focus(self):
"""
gui_info = win32structures.GUITHREADINFO()
gui_info.cbSize = ctypes.sizeof(gui_info)
window_thread_id, _ = win32process.GetWindowThreadProcessId(self.handle)
window_thread_id = win32functions.GetWindowThreadProcessId(self.handle, None)
ret = win32functions.GetGUIThreadInfo(
window_thread_id,
ctypes.byref(gui_info))
Expand Down Expand Up @@ -1335,7 +1335,7 @@ def has_focus(self):

def has_keyboard_focus(self):
"""Check the keyboard focus on this control."""
control_thread = win32process.GetWindowThreadProcessId(self.handle)[0]
control_thread = win32functions.GetWindowThreadProcessId(self.handle, None)
win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 1)
focused = win32gui.GetFocus()
win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 0)
Expand All @@ -1346,7 +1346,7 @@ def has_keyboard_focus(self):

def set_keyboard_focus(self):
"""Set the keyboard focus to this control."""
control_thread = win32process.GetWindowThreadProcessId(self.handle)[0]
control_thread = win32functions.GetWindowThreadProcessId(self.handle, None)
win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 1)
win32gui.SetFocus(self.handle)
win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 0)
Expand Down Expand Up @@ -1602,12 +1602,13 @@ def force_close(self):
#win32defines.SMTO_BLOCK)

# get a handle we can wait on
_, pid = win32process.GetWindowThreadProcessId(int(self.handle))
pid = wintypes.DWORD
win32functions.GetWindowThreadProcessId(self.handle, ctypes.byref(pid))
try:
process_wait_handle = win32api.OpenProcess(
win32con.SYNCHRONIZE | win32con.PROCESS_TERMINATE,
0,
pid)
pid.value)
except win32gui.error:
return True # already closed

Expand Down Expand Up @@ -1723,7 +1724,7 @@ def _perform_click(
# figure out the flags and pack coordinates
flags, click_point = _calc_flags_and_coords(pressed, coords)

#control_thread = win32functions.GetWindowThreadProcessId(ctrl, 0)
#control_thread = win32functions.GetWindowThreadProcessId(ctrl, None)
#win32functions.AttachThreadInput(win32functions.GetCurrentThreadId(), control_thread, win32defines.TRUE)
# TODO: check return value of AttachThreadInput properly

Expand Down
5 changes: 3 additions & 2 deletions pywinauto/handleprops.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,9 @@ def font(handle):
#=========================================================================
def processid(handle):
"""Return the ID of process that controls this window"""
_, process_id = win32process.GetWindowThreadProcessId(int(handle))
return process_id
pid = wintypes.DWORD()
win32functions.GetWindowThreadProcessId(handle, byref(pid))
return pid.value


#=========================================================================
Expand Down
7 changes: 2 additions & 5 deletions pywinauto/keyboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
import six

from . import win32structures
from . import win32functions

__all__ = ['KeySequenceError', 'send_keys']

Expand All @@ -122,10 +123,6 @@

GetMessageExtraInfo = ctypes.windll.user32.GetMessageExtraInfo
MapVirtualKey = ctypes.windll.user32.MapVirtualKeyW
SendInput = ctypes.windll.user32.SendInput
UINT = ctypes.c_uint
SendInput.restype = UINT
SendInput.argtypes = [UINT, ctypes.c_void_p, ctypes.c_int]

VkKeyScan = ctypes.windll.user32.VkKeyScanW
VkKeyScan.restype = ctypes.c_short
Expand Down Expand Up @@ -381,7 +378,7 @@ def run(self):
inputs = self.GetInput()

# SendInput() supports all Unicode symbols
num_inserted_events = SendInput(len(inputs), ctypes.byref(inputs),
num_inserted_events = win32functions.SendInput(len(inputs), ctypes.byref(inputs),
ctypes.sizeof(win32structures.INPUT))
if num_inserted_events != len(inputs):
raise RuntimeError('SendInput() inserted only ' + str(num_inserted_events) +
Expand Down
4 changes: 3 additions & 1 deletion pywinauto/remote_memory_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ def __init__(self, ctrl, size=4096):

self._as_parameter_ = self.mem_address

_, process_id = win32process.GetWindowThreadProcessId(self.handle)
pid = wintypes.DWORD()
win32functions.GetWindowThreadProcessId(self.handle, byref(pid))
process_id = pid.value
if not process_id:
raise AccessDenied(
str(WinError()) + " Cannot get process ID from handle.")
Expand Down
2 changes: 2 additions & 0 deletions pywinauto/unittests/test_handleprops.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,8 @@ def test_processid(self):
"""Make sure processid() function works"""
self.assertEqual(self.app.process, processid(self.dlghandle))
self.assertEqual(self.app.process, processid(self.edit_handle))
self.assertEqual(0, processid(sys.maxsize))
self.assertEqual(0, processid(None))

def test_children(self):
"""Make sure the children method returns correct result"""
Expand Down
100 changes: 79 additions & 21 deletions pywinauto/win32functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,11 @@
GetCaretPos.argtypes = [
ctypes.POINTER(win32structures.POINT),
]

GetKeyboardState = ctypes.windll.user32.GetKeyboardState
GetKeyboardState.restype = wintypes.BOOL
GetKeyboardState.argtypes = [
ctypes.POINTER(ctypes.c_ubyte),
]
# menu functions
DrawMenuBar = ctypes.windll.user32.DrawMenuBar
DrawMenuBar.restype = wintypes.BOOL
Expand Down Expand Up @@ -332,31 +336,85 @@
wintypes.HWND,
ctypes.POINTER(win32structures.WINDOWPLACEMENT),
]
GetWindowRect = ctypes.windll.user32.GetWindowRect
GetWindowText = ctypes.windll.user32.GetWindowTextW
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
GetClassName = ctypes.windll.user32.GetClassNameW
GetClassName.argtypes = [wintypes.HWND, wintypes.LPWSTR, ctypes.c_int]
GetWindowRect = ctypes.windll.user32.GetWindowRect
GetWindowRect.restype = wintypes.BOOL
GetWindowRect.argtypes = [
wintypes.HWND,
ctypes.POINTER(win32structures.RECT),
]
GetWindowText = ctypes.windll.user32.GetWindowTextW
GetWindowText.restype = ctypes.c_int
GetWindowText.argtypes = [
wintypes.HWND,
wintypes.LPWSTR,
ctypes.c_int,
]
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
GetWindowTextLength.restype = ctypes.c_int
GetWindowTextLength.argtypes = [
wintypes.HWND,
]
GetClassName = ctypes.windll.user32.GetClassNameW
GetClassName.restype = ctypes.c_int
GetClientRect = ctypes.windll.user32.GetClientRect
IsChild = ctypes.windll.user32.IsChild
IsWindow = ctypes.windll.user32.IsWindow
IsWindow.argtypes = [wintypes.HWND]
GetClassName.argtypes = [
wintypes.HWND,
wintypes.LPWSTR,
ctypes.c_int
]
GetClientRect = ctypes.windll.user32.GetClientRect
GetClientRect.restype = wintypes.BOOL
GetClientRect.argtypes = [
wintypes.HWND,
ctypes.POINTER(win32structures.RECT),
]
IsChild = ctypes.windll.user32.IsChild
IsChild.restype = wintypes.BOOL
IsChild.argtypes = [
wintypes.HWND,
wintypes.HWND,
]
IsWindow = ctypes.windll.user32.IsWindow
IsWindow.restype = wintypes.BOOL
IsWindowUnicode = ctypes.windll.user32.IsWindowUnicode
IsWindowUnicode.argtypes = [wintypes.HWND]
IsWindow.argtypes = [
wintypes.HWND,
]
IsWindowUnicode = ctypes.windll.user32.IsWindowUnicode
IsWindowUnicode.restype = wintypes.BOOL
IsWindowVisible = ctypes.windll.user32.IsWindowVisible
IsWindowVisible.argtypes = [wintypes.HWND]
IsWindowUnicode.argtypes = [
wintypes.HWND,
]
IsWindowVisible = ctypes.windll.user32.IsWindowVisible
IsWindowVisible.restype = wintypes.BOOL
IsWindowEnabled = ctypes.windll.user32.IsWindowEnabled
IsWindowEnabled.argtypes = [wintypes.HWND]
IsWindowVisible.argtypes = [
wintypes.HWND,
]
IsWindowEnabled = ctypes.windll.user32.IsWindowEnabled
IsWindowEnabled.restype = wintypes.BOOL
ClientToScreen = ctypes.windll.user32.ClientToScreen
ScreenToClient = ctypes.windll.user32.ScreenToClient

GetCurrentThreadId = ctypes.windll.Kernel32.GetCurrentThreadId
GetWindowThreadProcessId = ctypes.windll.user32.GetWindowThreadProcessId
IsWindowEnabled.argtypes = [
wintypes.HWND,
]
ClientToScreen = ctypes.windll.user32.ClientToScreen
ClientToScreen.restype = wintypes.BOOL
ClientToScreen.argtypes = [
wintypes.HWND,
ctypes.POINTER(win32structures.POINT),
]
ScreenToClient = ctypes.windll.user32.ScreenToClient
ScreenToClient.restype = wintypes.BOOL
ScreenToClient.argtypes = [
wintypes.HWND,
ctypes.POINTER(win32structures.POINT),
]
GetCurrentThreadId = ctypes.windll.kernel32.GetCurrentThreadId
GetCurrentThreadId.restype = wintypes.DWORD
GetCurrentThreadId.argtypes = [
]
GetWindowThreadProcessId = ctypes.windll.user32.GetWindowThreadProcessId
GetWindowThreadProcessId.restype = wintypes.DWORD
GetWindowThreadProcessId.argtypes = [
wintypes.HWND,
ctypes.POINTER(wintypes.DWORD),
]
GetGUIThreadInfo = ctypes.windll.user32.GetGUIThreadInfo
AttachThreadInput = ctypes.windll.user32.AttachThreadInput
AttachThreadInput.restype = wintypes.BOOL
Expand Down

0 comments on commit af261c8

Please sign in to comment.