Skip to content

Instantly share code, notes, and snippets.

@mozurin
Created December 1, 2020 13:49
Show Gist options
  • Save mozurin/ff7b3b218fe09332d815e794a2ade29f to your computer and use it in GitHub Desktop.
Save mozurin/ff7b3b218fe09332d815e794a2ade29f to your computer and use it in GitHub Desktop.
# Python WM_KEYDOWN / WM_KEYUP message checker based on following CreateWindow
# example gist:
# https://gist.github.com/mouseroot/6128651
# (I lost my Spy++ binary...)
from ctypes import *
from ctypes.wintypes import *
WNDPROCTYPE = WINFUNCTYPE(c_int, HWND, c_uint, WPARAM, LPARAM)
WS_EX_APPWINDOW = 0x40000
WS_OVERLAPPEDWINDOW = 0xcf0000
WS_CAPTION = 0xc00000
SW_SHOWNORMAL = 1
SW_SHOW = 5
CS_HREDRAW = 2
CS_VREDRAW = 1
CW_USEDEFAULT = 0x80000000
WM_DESTROY = 2
WHITE_BRUSH = 0
class WNDCLASSEX(ctypes.Structure):
_fields_ = [
('cbSize', c_uint),
('style', c_uint),
('lpfnWndProc', WNDPROCTYPE),
('cbClsExtra', c_int),
('cbWndExtra', c_int),
('hInstance', HANDLE),
('hIcon', HANDLE),
('hCursor', HANDLE),
('hBrush', HANDLE),
('lpszMenuName', LPCWSTR),
('lpszClassName', LPCWSTR),
('hIconSm', HANDLE),
]
windll.user32.DefWindowProcW.argtypes = (HWND, c_uint, WPARAM, LPARAM)
WM_KEYDOWN = 0x0100
WM_KEYUP = 0x0101
def window_procedure(h_wnd, msg, w_param, lParam):
if msg == WM_DESTROY:
windll.user32.PostQuitMessage(0)
elif msg == 0x0100:
print(
'WM_KEYDOWN: nVirtkey=%04x, cRepeat=%04x, scanCode=%02x, fExtended=%s' % (
w_param,
lParam & 0x0000ffff,
(lParam & 0x00ff0000) >> 16,
bool(lParam & 0x01000000),
)
)
elif msg == 0x0101:
print(
'WM_KEYUP: nVirtkey=%04x, cRepeat=%04x, scanCode=%02x, fExtended=%s' % (
w_param,
lParam & 0x0000ffff,
(lParam & 0x00ff0000) >> 16,
bool(lParam & 0x01000000),
)
)
else:
return windll.user32.DefWindowProcW(h_wnd, msg, w_param, lParam)
return 0
def main():
WndProc = WNDPROCTYPE(window_procedure)
hInst = windll.kernel32.GetModuleHandleW(0)
wclassName = 'My Python Win32 Class'
wname = 'My message test window'
wndClass = WNDCLASSEX()
wndClass.cbSize = sizeof(WNDCLASSEX)
wndClass.style = CS_HREDRAW | CS_VREDRAW
wndClass.lpfnWndProc = WndProc
wndClass.cbClsExtra = 0
wndClass.cbWndExtra = 0
wndClass.hInstance = hInst
wndClass.hIcon = 0
wndClass.hCursor = 0
wndClass.hBrush = windll.gdi32.GetStockObject(WHITE_BRUSH)
wndClass.lpszMenuName = 0
wndClass.lpszClassName = wclassName
wndClass.hIconSm = 0
regRes = windll.user32.RegisterClassExW(byref(wndClass))
hWnd = windll.user32.CreateWindowExW(
0,
wclassName,
wname,
WS_OVERLAPPEDWINDOW | WS_CAPTION,
CW_USEDEFAULT,
CW_USEDEFAULT,
300,
300,
0,
0,
hInst,
0
)
if not hWnd:
print('Failed to create window')
exit(-1)
windll.user32.ShowWindow(hWnd, SW_SHOW)
windll.user32.UpdateWindow(hWnd)
msg = MSG()
lpmsg = pointer(msg)
print('Ready')
while windll.user32.GetMessageW(lpmsg, 0, 0, 0) != 0:
windll.user32.TranslateMessage(lpmsg)
windll.user32.DispatchMessageW(lpmsg)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment