Fix Win32 ctypes issues: wintypes aliases, DrawTextW belongs to user32, drop FillRect (use class brush), NULL ptr for EnumDisplayMonitors

Verified on Windows: module imports and enum_monitor_rects() returns correct
device-coordinate monitor rects.
This commit is contained in:
Hermes Agent committed 2026-09-16 16:28:23 +02:00
1 parent 0e88bf62f5
commit d6e83565c1
1 file changed
+27 -30
+27 -30
View File
@@ -104,11 +104,18 @@ if sys.platform == "win32":
TRANSPARENT = 1
DEFAULT_GUI_FONT = 17
WNDPROC = ctypes.WINFUNCTYPE(wt.LRESULT, wt.HWND, wt.UINT, wt.WPARAM, wt.LPARAM)
LRESULT = ctypes.c_int64
HMONITOR = ctypes.c_void_p
HHOOK = ctypes.c_void_p
HCURSOR = ctypes.c_void_p
ULONG_PTR = ctypes.c_void_p
UINT_PTR = ctypes.c_void_p
WNDPROC = ctypes.WINFUNCTYPE(LRESULT, wt.HWND, wt.UINT, wt.WPARAM, wt.LPARAM)
MONITORENUMPROC = ctypes.WINFUNCTYPE(
wt.BOOL, wt.HMONITOR, wt.HDC, ctypes.POINTER(wt.RECT), wt.LPARAM
wt.BOOL, HMONITOR, wt.HDC, ctypes.POINTER(wt.RECT), wt.LPARAM
)
HOOKPROC = ctypes.WINFUNCTYPE(wt.LRESULT, ctypes.c_int, wt.WPARAM, wt.LPARAM)
HOOKPROC = ctypes.WINFUNCTYPE(LRESULT, ctypes.c_int, wt.WPARAM, wt.LPARAM)
class WNDCLASSEXW(ctypes.Structure):
_fields_ = [
@@ -119,7 +126,7 @@ if sys.platform == "win32":
("cbWndExtra", wt.INT),
("hInstance", wt.HINSTANCE),
("hIcon", wt.HICON),
("hCursor", wt.HCURSOR),
("hCursor", HCURSOR),
("hbrBackground", wt.HBRUSH),
("lpszMenuName", wt.LPCWSTR),
("lpszClassName", wt.LPCWSTR),
@@ -142,7 +149,7 @@ if sys.platform == "win32":
("scanCode", wt.DWORD),
("flags", wt.DWORD),
("time", wt.DWORD),
("dwExtraInfo", wt.ULONG_PTR),
("dwExtraInfo", ULONG_PTR),
]
# --- prototypes (64-bit safe) ---
@@ -161,9 +168,9 @@ if sys.platform == "win32":
user32.UpdateWindow.restype = wt.BOOL
user32.SetWindowPos.argtypes = [wt.HWND, wt.HWND, wt.INT, wt.INT, wt.INT, wt.INT, wt.UINT]
user32.SetWindowPos.restype = wt.BOOL
user32.SetTimer.argtypes = [wt.HWND, wt.UINT_PTR, wt.UINT, ctypes.c_void_p]
user32.SetTimer.restype = wt.UINT_PTR
user32.KillTimer.argtypes = [wt.HWND, wt.UINT_PTR]
user32.SetTimer.argtypes = [wt.HWND, UINT_PTR, wt.UINT, ctypes.c_void_p]
user32.SetTimer.restype = UINT_PTR
user32.KillTimer.argtypes = [wt.HWND, UINT_PTR]
user32.KillTimer.restype = wt.BOOL
user32.GetClientRect.argtypes = [wt.HWND, ctypes.POINTER(wt.RECT)]
user32.GetClientRect.restype = wt.BOOL
@@ -182,24 +189,20 @@ if sys.platform == "win32":
user32.DispatchMessageW.argtypes = [ctypes.POINTER(wt.MSG)]
user32.DispatchMessageW.restype = wt.LONG
user32.SetWindowsHookExW.argtypes = [wt.INT, HOOKPROC, wt.HINSTANCE, wt.DWORD]
user32.SetWindowsHookExW.restype = wt.HHOOK
user32.CallNextHookEx.argtypes = [wt.HHOOK, ctypes.c_int, wt.WPARAM, wt.LPARAM]
user32.CallNextHookEx.restype = wt.LRESULT
user32.UnhookWindowsHookEx.argtypes = [wt.HHOOK]
user32.SetWindowsHookExW.restype = HHOOK
user32.CallNextHookEx.argtypes = [HHOOK, ctypes.c_int, wt.WPARAM, wt.LPARAM]
user32.CallNextHookEx.restype = LRESULT
user32.UnhookWindowsHookEx.argtypes = [HHOOK]
user32.UnhookWindowsHookEx.restype = wt.BOOL
user32.DestroyWindow.argtypes = [wt.HWND]
user32.DestroyWindow.restype = wt.BOOL
user32.ShowCursor.argtypes = [wt.BOOL]
user32.ShowCursor.restype = wt.INT
user32.DefWindowProcW.argtypes = [wt.HWND, wt.UINT, wt.WPARAM, wt.LPARAM]
user32.DefWindowProcW.restype = wt.LRESULT
user32.DefWindowProcW.restype = LRESULT
user32.SetProcessDPIAware.argtypes = []
user32.SetProcessDPIAware.restype = wt.BOOL
gdi32.CreateSolidBrush.argtypes = [wt.COLORREF]
gdi32.CreateSolidBrush.restype = wt.HBRUSH
gdi32.FillRect.argtypes = [wt.HDC, ctypes.POINTER(wt.RECT), wt.HBRUSH]
gdi32.FillRect.restype = wt.INT
gdi32.DeleteObject.argtypes = [wt.HGDIOBJ]
gdi32.DeleteObject.restype = wt.BOOL
gdi32.SetTextColor.argtypes = [wt.HDC, wt.COLORREF]
gdi32.SetTextColor.restype = wt.COLORREF
@@ -209,8 +212,8 @@ if sys.platform == "win32":
gdi32.GetStockObject.restype = wt.HGDIOBJ
gdi32.SelectObject.argtypes = [wt.HDC, wt.HGDIOBJ]
gdi32.SelectObject.restype = wt.HGDIOBJ
gdi32.DrawTextW.argtypes = [wt.HDC, wt.LPCWSTR, wt.INT, ctypes.POINTER(wt.RECT), wt.UINT]
gdi32.DrawTextW.restype = wt.INT
user32.DrawTextW.argtypes = [wt.HDC, wt.LPCWSTR, wt.INT, ctypes.POINTER(wt.RECT), wt.UINT]
user32.DrawTextW.restype = wt.INT
kernel32.GetModuleHandleW.argtypes = [wt.LPCWSTR]
kernel32.GetModuleHandleW.restype = wt.HINSTANCE
kernel32.GetLastError.argtypes = []
@@ -229,28 +232,23 @@ if sys.platform == "win32":
rects.append((r.left, r.top, r.right, r.bottom))
return True
user32.EnumDisplayMonitors(0, 0, MONITORENUMPROC(cb), 0)
user32.EnumDisplayMonitors(None, None, MONITORENUMPROC(cb), 0)
return rects
def _wndproc(hwnd, msg, wparam, lparam):
if msg == WM_ERASEBKGND:
return 1
global _hint_active
if msg == WM_PAINT:
# Background (black) is erased by DefWindowProc via the class brush.
ps = PAINTSTRUCT()
hdc = user32.BeginPaint(hwnd, ctypes.byref(ps))
rect = wt.RECT()
user32.GetClientRect(hwnd, ctypes.byref(rect))
brush = gdi32.CreateSolidBrush(0x000000)
gdi32.FillRect(hdc, ctypes.byref(rect), brush)
gdi32.DeleteObject(brush)
if _hint_active:
gdi32.SetTextColor(hdc, 0xFFFFFF)
gdi32.SetBkMode(hdc, TRANSPARENT)
font = gdi32.GetStockObject(DEFAULT_GUI_FONT)
old = gdi32.SelectObject(hdc, font)
buf = ctypes.create_unicode_buffer(_hint_text)
gdi32.DrawTextW(
hdc, buf, -1, ctypes.byref(rect),
user32.DrawTextW(
hdc, buf, -1, ctypes.byref(ps.rcPaint),
DT_CENTER | DT_VCENTER | DT_SINGLELINE,
)
if old:
@@ -258,7 +256,6 @@ if sys.platform == "win32":
user32.EndPaint(hwnd, ctypes.byref(ps))
return 0
if msg == WM_TIMER:
global _hint_active
_hint_active = False
user32.KillTimer(hwnd, 1)
for h in _hwnds: