def get_actual_rect(hwnd):
"""Gets correct dimensions of a DWM controlled window
"Retrieves the extended frame bounds rectangle in screen space".
Windows 10 reports (technically) incorrect window dimensions,
so this is used to obtain the correct window dimensions.
Args:
hwnd: The handle to the window from which the attribute data is retrieved.
Returns:
A windows RECT structure of the correct window dimensions.
"""
rect = RECT()
DWMWA_EXTENDED_FRAME_BOUNDS = 9
dwmapi.DwmGetWindowAttribute(HWND(hwnd),
DWORD(DWMWA_EXTENDED_FRAME_BOUNDS),
ctypes.byref(rect),
ctypes.sizeof(rect))
# actual_x1 = rect.left
# actual_y1 = rect.top
# actual_x2 = rect.right
# actual_y2 = rect.bottom
# return [actual_x1, actual_y1, actual_x2, actual_y2]
return rect
python类RECT的实例源码
def _set_argtypes(self):
''' Functions arguments. '''
self.MONITORENUMPROC = WINFUNCTYPE(INT, DWORD, DWORD, POINTER(RECT),
DOUBLE)
windll.user32.GetSystemMetrics.argtypes = [INT]
windll.user32.EnumDisplayMonitors.argtypes = [HDC, c_void_p,
self.MONITORENUMPROC,
LPARAM]
windll.user32.GetWindowDC.argtypes = [HWND]
windll.gdi32.CreateCompatibleDC.argtypes = [HDC]
windll.gdi32.CreateCompatibleBitmap.argtypes = [HDC, INT, INT]
windll.gdi32.SelectObject.argtypes = [HDC, HGDIOBJ]
windll.gdi32.BitBlt.argtypes = [HDC, INT, INT, INT, INT, HDC, INT, INT,
DWORD]
windll.gdi32.DeleteObject.argtypes = [HGDIOBJ]
windll.gdi32.GetDIBits.argtypes = [HDC, HBITMAP, UINT, UINT, c_void_p,
POINTER(BITMAPINFO), UINT]
def _set_argtypes(self):
''' Functions arguments. '''
self.MONITORENUMPROC = WINFUNCTYPE(INT, DWORD, DWORD, POINTER(RECT),
DOUBLE)
windll.user32.GetSystemMetrics.argtypes = [INT]
windll.user32.EnumDisplayMonitors.argtypes = [HDC, c_void_p,
self.MONITORENUMPROC,
LPARAM]
windll.user32.GetWindowDC.argtypes = [HWND]
windll.gdi32.CreateCompatibleDC.argtypes = [HDC]
windll.gdi32.CreateCompatibleBitmap.argtypes = [HDC, INT, INT]
windll.gdi32.SelectObject.argtypes = [HDC, HGDIOBJ]
windll.gdi32.BitBlt.argtypes = [HDC, INT, INT, INT, INT, HDC, INT, INT,
DWORD]
windll.gdi32.DeleteObject.argtypes = [HGDIOBJ]
windll.gdi32.GetDIBits.argtypes = [HDC, HBITMAP, UINT, UINT, c_void_p,
POINTER(BITMAPINFO), UINT]
def _set_argtypes(self):
''' Functions arguments. '''
self.MONITORENUMPROC = WINFUNCTYPE(INT, DWORD, DWORD, POINTER(RECT),
DOUBLE)
windll.user32.GetSystemMetrics.argtypes = [INT]
windll.user32.EnumDisplayMonitors.argtypes = [HDC, c_void_p,
self.MONITORENUMPROC,
LPARAM]
windll.user32.GetWindowDC.argtypes = [HWND]
windll.gdi32.CreateCompatibleDC.argtypes = [HDC]
windll.gdi32.CreateCompatibleBitmap.argtypes = [HDC, INT, INT]
windll.gdi32.SelectObject.argtypes = [HDC, HGDIOBJ]
windll.gdi32.BitBlt.argtypes = [HDC, INT, INT, INT, INT, HDC, INT, INT,
DWORD]
windll.gdi32.DeleteObject.argtypes = [HGDIOBJ]
windll.gdi32.GetDIBits.argtypes = [HDC, HBITMAP, UINT, UINT, c_void_p,
POINTER(BITMAPINFO), UINT]
def window__border_rectangle(hwnd):
"""
The outer border size and position of the window
:param hwnd:
:return: a dict with the keys 'x', 'y', 'width', 'height',
'left', 'right', 'top', 'bottom'
"""
rect = wintypes.RECT()
res = windll.user32.GetWindowRect(hwnd, byref(rect))
if res == 0:
raise WinError()
return _rect_to_dict(rect)
def window__client_rectangle(hwnd):
"""
The client-usable space within the border rectangle. Top and Left
are always 0.
:param hwnd:
:return: the rectangle structure.
"""
client_rect = wintypes.RECT()
res = windll.user32.GetClientRect(hwnd, byref(client_rect))
if res == 0:
raise WinError()
return _rect_to_dict(client_rect)
def paint__draw_rect(hdc, pos_x, pos_y, width, height, color):
rect = wintypes.RECT()
rect.left = pos_x
rect.top = pos_y
rect.right = pos_x + width
rect.bottom = pos_y + height
fill_rgb = wintypes.RGB((color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff)
fill_brush = None
try:
fill_brush = windll.gdi32.CreateSolidBrush(fill_rgb)
windll.user32.FillRect(hdc, byref(rect), fill_brush)
finally:
if fill_brush is not None:
_delete_gdi_object(fill_brush)
def paint__draw_text(hdc, hfont, text, pos_x, pos_y, width, height, fg_color, bg_color):
old_hfont = None
try:
old_hfont = windll.gdi32.SelectObject(hdc, hfont)
if fg_color:
fg = wintypes.RGB((fg_color >> 16) & 0xff, (fg_color >> 8) & 0xff, fg_color & 0xff)
windll.gdi32.SetTextColor(hdc, fg)
if bg_color:
bg = wintypes.RGB((bg_color >> 16) & 0xff, (bg_color >> 8) & 0xff, bg_color & 0xff)
windll.gdi32.SetBkColor(hdc, bg)
windll.gdi32.SetBkMode(hdc, OPAQUE)
else:
bg = wintypes.RGB(0, 0, 0)
windll.gdi32.SetBkColor(hdc, bg)
windll.gdi32.SetBkMode(hdc, TRANSPARENT)
rect = wintypes.RECT()
rect.left = pos_x
rect.top = pos_y
rect.right = pos_x + width
rect.bottom = pos_y + height
ret = windll.user32.DrawTextW(
hdc, create_unicode_buffer(text), len(text), byref(rect),
DT_LEFT | DT_TOP | DT_NOPREFIX)
if ret == 0:
raise WinError()
finally:
# To prevent a memory leak
if old_hfont is not None:
windll.gdi32.SelectObject(hdc, old_hfont)
def monitor__find_monitors():
ret = []
def callback(h_monitor, hdc_monitor, lprc_monitor, lParam):
# hMonitor: display monitor handle
# hdcMonitor: device context handle; color attributes + clipping region
# lprcMonitor: RECT structure w/ device-context coordinates.
ret.append({
'monitor_handle': h_monitor,
'device_context_handle': hdc_monitor,
'left': lprc_monitor.contents.left,
'right': lprc_monitor.contents.right,
'top': lprc_monitor.contents.top,
'bottom': lprc_monitor.contents.bottom,
'width': lprc_monitor.contents.right - lprc_monitor.contents.left,
'height': lprc_monitor.contents.bottom - lprc_monitor.contents.top,
'primary': len(ret) == 0,
'index': len(ret),
})
return True
enum_monitor_proc = WINFUNCTYPE(c_bool, POINTER(c_int), POINTER(c_int), POINTER(wintypes.RECT), POINTER(c_int))
if EnumDisplayMonitors(None, None, enum_monitor_proc(callback), None) == 0:
raise Exception("Could not find monitors")
# for i in ret:
# info = POINTER(wintypes.MONITORINFOEX())
# if GetMonitorInfo(i['monitor_handle'], info) != 0:
# i['primary'] = info.contents.dwFlags == MONITORINFOF_PRIMARY
# i['name'] = str(info.contents.szDevice)
return ret
def to_rect(coords):
"""Converts a set of coordinates to a windows RECT
Converts the form [x1, y1, x2, y2] to a windows RECT structure.
Args:
coords: List of coordinates in the form [x1, y1, x2, y2].
Returns:
A windows RECT structure.
"""
rect = ctypes.wintypes.RECT(*coords)
return rect
def enum_display_monitors(self, screen=-1):
''' Get positions of one or more monitors.
Returns a dict with minimal requirements.
'''
if screen == -1:
SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN = 76, 77
SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN = 78, 79
left = windll.user32.GetSystemMetrics(SM_XVIRTUALSCREEN)
right = windll.user32.GetSystemMetrics(SM_CXVIRTUALSCREEN)
top = windll.user32.GetSystemMetrics(SM_YVIRTUALSCREEN)
bottom = windll.user32.GetSystemMetrics(SM_CYVIRTUALSCREEN)
yield ({
b'left': int(left),
b'top': int(top),
b'width': int(right - left),
b'height': int(bottom - top)
})
else:
def _callback(monitor, dc, rect, data):
''' Callback for MONITORENUMPROC() function, it will return
a RECT with appropriate values.
'''
rct = rect.contents
monitors.append({
b'left': int(rct.left),
b'top': int(rct.top),
b'width': int(rct.right - rct.left),
b'height': int(rct.bottom - rct.top)
})
return 1
monitors = []
callback = self.MONITORENUMPROC(_callback)
windll.user32.EnumDisplayMonitors(0, 0, callback, 0)
for mon in monitors:
yield mon
def enum_display_monitors(self, screen=-1):
''' Get positions of one or more monitors.
Returns a dict with minimal requirements.
'''
if screen == -1:
SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN = 76, 77
SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN = 78, 79
left = windll.user32.GetSystemMetrics(SM_XVIRTUALSCREEN)
right = windll.user32.GetSystemMetrics(SM_CXVIRTUALSCREEN)
top = windll.user32.GetSystemMetrics(SM_YVIRTUALSCREEN)
bottom = windll.user32.GetSystemMetrics(SM_CYVIRTUALSCREEN)
yield ({
b'left': int(left),
b'top': int(top),
b'width': int(right - left),
b'height': int(bottom - top)
})
else:
def _callback(monitor, dc, rect, data):
''' Callback for MONITORENUMPROC() function, it will return
a RECT with appropriate values.
'''
rct = rect.contents
monitors.append({
b'left': int(rct.left),
b'top': int(rct.top),
b'width': int(rct.right - rct.left),
b'height': int(rct.bottom - rct.top)
})
return 1
monitors = []
callback = self.MONITORENUMPROC(_callback)
windll.user32.EnumDisplayMonitors(0, 0, callback, 0)
for mon in monitors:
yield mon
def enum_display_monitors(self, screen=-1):
''' Get positions of one or more monitors.
Returns a dict with minimal requirements.
'''
if screen == -1:
SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN = 76, 77
SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN = 78, 79
left = windll.user32.GetSystemMetrics(SM_XVIRTUALSCREEN)
right = windll.user32.GetSystemMetrics(SM_CXVIRTUALSCREEN)
top = windll.user32.GetSystemMetrics(SM_YVIRTUALSCREEN)
bottom = windll.user32.GetSystemMetrics(SM_CYVIRTUALSCREEN)
yield ({
b'left': int(left),
b'top': int(top),
b'width': int(right - left),
b'height': int(bottom - top)
})
else:
def _callback(monitor, dc, rect, data):
''' Callback for MONITORENUMPROC() function, it will return
a RECT with appropriate values.
'''
rct = rect.contents
monitors.append({
b'left': int(rct.left),
b'top': int(rct.top),
b'width': int(rct.right - rct.left),
b'height': int(rct.bottom - rct.top)
})
return 1
monitors = []
callback = self.MONITORENUMPROC(_callback)
windll.user32.EnumDisplayMonitors(0, 0, callback, 0)
for mon in monitors:
yield mon
def create_window__create_borderless_window(func_map):
# Use an inner window, so that we can use the func_map for accessing other functions
# that are OS specific.
# Call out to the answer:
# http://stackoverflow.com/questions/39731497/create-window-without-titlebar-with-resizable-border-and-without-bogus-6px-whit/39735058
# However, the WM_CREATE just doesn't work right - it causes windows to
# be automatically closed, even when 0 is explicitly returned.
def window__create_borderless_window(class_name, title, message_handler, callback_map,
show_on_taskbar=True, always_on_top=False):
margins = MARGINS()
margins.cxLeftWidth = 0
margins.cxRightWidth = 0
margins.cyTopHeight = 0
margins.cyBottomHeight = 0
style_flags = {
'popup', 'visible',
# 'layered', This causes the windows to not show up.
'transparent'
}
if always_on_top:
style_flags.add('topmost')
if not show_on_taskbar:
style_flags.add('tool-window')
def hit_test(hwnd, msg, wparam, lparam):
# We don't have a border, so don't worry about
# border cursor checks.
# pt = wintypes.POINT()
# x in low word, y in the high word
# pt.x = wintypes.DWORD(lparam & 0xffff)
# pt.y = wintypes.DWORD((lparam >> 16) & 0xffff)
# windll.user32.ScreenToClient(hwnd, byref(pt))
# rc = wintypes.RECT()
# windll.user32.GetClientRect(hwnd, byref(rc))
return HTCLIENT
callback_map[WM_NCACTIVATE] = lambda hwnd, msg, wparam, lparam: 0
callback_map[WM_NCCALCSIZE] = lambda hwnd, msg, wparam, lparam: lparam == 0 and 0 or False
callback_map[WM_NCHITTEST] = hit_test
hwnd = func_map['window__create_display_window'](class_name, title, message_handler, style_flags)
# windll.dwmapi.DwmExtendFrameIntoClientArea(hwnd, byref(margins))
return hwnd
return window__create_borderless_window
def up():
global id4, proc, hwnd
mouse = POINT()
user32.GetCursorPos(ctypes.byref(mouse))
hot.removeHotkey(id=id4)
if proc is not None:
proc.terminate()
print("-" * 40)
print_handles("GetForegroundWindow", user32.GetForegroundWindow())
active_window = print_handles("WindowFromPoint", hwnd)
print_handles("GetParent", user32.GetParent(active_window))
ancestor = print_handles(
"GetAncestor", user32.GetAncestor(active_window, 3))
if ancestor:
# GetAncestor is the most correct for our use-case, so prefer it.
active_window = ancestor
rect = RECT()
user32.GetWindowRect(active_window, ctypes.byref(rect))
grid = find_matching_grid(mouse.x, mouse.y)
if grid:
grid = to_rect(grid)
if is_aero_enabled():
arect = get_actual_rect(active_window)
grid.left -= abs(arect.left - rect.left)
grid.top -= abs(arect.top - rect.top)
grid.right += abs(arect.right - rect.right)
grid.bottom += abs(arect.bottom - rect.bottom)
width = grid.right - grid.left
height = grid.bottom - grid.top
print("width: %d height: %d" % (width, height))
HWND_NOTOPMOST = -2
user32.SetWindowPos(active_window, HWND_NOTOPMOST,
grid.left, grid.top, width, height, 0)
user32.SetForegroundWindow(active_window)
proc = None
hwnd = None