Initial commit

This commit is contained in:
Untriex Programming
2021-08-31 22:06:02 +02:00
commit 9b6723e11e
5142 changed files with 1455625 additions and 0 deletions

View File

@@ -0,0 +1,349 @@
# PyGetWindow
# A cross-platform module to find information about the windows on the screen.
# Work in progress
# Useful info:
# https://stackoverflow.com/questions/373020/finding-the-current-active-window-in-mac-os-x-using-python
# https://stackoverflow.com/questions/7142342/get-window-position-size-with-python
# win32 api and ctypes on Windows
# cocoa api and pyobjc on Mac
# Xlib on linux
# Possible Future Features:
# get/click menu (win32: GetMenuItemCount, GetMenuItemInfo, GetMenuItemID, GetMenu, GetMenuItemRect)
__version__ = "0.0.9"
import sys, collections, pyrect
class PyGetWindowException(Exception):
"""
Base class for exceptions raised when PyGetWindow functions
encounter a problem. If PyGetWindow raises an exception that isn't
this class, that indicates a bug in the module.
"""
pass
def pointInRect(x, y, left, top, width, height):
"""Returns ``True`` if the ``(x, y)`` point is within the box described
by ``(left, top, width, height)``."""
return left < x < left + width and top < y < top + height
# NOTE: `Rect` is a named tuple for use in Python, while structs.RECT represents
# the win32 RECT struct. PyRect's Rect class is used for handling changing
# geometry of rectangular areas.
Rect = collections.namedtuple("Rect", "left top right bottom")
Point = collections.namedtuple("Point", "x y")
Size = collections.namedtuple("Size", "width height")
class BaseWindow:
def __init__(self):
pass
def _setupRectProperties(self):
def _onRead(attrName):
r = self._getWindowRect()
self._rect._left = r.left # Setting _left directly to skip the onRead.
self._rect._top = r.top # Setting _top directly to skip the onRead.
self._rect._width = r.right - r.left # Setting _width directly to skip the onRead.
self._rect._height = r.bottom - r.top # Setting _height directly to skip the onRead.
def _onChange(oldBox, newBox):
self.moveTo(newBox.left, newBox.top)
self.resizeTo(newBox.width, newBox.height)
r = self._getWindowRect()
self._rect = pyrect.Rect(r.left, r.top, r.right - r.left, r.bottom - r.top, onChange=_onChange, onRead=_onRead)
def _getWindowRect(self):
raise NotImplementedError
def __str__(self):
r = self._getWindowRect()
width = r.right - r.left
height = r.bottom - r.top
return '<%s left="%s", top="%s", width="%s", height="%s", title="%s">' % (
self.__class__.__qualname__,
r.left,
r.top,
width,
height,
self.title,
)
def close(self):
"""Closes this window. This may trigger "Are you sure you want to
quit?" dialogs or other actions that prevent the window from
actually closing. This is identical to clicking the X button on the
window."""
raise NotImplementedError
def minimize(self):
"""Minimizes this window."""
raise NotImplementedError
def maximize(self):
"""Maximizes this window."""
raise NotImplementedError
def restore(self):
"""If maximized or minimized, restores the window to it's normal size."""
raise NotImplementedError
def activate(self):
"""Activate this window and make it the foreground window."""
raise NotImplementedError
def resizeRel(self, widthOffset, heightOffset):
"""Resizes the window relative to its current size."""
raise NotImplementedError
def resizeTo(self, newWidth, newHeight):
"""Resizes the window to a new width and height."""
raise NotImplementedError
def moveRel(self, xOffset, yOffset):
"""Moves the window relative to its current position."""
raise NotImplementedError
def moveTo(self, newLeft, newTop):
"""Moves the window to new coordinates on the screen."""
raise NotImplementedError
@property
def isMinimized(self):
"""Returns True if the window is currently minimized."""
raise NotImplementedError
@property
def isMaximized(self):
"""Returns True if the window is currently maximized."""
raise NotImplementedError
@property
def isActive(self):
"""Returns True if the window is currently the active, foreground window."""
raise NotImplementedError
@property
def title(self):
"""Returns the window title as a string."""
raise NotImplementedError
@property
def visible(self):
raise NotImplementedError
# Wrappers for pyrect.Rect object's properties:
@property
def left(self):
return self._rect.left
@left.setter
def left(self, value):
# import pdb; pdb.set_trace()
self._rect.left # Run rect's onRead to update the Rect object.
self._rect.left = value
@property
def right(self):
return self._rect.right
@right.setter
def right(self, value):
self._rect.right # Run rect's onRead to update the Rect object.
self._rect.right = value
@property
def top(self):
return self._rect.top
@top.setter
def top(self, value):
self._rect.top # Run rect's onRead to update the Rect object.
self._rect.top = value
@property
def bottom(self):
return self._rect.bottom
@bottom.setter
def bottom(self, value):
self._rect.bottom # Run rect's onRead to update the Rect object.
self._rect.bottom = value
@property
def topleft(self):
return self._rect.topleft
@topleft.setter
def topleft(self, value):
self._rect.topleft # Run rect's onRead to update the Rect object.
self._rect.topleft = value
@property
def topright(self):
return self._rect.topright
@topright.setter
def topright(self, value):
self._rect.topright # Run rect's onRead to update the Rect object.
self._rect.topright = value
@property
def bottomleft(self):
return self._rect.bottomleft
@bottomleft.setter
def bottomleft(self, value):
self._rect.bottomleft # Run rect's onRead to update the Rect object.
self._rect.bottomleft = value
@property
def bottomright(self):
return self._rect.bottomright
@bottomright.setter
def bottomright(self, value):
self._rect.bottomright # Run rect's onRead to update the Rect object.
self._rect.bottomright = value
@property
def midleft(self):
return self._rect.midleft
@midleft.setter
def midleft(self, value):
self._rect.midleft # Run rect's onRead to update the Rect object.
self._rect.midleft = value
@property
def midright(self):
return self._rect.midright
@midright.setter
def midright(self, value):
self._rect.midright # Run rect's onRead to update the Rect object.
self._rect.midright = value
@property
def midtop(self):
return self._rect.midtop
@midtop.setter
def midtop(self, value):
self._rect.midtop # Run rect's onRead to update the Rect object.
self._rect.midtop = value
@property
def midbottom(self):
return self._rect.midbottom
@midbottom.setter
def midbottom(self, value):
self._rect.midbottom # Run rect's onRead to update the Rect object.
self._rect.midbottom = value
@property
def center(self):
return self._rect.center
@center.setter
def center(self, value):
self._rect.center # Run rect's onRead to update the Rect object.
self._rect.center = value
@property
def centerx(self):
return self._rect.centerx
@centerx.setter
def centerx(self, value):
self._rect.centerx # Run rect's onRead to update the Rect object.
self._rect.centerx = value
@property
def centery(self):
return self._rect.centery
@centery.setter
def centery(self, value):
self._rect.centery # Run rect's onRead to update the Rect object.
self._rect.centery = value
@property
def width(self):
return self._rect.width
@width.setter
def width(self, value):
self._rect.width # Run rect's onRead to update the Rect object.
self._rect.width = value
@property
def height(self):
return self._rect.height
@height.setter
def height(self, value):
self._rect.height # Run rect's onRead to update the Rect object.
self._rect.height = value
@property
def size(self):
return self._rect.size
@size.setter
def size(self, value):
self._rect.size # Run rect's onRead to update the Rect object.
self._rect.size = value
@property
def area(self):
return self._rect.area
@area.setter
def area(self, value):
self._rect.area # Run rect's onRead to update the Rect object.
self._rect.area = value
@property
def box(self):
return self._rect.box
@box.setter
def box(self, value):
self._rect.box # Run rect's onRead to update the Rect object.
self._rect.box = value
if sys.platform == "darwin":
# raise NotImplementedError('PyGetWindow currently does not support macOS. If you have Appkit/Cocoa knowledge, please contribute! https://github.com/asweigart/pygetwindow') # TODO - implement mac
from ._pygetwindow_macos import *
Window = MacOSWindow
elif sys.platform == "win32":
from ._pygetwindow_win import (
Win32Window,
getActiveWindow,
getActiveWindowTitle,
getWindowsAt,
getWindowsWithTitle,
getAllWindows,
getAllTitles,
)
Window = Win32Window
else:
raise NotImplementedError(
"PyGetWindow currently does not support Linux. If you have Xlib knowledge, please contribute! https://github.com/asweigart/pygetwindow"
)

View File

@@ -0,0 +1,174 @@
import Quartz
import pygetwindow
def getAllTitles():
"""Returns a list of strings of window titles for all visible windows.
"""
# Source: https://stackoverflow.com/questions/53237278/obtain-list-of-all-window-titles-on-macos-from-a-python-script/53985082#53985082
windows = Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListExcludeDesktopElements | Quartz.kCGWindowListOptionOnScreenOnly, Quartz.kCGNullWindowID)
return ['%s %s' % (win[Quartz.kCGWindowOwnerName], win.get(Quartz.kCGWindowName, '')) for win in windows]
def getActiveWindow():
"""Returns a Window object of the currently active Window."""
# Source: https://stackoverflow.com/questions/5286274/front-most-window-using-cgwindowlistcopywindowinfo
windows = Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListExcludeDesktopElements | Quartz.kCGWindowListOptionOnScreenOnly, Quartz.kCGNullWindowID)
for win in windows:
if win['kCGWindowLayer'] == 0:
return '%s %s' % (win[Quartz.kCGWindowOwnerName], win.get(Quartz.kCGWindowName, '')) # Temporary. For now, we'll just return the title of the active window.
raise Exception('Could not find an active window.') # Temporary hack.
def getWindowsAt(x, y):
windows = Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListExcludeDesktopElements | Quartz.kCGWindowListOptionOnScreenOnly, Quartz.kCGNullWindowID)
matches = []
for win in windows:
w = win['kCGWindowBounds']
if pygetwindow.pointInRect(x, y, w['X'], w['Y'], w['Width'], w['Height']):
matches.append('%s %s' % (win[Quartz.kCGWindowOwnerName], win.get(Quartz.kCGWindowName, '')))
return matches
def activate():
# TEMP - this is not a real api, I'm just using this name to store these notes for now.
# Source: https://stackoverflow.com/questions/7460092/nswindow-makekeyandorderfront-makes-window-appear-but-not-key-or-front?rq=1
# Source: https://stackoverflow.com/questions/4905024/is-it-possible-to-bring-window-to-front-without-taking-focus?rq=1
pass
def getWindowGeometry(title):
# TEMP - this is not a real api, I'm just using this name to stoe these notes for now.
windows = Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListExcludeDesktopElements | Quartz.kCGWindowListOptionOnScreenOnly, Quartz.kCGNullWindowID)
for win in windows:
if title in '%s %s' % (win[Quartz.kCGWindowOwnerName], win.get(Quartz.kCGWindowName, '')):
w = win['kCGWindowBounds']
return (w['X'], w['Y'], w['Width'], w['Height'])
def isVisible(title):
# TEMP - this is not a real api, I'm just using this name to stoe these notes for now.
windows = Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListExcludeDesktopElements | Quartz.kCGWindowListOptionOnScreenOnly, Quartz.kCGNullWindowID)
for win in windows:
if title in '%s %s' % (win[Quartz.kCGWindowOwnerName], win.get(Quartz.kCGWindowName, '')):
return win['kCGWindowAlpha'] != 0.0
def isMinimized():
# TEMP - this is not a real api, I'm just using this name to stoe these notes for now.
# Source: https://stackoverflow.com/questions/10258676/how-to-know-whether-a-window-is-minimised-or-not
# Use the kCGWindowIsOnscreen to check this. Minimized windows are considered to not be on the screen. (But I'm not sure if there are other situations where a window is "off screen".)
# I'm not sure how kCGWindowListOptionOnScreenOnly interferes with this.
pass
# TODO: This class doesn't work yet. I've copied the Win32Window class and will make adjustments as needed here.
class MacOSWindow():
def __init__(self, hWnd):
self._hWnd = hWnd # TODO fix this, this is a LP_c_long insead of an int.
def _onRead(attrName):
r = self._getWindowRect(_hWnd)
self._rect._left = r.left # Setting _left directly to skip the onRead.
self._rect._top = r.top # Setting _top directly to skip the onRead.
self._rect._width = r.right - r.left # Setting _width directly to skip the onRead.
self._rect._height = r.bottom - r.top # Setting _height directly to skip the onRead.
def _onChange(oldBox, newBox):
self.moveTo(newBox.left, newBox.top)
self.resizeTo(newBox.width, newBox.height)
r = self._getWindowRect(_hWnd)
self._rect = pyrect.Rect(r.left, r.top, r.right - r.left, r.bottom - r.top, onChange=_onChange, onRead=_onRead)
def __str__(self):
r = self._getWindowRect(_hWnd)
width = r.right - r.left
height = r.bottom - r.top
return '<%s left="%s", top="%s", width="%s", height="%s", title="%s">' % (self.__class__.__name__, r.left, r.top, width, height, self.title)
def __repr__(self):
return '%s(hWnd=%s)' % (self.__class__.__name__, self._hWnd)
def __eq__(self, other):
return isinstance(other, MacOSWindow) and self._hWnd == other._hWnd
def close(self):
"""Closes this window. This may trigger "Are you sure you want to
quit?" dialogs or other actions that prevent the window from
actually closing. This is identical to clicking the X button on the
window."""
raise NotImplementedError
def minimize(self):
"""Minimizes this window."""
raise NotImplementedError
def maximize(self):
"""Maximizes this window."""
raise NotImplementedError
def restore(self):
"""If maximized or minimized, restores the window to it's normal size."""
raise NotImplementedError
def activate(self):
"""Activate this window and make it the foreground window."""
raise NotImplementedError
def resizeRel(self, widthOffset, heightOffset):
"""Resizes the window relative to its current size."""
raise NotImplementedError
def resizeTo(self, newWidth, newHeight):
"""Resizes the window to a new width and height."""
raise NotImplementedError
def moveRel(self, xOffset, yOffset):
"""Moves the window relative to its current position."""
raise NotImplementedError
def moveTo(self, newLeft, newTop):
"""Moves the window to new coordinates on the screen."""
raise NotImplementedError
@property
def isMinimized(self):
"""Returns True if the window is currently minimized."""
raise NotImplementedError
@property
def isMaximized(self):
"""Returns True if the window is currently maximized."""
raise NotImplementedError
@property
def isActive(self):
"""Returns True if the window is currently the active, foreground window."""
raise NotImplementedError
@property
def title(self):
"""Returns the window title as a string."""
raise NotImplementedError
@property
def visible(self):
raise NotImplementedError

View File

@@ -0,0 +1,351 @@
import ctypes
from ctypes import wintypes # We can't use ctypes.wintypes, we must import wintypes this way.
from pygetwindow import PyGetWindowException, pointInRect, BaseWindow, Rect, Point, Size
NULL = 0 # Used to match the Win32 API value of "null".
# These FORMAT_MESSAGE_ constants are used for FormatMesage() and are
# documented at https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-formatmessage#parameters
FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100
FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200
# These SW_ constants are used for ShowWindow() and are documented at
# https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-showwindow#parameters
SW_MINIMIZE = 6
SW_MAXIMIZE = 3
SW_HIDE = 0
SW_SHOW = 5
SW_RESTORE = 9
# SetWindowPos constants:
HWND_TOP = 0
# Window Message constants:
WM_CLOSE = 0x0010
# This ctypes structure is for a Win32 POINT structure,
# which is documented here: http://msdn.microsoft.com/en-us/library/windows/desktop/dd162805(v=vs.85).aspx
# The POINT structure is used by GetCursorPos().
class POINT(ctypes.Structure):
_fields_ = [("x", ctypes.c_long),
("y", ctypes.c_long)]
enumWindows = ctypes.windll.user32.EnumWindows
enumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.c_int, ctypes.POINTER(ctypes.c_int))
getWindowText = ctypes.windll.user32.GetWindowTextW
getWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
isWindowVisible = ctypes.windll.user32.IsWindowVisible
class RECT(ctypes.Structure):
"""A nice wrapper of the RECT structure.
Microsoft Documentation:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd162897(v=vs.85).aspx
"""
_fields_ = [('left', ctypes.c_long),
('top', ctypes.c_long),
('right', ctypes.c_long),
('bottom', ctypes.c_long)]
def _getAllTitles():
# This code taken from https://sjohannes.wordpress.com/2012/03/23/win32-python-getting-all-window-titles/
# A correction to this code (for enumWindowsProc) is here: http://makble.com/the-story-of-lpclong
titles = []
def foreach_window(hWnd, lParam):
if isWindowVisible(hWnd):
length = getWindowTextLength(hWnd)
buff = ctypes.create_unicode_buffer(length + 1)
getWindowText(hWnd, buff, length + 1)
titles.append((hWnd, buff.value))
return True
enumWindows(enumWindowsProc(foreach_window), 0)
return titles
def _formatMessage(errorCode):
"""A nice wrapper for FormatMessageW(). TODO
Microsoft Documentation:
https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-formatmessagew
Additional information:
https://stackoverflow.com/questions/18905702/python-ctypes-and-mutable-buffers
https://stackoverflow.com/questions/455434/how-should-i-use-formatmessage-properly-in-c
"""
lpBuffer = wintypes.LPWSTR()
ctypes.windll.kernel32.FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
errorCode,
0, # dwLanguageId
ctypes.cast(ctypes.byref(lpBuffer), wintypes.LPWSTR),
0, # nSize
NULL)
msg = lpBuffer.value.rstrip()
ctypes.windll.kernel32.LocalFree(lpBuffer) # Free the memory allocated for the error message's buffer.
return msg
def _raiseWithLastError():
"""A helper function that raises PyGetWindowException using the error
information from GetLastError() and FormatMessage()."""
errorCode = ctypes.windll.kernel32.GetLastError()
raise PyGetWindowException('Error code from Windows: %s - %s' % (errorCode, _formatMessage(errorCode)))
def getActiveWindow():
"""Returns a Window object of the currently active (focused) Window."""
hWnd = ctypes.windll.user32.GetForegroundWindow()
if hWnd == 0:
# TODO - raise error instead
return None # Note that this function doesn't use GetLastError().
else:
return Win32Window(hWnd)
def getActiveWindowTitle():
"""Returns a string of the title text of the currently active (focused) Window."""
# NOTE - This function isn't threadsafe because it relies on a global variable. I don't use nonlocal because I want this to work on Python 2.
global activeWindowTitle
activeWindowHwnd = ctypes.windll.user32.GetForegroundWindow()
if activeWindowHwnd == 0:
# TODO - raise error instead
return None # Note that this function doesn't use GetLastError().
def foreach_window(hWnd, lParam):
global activeWindowTitle
if hWnd == activeWindowHwnd:
length = getWindowTextLength(hWnd)
buff = ctypes.create_unicode_buffer(length + 1)
getWindowText(hWnd, buff, length + 1)
activeWindowTitle = buff.value
return True
enumWindows(enumWindowsProc(foreach_window), 0)
return activeWindowTitle
def getWindowsAt(x, y):
"""Returns a list of Window objects whose windows contain the point ``(x, y)``.
* ``x`` (int, optional): The x position of the window(s).
* ``y`` (int, optional): The y position of the window(s)."""
windowsAtXY = []
for window in getAllWindows():
if pointInRect(x, y, window.left, window.top, window.width, window.height):
windowsAtXY.append(window)
return windowsAtXY
def getWindowsWithTitle(title):
"""Returns a list of Window objects that substring match ``title`` in their title text."""
hWndsAndTitles = _getAllTitles()
windowObjs = []
for hWnd, winTitle in hWndsAndTitles:
if title.upper() in winTitle.upper(): # do a case-insensitive match
windowObjs.append(Win32Window(hWnd))
return windowObjs
def getAllTitles():
"""Returns a list of strings of window titles for all visible windows.
"""
return [window.title for window in getAllWindows()]
def getAllWindows():
"""Returns a list of Window objects for all visible windows.
"""
windowObjs = []
def foreach_window(hWnd, lParam):
if ctypes.windll.user32.IsWindowVisible(hWnd) != 0:
windowObjs.append(Win32Window(hWnd))
return True
enumWindows(enumWindowsProc(foreach_window), 0)
return windowObjs
class Win32Window(BaseWindow):
def __init__(self, hWnd):
self._hWnd = hWnd # TODO fix this, this is a LP_c_long insead of an int.
self._setupRectProperties()
def _getWindowRect(self):
"""A nice wrapper for GetWindowRect(). TODO
Syntax:
BOOL GetWindowRect(
HWND hWnd,
LPRECT lpRect
);
Microsoft Documentation:
https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowrect
"""
rect = RECT()
result = ctypes.windll.user32.GetWindowRect(self._hWnd, ctypes.byref(rect))
if result != 0:
return Rect(rect.left, rect.top, rect.right, rect.bottom)
else:
_raiseWithLastError()
def __repr__(self):
return '%s(hWnd=%s)' % (self.__class__.__name__, self._hWnd)
def __eq__(self, other):
return isinstance(other, Win32Window) and self._hWnd == other._hWnd
def close(self):
"""Closes this window. This may trigger "Are you sure you want to
quit?" dialogs or other actions that prevent the window from
actually closing. This is identical to clicking the X button on the
window."""
result = ctypes.windll.user32.PostMessageA(self._hWnd, WM_CLOSE, 0, 0)
if result == 0:
_raiseWithLastError()
def minimize(self):
"""Minimizes this window."""
ctypes.windll.user32.ShowWindow(self._hWnd, SW_MINIMIZE)
def maximize(self):
"""Maximizes this window."""
ctypes.windll.user32.ShowWindow(self._hWnd, SW_MAXIMIZE)
def restore(self):
"""If maximized or minimized, restores the window to it's normal size."""
ctypes.windll.user32.ShowWindow(self._hWnd, SW_RESTORE)
def show(self):
"""If hidden or showing, shows the window on screen and in title bar."""
ctypes.windll.user32.ShowWindow(self._hWnd,SW_SHOW)
def hide(self):
"""If hidden or showing, hides the window from screen and title bar."""
ctypes.windll.user32.ShowWindow(self._hWnd,SW_HIDE)
def activate(self):
"""Activate this window and make it the foreground (focused) window."""
result = ctypes.windll.user32.SetForegroundWindow(self._hWnd)
if result == 0:
_raiseWithLastError()
def resize(self, widthOffset, heightOffset):
"""Resizes the window relative to its current size."""
result = ctypes.windll.user32.SetWindowPos(self._hWnd, HWND_TOP, self.left, self.top, self.width + widthOffset, self.height + heightOffset, 0)
if result == 0:
_raiseWithLastError()
resizeRel = resize # resizeRel is an alias for the resize() method.
def resizeTo(self, newWidth, newHeight):
"""Resizes the window to a new width and height."""
result = ctypes.windll.user32.SetWindowPos(self._hWnd, HWND_TOP, self.left, self.top, newWidth, newHeight, 0)
if result == 0:
_raiseWithLastError()
def move(self, xOffset, yOffset):
"""Moves the window relative to its current position."""
result = ctypes.windll.user32.SetWindowPos(self._hWnd, HWND_TOP, self.left + xOffset, self.top + yOffset, self.width, self.height, 0)
if result == 0:
_raiseWithLastError()
moveRel = move # moveRel is an alias for the move() method.
def moveTo(self, newLeft, newTop):
"""Moves the window to new coordinates on the screen."""
result = ctypes.windll.user32.SetWindowPos(self._hWnd, HWND_TOP, newLeft, newTop, self.width, self.height, 0)
if result == 0:
_raiseWithLastError()
@property
def isMinimized(self):
"""Returns ``True`` if the window is currently minimized."""
return ctypes.windll.user32.IsIconic(self._hWnd) != 0
@property
def isMaximized(self):
"""Returns ``True`` if the window is currently maximized."""
return ctypes.windll.user32.IsZoomed(self._hWnd) != 0
@property
def isActive(self):
"""Returns ``True`` if the window is currently the active, foreground window."""
return getActiveWindow() == self
@property
def title(self):
"""Returns the window title as a string."""
textLenInCharacters = ctypes.windll.user32.GetWindowTextLengthW(self._hWnd)
stringBuffer = ctypes.create_unicode_buffer(textLenInCharacters + 1) # +1 for the \0 at the end of the null-terminated string.
ctypes.windll.user32.GetWindowTextW(self._hWnd, stringBuffer, textLenInCharacters + 1)
# TODO it's ambiguous if an error happened or the title text is just empty. Look into this later.
return stringBuffer.value
@property
def visible(self):
"""Return ``True`` if the window is currently visible."""
return isWindowVisible(self._hWnd)
def cursor():
"""Returns the current xy coordinates of the mouse cursor as a two-integer
tuple by calling the GetCursorPos() win32 function.
Returns:
(x, y) tuple of the current xy coordinates of the mouse cursor.
"""
cursor = POINT()
ctypes.windll.user32.GetCursorPos(ctypes.byref(cursor))
return Point(x=cursor.x, y=cursor.y)
def resolution():
"""Returns the width and height of the screen as a two-integer tuple.
Returns:
(width, height) tuple of the screen size, in pixels.
"""
return Size(width=ctypes.windll.user32.GetSystemMetrics(0), height=ctypes.windll.user32.GetSystemMetrics(1))
'''
def displayWindowsUnderMouse(xOffset=0, yOffset=0):
"""This function is meant to be run from the command line. It will
automatically display the location and RGB of the mouse cursor."""
print('Press Ctrl-C to quit.')
if xOffset != 0 or yOffset != 0:
print('xOffset: %s yOffset: %s' % (xOffset, yOffset))
resolution = size()
try:
while True:
# Get and print the mouse coordinates.
x, y = position()
positionStr = 'X: ' + str(x - xOffset).rjust(4) + ' Y: ' + str(y - yOffset).rjust(4)
# TODO - display windows under the mouse
sys.stdout.write(positionStr)
sys.stdout.write('\b' * len(positionStr))
sys.stdout.flush()
except KeyboardInterrupt:
sys.stdout.write('\n')
sys.stdout.flush()
'''