Skip to content
24 changes: 21 additions & 3 deletions comtypes/messageloop.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import ctypes
from ctypes import WinDLL, WinError, byref
from ctypes.wintypes import MSG
from ctypes import POINTER, WinDLL, WinError, byref
from ctypes.wintypes import BOOL, HWND, MSG
from ctypes.wintypes import LPLONG as LRESULT
from typing import TYPE_CHECKING, SupportsIndex

if TYPE_CHECKING:
Expand All @@ -10,12 +11,29 @@

_FilterCallable = Callable[["_CArgObject"], Iterable[Any]] # type: ignore

# PeekMessage options
PM_NOREMOVE = 0x0000
PM_REMOVE = 0x0001
PM_NOYIELD = 0x0002

_user32 = WinDLL("user32")

GetMessage = _user32.GetMessageA
GetMessage.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint, ctypes.c_uint]
GetMessage.argtypes = [POINTER(MSG), HWND, ctypes.c_uint, ctypes.c_uint]
GetMessage.restype = BOOL

TranslateMessage = _user32.TranslateMessage
TranslateMessage.argtypes = [POINTER(MSG)]
TranslateMessage.restype = BOOL

DispatchMessage = _user32.DispatchMessageA
DispatchMessage.argtypes = [POINTER(MSG)]
DispatchMessage.restype = LRESULT

# https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-peekmessagea
PeekMessage = _user32.PeekMessageA
PeekMessage.argtypes = [POINTER(MSG), HWND, ctypes.c_uint, ctypes.c_uint, ctypes.c_uint]
PeekMessage.restype = BOOL


class _MessageLoop:
Expand Down
47 changes: 11 additions & 36 deletions comtypes/test/test_eventinterface.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import unittest as ut
from ctypes import POINTER, Structure, WinDLL, byref, c_long, c_uint, c_ulong
from ctypes.wintypes import BOOL, HWND, LPLONG, UINT
from ctypes import byref
from ctypes.wintypes import MSG

from comtypes.client import CreateObject, GetEvents
from comtypes.messageloop import (
PM_REMOVE,
DispatchMessage,
PeekMessage,
TranslateMessage,
)

# FIXME: External test dependencies like this seem bad. Find a different
# built-in win32 API to use.
Expand Down Expand Up @@ -42,42 +48,11 @@ def DocumentComplete(self, this, *args):
self._events.append("DocumentComplete")


class POINT(Structure):
_fields_ = [("x", c_long), ("y", c_long)]


class MSG(Structure):
_fields_ = [
("hWnd", c_ulong),
("message", c_uint),
("wParam", c_ulong),
("lParam", c_ulong),
("time", c_ulong),
("pt", POINT),
]


def PumpWaitingMessages():
_user32 = WinDLL("user32")

_PeekMessageA = _user32.PeekMessageA
_PeekMessageA.argtypes = [POINTER(MSG), HWND, UINT, UINT, UINT]
_PeekMessageA.restype = BOOL

_TranslateMessage = _user32.TranslateMessage
_TranslateMessage.argtypes = [POINTER(MSG)]
_TranslateMessage.restype = BOOL

LRESULT = LPLONG
_DispatchMessageA = _user32.DispatchMessageA
_DispatchMessageA.argtypes = [POINTER(MSG)]
_DispatchMessageA.restype = LRESULT

msg = MSG()
PM_REMOVE = 0x0001
while _PeekMessageA(byref(msg), 0, 0, 0, PM_REMOVE):
_TranslateMessage(byref(msg))
_DispatchMessageA(byref(msg))
while PeekMessage(byref(msg), 0, 0, 0, PM_REMOVE):
TranslateMessage(byref(msg))
DispatchMessage(byref(msg))


class Test(ut.TestCase):
Expand Down
16 changes: 7 additions & 9 deletions comtypes/test/test_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from _ctypes import COMError
from collections.abc import Iterator
from ctypes import HRESULT, POINTER, OleDLL, WinDLL, byref
from ctypes.wintypes import BOOL, DWORD, HANDLE, HWND, MSG, UINT
from ctypes.wintypes import BOOL, DWORD, HANDLE, MSG
from pathlib import Path
from queue import Queue

Expand All @@ -18,16 +18,16 @@
RegisterInterfaceInGlobal,
RevokeInterfaceFromGlobal,
)
from comtypes.messageloop import DispatchMessage, TranslateMessage
from comtypes.messageloop import (
PM_REMOVE,
DispatchMessage,
PeekMessage,
TranslateMessage,
)
from comtypes.persist import STGM_READ, IPersistFile

_user32 = WinDLL("user32")

# https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-peekmessagea
PeekMessage = _user32.PeekMessageA
PeekMessage.argtypes = [POINTER(MSG), HWND, UINT, UINT, UINT]
PeekMessage.restype = BOOL

# https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-msgwaitformultipleobjects
MsgWaitForMultipleObjects = _user32.MsgWaitForMultipleObjects
MsgWaitForMultipleObjects.restype = DWORD
Expand All @@ -49,8 +49,6 @@

QS_ALLINPUT = 0x04FF # All message types including SendMessage

PM_REMOVE = 0x0001 # Remove message from queue after Peek

APTTYPE_MAINSTA = 3

RPC_E_WRONG_THREAD = -2147417842 # 0x8001010E
Expand Down