It is easy to call Windows API dlls using the ctypes module with win32con defining the constant values for message identifiers and parameter flags. The demo code shows a simple but complete application that registers a window class and a Python WndProc callback function, creates the window and pumps messages.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | import win32con
import sys
from ctypes import *
WNDPROC = WINFUNCTYPE(c_long, c_int, c_uint, c_int, c_int)
class WNDCLASS(Structure):
_fields_ = [('style', c_uint),
('lpfnWndProc', WNDPROC),
('cbClsExtra', c_int),
('cbWndExtra', c_int),
('hInstance', c_int),
('hIcon', c_int),
('hCursor', c_int),
('hbrBackground', c_int),
('lpszMenuName', c_char_p),
('lpszClassName', c_char_p)]
class RECT(Structure):
_fields_ = [('left', c_long),
('top', c_long),
('right', c_long),
('bottom', c_long)]
class PAINTSTRUCT(Structure):
_fields_ = [('hdc', c_int),
('fErase', c_int),
('rcPaint', RECT),
('fRestore', c_int),
('fIncUpdate', c_int),
('rgbReserved', c_char * 32)]
class POINT(Structure):
_fields_ = [('x', c_long),
('y', c_long)]
class MSG(Structure):
_fields_ = [('hwnd', c_int),
('message', c_uint),
('wParam', c_int),
('lParam', c_int),
('time', c_int),
('pt', POINT)]
def ErrorIfZero(handle):
if handle == 0:
raise WinError
else:
return handle
def MainWin():
CreateWindowEx = windll.user32.CreateWindowExA
CreateWindowEx.argtypes = [c_int, c_char_p, c_char_p, c_int, c_int, c_int, c_int, c_int, c_int, c_int, c_int, c_int]
CreateWindowEx.restype = ErrorIfZero
# Define Window Class
wndclass = WNDCLASS()
wndclass.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW
wndclass.lpfnWndProc = WNDPROC(WndProc)
wndclass.cbClsExtra = wndclass.cbWndExtra = 0
wndclass.hInstance = windll.kernel32.GetModuleHandleA(c_int(win32con.NULL))
wndclass.hIcon = windll.user32.LoadIconA(c_int(win32con.NULL), c_int(win32con.IDI_APPLICATION))
wndclass.hCursor = windll.user32.LoadCursorA(c_int(win32con.NULL), c_int(win32con.IDC_ARROW))
wndclass.hbrBackground = windll.gdi32.GetStockObject(c_int(win32con.WHITE_BRUSH))
wndclass.lpszMenuName = None
wndclass.lpszClassName = "MainWin"
# Register Window Class
if not windll.user32.RegisterClassA(byref(wndclass)):
raise WinError()
# Create Window
hwnd = CreateWindowEx(0,
wndclass.lpszClassName,
"Python Window",
win32con.WS_OVERLAPPEDWINDOW,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
win32con.NULL,
win32con.NULL,
wndclass.hInstance,
win32con.NULL)
# Show Window
windll.user32.ShowWindow(c_int(hwnd), c_int(win32con.SW_SHOWNORMAL))
windll.user32.UpdateWindow(c_int(hwnd))
# Pump Messages
msg = MSG()
pMsg = pointer(msg)
NULL = c_int(win32con.NULL)
while windll.user32.GetMessageA( pMsg, NULL, 0, 0) != 0:
windll.user32.TranslateMessage(pMsg)
windll.user32.DispatchMessageA(pMsg)
return msg.wParam
def WndProc(hwnd, message, wParam, lParam):
ps = PAINTSTRUCT()
rect = RECT()
if message == win32con.WM_PAINT:
hdc = windll.user32.BeginPaint(c_int(hwnd), byref(ps))
windll.user32.GetClientRect(c_int(hwnd), byref(rect))
windll.user32.DrawTextA(c_int(hdc),
"Python Powered Windows" ,
c_int(-1), byref(rect),
win32con.DT_SINGLELINE|win32con.DT_CENTER|win32con.DT_VCENTER)
windll.user32.EndPaint(c_int(hwnd), byref(ps))
return 0
elif message == win32con.WM_DESTROY:
windll.user32.PostQuitMessage(0)
return 0
return windll.user32.DefWindowProcA(c_int(hwnd), c_int(message), c_int(wParam), c_int(lParam))
if __name__=='__main__':
sys.exit(MainWin())
|
The code runs on Windows98 and WindowsNT (see Comment below).
ctypes lives here: http://starship.python.net/crew/theller/ctypes/
win32con is part of win32all and lives here: http://starship.python.net/crew/mhammond/
Download
Copy to clipboard
Code runs unchanged on NT family. This code runs unchanged under the NT family of operating systems. There is no need to change it to the unicode versions of functions/structures, although it would be possible.
Discussion changed. Thanks!