import ctypes
import re
def get_display_name():
GetUserNameEx = ctypes.windll.secur32.GetUserNameExW
NameDisplay = 3
size = ctypes.pointer(ctypes.c_ulong(0))
GetUserNameEx(NameDisplay, None, size)
nameBuffer = ctypes.create_unicode_buffer(size.contents.value)
GetUserNameEx(NameDisplay, nameBuffer, size)
return nameBuffer.value
EnumWindows = ctypes.windll.user32.EnumWindows
EnumWindowsProc = ctypes.WINFUNCTYPE(
ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)
)
def HandleError(func):
def _handler(*args, **kwargs):
result = func(*args, **kwargs)
if result == 0:
raise Exception("Error!")
return result
return _handler
GetWindowText = ctypes.windll.user32.GetWindowTextW
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
IsWindowVisible = ctypes.windll.user32.IsWindowVisible
CloseWindow = ctypes.windll.user32.CloseWindow
ShowWindow = ctypes.windll.user32.ShowWindow
BringWindowToTop = HandleError(ctypes.windll.user32.BringWindowToTop)
SetForegroundWindow = HandleError(ctypes.windll.user32.SetForegroundWindow)
SetWindowPos = HandleError(ctypes.windll.user32.SetWindowPos)
GetWindowPlacement = ctypes.windll.user32.GetWindowPlacement
GetDesktopWindow = ctypes.windll.user32.GetDesktopWindow
GetClipboardData = ctypes.windll.user32.GetClipboardData
class POINT(ctypes.Structure):
_fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
class RECT(ctypes.Structure):
_fields_ = [
("left", ctypes.c_long),
("top", ctypes.c_long),
("right", ctypes.c_long),
("bottom", ctypes.c_long),
]
class WindowPlacement(ctypes.Structure):
_fields_ = [
("length", ctypes.c_uint),
("flags", ctypes.c_uint),
("showCmd", ctypes.c_uint),
("ptMinPosition", POINT),
("ptMaxPosition", POINT),
("rcNormalPosition", RECT),
("rcDevices", RECT),
]
@property
def top(self):
return self.rcNormalPosition.top
@property
def left(self):
return self.rcNormalPosition.left
@property
def bottom(self):
return self.rcNormalPosition.bottom
@property
def right(self):
return self.rcNormalPosition.right
@staticmethod
def get(handle):
winpl = WindowPlacement()
# print(index, title, str(handle))
# ShowWindow(handle, 9)
# BringWindowToTop(handle)
# SetForegroundWindow(handle)
GetWindowPlacement(handle, ctypes.byref(winpl))
return winpl
class Window(object):
"""A wrapper around a Window Handle object.
"""
def __init__(self, handle):
self.handle = handle
@property
def title(self):
if not hasattr(self, "_text"):
length = GetWindowTextLength(self.handle)
buff = ctypes.create_unicode_buffer(length + 1)
GetWindowText(self.handle, buff, length + 1)
self._text = buff.value
return self._text
@property
def placement(self):
if not hasattr(self, "_placement"):
self._placement = WindowPlacement.get(self.handle)
return self._placement
@property
def desktop(self):
if not hasattr(self, "_desktop"):
self._desktop = Desktop()
return self._desktop
@property
def visible(self):
return IsWindowVisible(self.handle)
@property
def top(self):
return self.placement.top
@property
def right(self):
return self.placement.right
@property
def bottom(self):
return self.placement.bottom
@property
def left(self):
return self.placement.left
@property
def width(self):
return self.right - self.left
@property
def height(self):
return self.bottom - self.top
def bring_to_front(self):
ShowWindow(self.handle, 9)
SetForegroundWindow(self.handle)
def set_position(self, top, left, width, height):
SetWindowPos(self.handle, 0, top, left, width, height, 0)
def anchor_top_left(self):
width = int(self.desktop.width / 2)
height = int(self.desktop.height / 2)
self.set_position(0, 0, width, height)
def anchor_left(self):
width = int(self.desktop.width / 2)
self.set_position(0, 0, width, self.desktop.height)
def get_window_text(handle):
length = GetWindowTextLength(handle)
buff = ctypes.create_unicode_buffer(length + 1)
GetWindowText(handle, buff, length + 1)
return buff.value
@staticmethod
def iter_windows():
windows = []
def enumerate_windows(hwnd, lParam):
windows.append(Window(hwnd))
return True
EnumWindows(EnumWindowsProc(enumerate_windows), 0)
for entry in windows:
yield entry
@staticmethod
def find(name):
windows = list(Window.find_all(name))
if windows:
return windows[0]
return []
@staticmethod
def find_all(name):
def _match_in(title):
return name in title
matcher = _match_in
if isinstance(name, re.Pattern):
regex = re.compile(name)
def _match_re(title):
return regex.match(title)
matcher = _match_re
for wind in Window.iter_windows():
if not wind.visible:
continue
if matcher(wind.title):
yield wind
class Desktop(Window):
def __init__(self):
dsktp = GetDesktopWindow()
super(Desktop, self).__init__(dsktp)
if __name__ == "__main__":
for win in Window.iter_windows():
if win.visible:
print(win.title)
chrome = Window.find(re.compile("^.* - Google Chrome$"))
print(f"{chrome.title}")
print(f"Chrome: {chrome.top} {chrome.left}, {chrome.width} x {chrome.height}")
chrome.bring_to_front()
chrome.anchor_left()