Dar*_*kas 6 winapi ctypes pywin32 win32gui python-3.x
我已经google了一段时间,但找不到用于创建和显示窗口的python3 ctypes和Win32 API的简单示例.请指出我的好链接或显示代码.
提前致谢!
Dav*_*nan 10
这对win32gui模块及其朋友win32api和win32con来说最容易实现.没有必要为Windows API编写自己的ctypes包装器.最简单的Petzold风格的应用程序出现如下:
import win32api, win32con, win32gui
class MyWindow:
def __init__(self):
win32gui.InitCommonControls()
self.hinst = win32api.GetModuleHandle(None)
className = 'MyWndClass'
message_map = {
win32con.WM_DESTROY: self.OnDestroy,
}
wc = win32gui.WNDCLASS()
wc.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW
wc.lpfnWndProc = message_map
wc.lpszClassName = className
win32gui.RegisterClass(wc)
style = win32con.WS_OVERLAPPEDWINDOW
self.hwnd = win32gui.CreateWindow(
className,
'My win32api app',
style,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
300,
300,
0,
0,
self.hinst,
None
)
win32gui.UpdateWindow(self.hwnd)
win32gui.ShowWindow(self.hwnd, win32con.SW_SHOW)
def OnDestroy(self, hwnd, message, wparam, lparam):
win32gui.PostQuitMessage(0)
return True
w = MyWindow()
win32gui.PumpMessages()
Run Code Online (Sandbox Code Playgroud)
找到了这个漂亮的小饰品,并花时间让它在 vanilla python 3.4.0 的标准库上工作:(
对于那些希望通过 PyWin32 使用本地程序的人)
http://code.activestate.com/recipes/208699 -calling-windows-api-using-ctypes-and-win32con/
import sys
from ctypes import *
kernel32 = windll.kernel32
user32 = windll.user32
gdi32 = windll.gdi32
NULL = 0
CW_USEDEFAULT = -2147483648
IDI_APPLICATION = 32512
WS_OVERLAPPEDWINDOW = 13565952
CS_HREDRAW = 2
CS_VREDRAW = 1
IDC_ARROW = 32512
WHITE_BRUSH = 0
SW_SHOWNORMAL = 1
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():
global NULL
CreateWindowEx = 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 = CS_HREDRAW | CS_VREDRAW
wndclass.lpfnWndProc = WNDPROC(WndProc)
wndclass.cbClsExtra = wndclass.cbWndExtra = 0
wndclass.hInstance = kernel32.GetModuleHandleA(c_int(NULL))
wndclass.hIcon = user32.LoadIconA(c_int(NULL), c_int(IDI_APPLICATION))
wndclass.hCursor = user32.LoadCursorA(c_int(NULL), c_int(IDC_ARROW))
wndclass.hbrBackground = gdi32.GetStockObject(c_int(WHITE_BRUSH))
wndclass.lpszMenuName = None
wndclass.lpszClassName = b"MainWin"
# Register Window Class
if not user32.RegisterClassA(byref(wndclass)):
raise WinError()
# Create Window
hwnd = CreateWindowEx(0,
wndclass.lpszClassName,
b"Python Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
wndclass.hInstance,
NULL)
# Show Window
user32.ShowWindow(c_int(hwnd), c_int(SW_SHOWNORMAL))
user32.UpdateWindow(c_int(hwnd))
# Pump Messages
msg = MSG()
pMsg = pointer(msg)
NULL = c_int(NULL)
while user32.GetMessageA( pMsg, NULL, 0, 0) != 0:
user32.TranslateMessage(pMsg)
user32.DispatchMessageA(pMsg)
return msg.wParam
WM_PAINT = 15
WM_DESTROY = 2
DT_SINGLELINE = 32
DT_CENTER = 1
DT_VCENTER = 4
def WndProc(hwnd, message, wParam, lParam):
ps = PAINTSTRUCT()
rect = RECT()
if message == WM_PAINT:
hdc = user32.BeginPaint(c_int(hwnd), byref(ps))
user32.GetClientRect(c_int(hwnd), byref(rect))
user32.DrawTextA(c_int(hdc),
b"Python Powered Windows" ,
c_int(-1), byref(rect),
DT_SINGLELINE|DT_CENTER|DT_VCENTER)
user32.EndPaint(c_int(hwnd), byref(ps))
return 0
elif message == WM_DESTROY:
user32.PostQuitMessage(0)
return 0
return user32.DefWindowProcA(c_int(hwnd), c_int(message), c_int(wParam), c_int(lParam))
if __name__=='__main__':
sys.exit(MainWin())
Run Code Online (Sandbox Code Playgroud)

这里是纯粹的ctypes基于 @Tcll 答案的纯版本,也移植到“广泛”API。原始版本无法正确处理 64 位 Python(将句柄转换为 c_int)并且使用 ANSI API,但不再推荐这样做。它还为所有内容声明完整的 argtypes/restype 以帮助捕获编码错误。
正如您所看到的,使用起来更加容易pywin32。
在 Python 2.7 32 位、Python 3.6 64 位和 Python 3.8 32 位上测试。
\n#coding:utf8\nfrom __future__ import unicode_literals\n\nimport sys\nfrom ctypes import *\nfrom ctypes import wintypes as w # ctypes has many pre-defined Windows types\n\ndef errcheck(result,func,args):\n if result is None or result == 0:\n raise WinError(get_last_error())\n return result\n\n# Missing from ctypes.wintypes...\nLRESULT = c_int64\nHCURSOR = c_void_p\n\nWNDPROC = WINFUNCTYPE(LRESULT,w.HWND,w.UINT,w.WPARAM,w.LPARAM)\n\ndef MAKEINTRESOURCEW(x):\n return w.LPCWSTR(x)\n\nclass WNDCLASSW(Structure):\n _fields_ = [(\'style\', w.UINT),\n (\'lpfnWndProc\', WNDPROC),\n (\'cbClsExtra\', c_int),\n (\'cbWndExtra\', c_int),\n (\'hInstance\', w.HINSTANCE),\n (\'hIcon\', w.HICON),\n (\'hCursor\', HCURSOR),\n (\'hbrBackground\', w.HBRUSH),\n (\'lpszMenuName\', w.LPCWSTR),\n (\'lpszClassName\', w.LPCWSTR)]\n\nclass PAINTSTRUCT(Structure):\n _fields_ = [(\'hdc\', w.HDC),\n (\'fErase\', w.BOOL),\n (\'rcPaint\', w.RECT),\n (\'fRestore\', w.BOOL),\n (\'fIncUpdate\', w.BOOL),\n (\'rgbReserved\', w.BYTE * 32)]\n\nkernel32 = WinDLL(\'kernel32\',use_last_error=True)\nkernel32.GetModuleHandleW.argtypes = w.LPCWSTR,\nkernel32.GetModuleHandleW.restype = w.HMODULE\nkernel32.GetModuleHandleW.errcheck = errcheck\n\nuser32 = WinDLL(\'user32\',use_last_error=True)\nuser32.CreateWindowExW.argtypes = w.DWORD,w.LPCWSTR,w.LPCWSTR,w.DWORD,c_int,c_int,c_int,c_int,w.HWND,w.HMENU,w.HINSTANCE,w.LPVOID\nuser32.CreateWindowExW.restype = w.HWND\nuser32.CreateWindowExW.errcheck = errcheck\nuser32.LoadIconW.argtypes = w.HINSTANCE,w.LPCWSTR\nuser32.LoadIconW.restype = w.HICON\nuser32.LoadIconW.errcheck = errcheck\nuser32.LoadCursorW.argtypes = w.HINSTANCE,w.LPCWSTR\nuser32.LoadCursorW.restype = HCURSOR\nuser32.LoadCursorW.errcheck = errcheck\nuser32.RegisterClassW.argtypes = POINTER(WNDCLASSW),\nuser32.RegisterClassW.restype = w.ATOM\nuser32.RegisterClassW.errcheck = errcheck\nuser32.ShowWindow.argtypes = w.HWND,c_int\nuser32.ShowWindow.restype = w.BOOL\nuser32.UpdateWindow.argtypes = w.HWND,\nuser32.UpdateWindow.restype = w.BOOL\nuser32.UpdateWindow.errcheck = errcheck\nuser32.GetMessageW.argtypes = POINTER(w.MSG),w.HWND,w.UINT,w.UINT\nuser32.GetMessageW.restype = w.BOOL\nuser32.TranslateMessage.argtypes = POINTER(w.MSG),\nuser32.TranslateMessage.restype = w.BOOL\nuser32.DispatchMessageW.argtypes = POINTER(w.MSG),\nuser32.DispatchMessageW.restype = LRESULT\nuser32.BeginPaint.argtypes = w.HWND,POINTER(PAINTSTRUCT)\nuser32.BeginPaint.restype = w.HDC\nuser32.BeginPaint.errcheck = errcheck\nuser32.GetClientRect.argtypes = w.HWND,POINTER(w.RECT)\nuser32.GetClientRect.restype = w.BOOL\nuser32.GetClientRect.errcheck = errcheck\nuser32.DrawTextW.argtypes = w.HDC,w.LPCWSTR,c_int,POINTER(w.RECT),w.UINT\nuser32.DrawTextW.restype = c_int\nuser32.EndPaint.argtypes = w.HWND,POINTER(PAINTSTRUCT)\nuser32.EndPaint.restype = w.BOOL\nuser32.PostQuitMessage.argtypes = c_int,\nuser32.PostQuitMessage.restype = None\nuser32.DefWindowProcW.argtypes = w.HWND,w.UINT,w.WPARAM,w.LPARAM\nuser32.DefWindowProcW.restype = LRESULT\n\ngdi32 = WinDLL(\'gdi32\',use_last_error=True)\ngdi32.GetStockObject.argtypes = c_int,\ngdi32.GetStockObject.restype = w.HGDIOBJ\n\nCW_USEDEFAULT = -2147483648\nIDI_APPLICATION = MAKEINTRESOURCEW(32512)\nWS_OVERLAPPEDWINDOW = 13565952\n\nCS_HREDRAW = 2\nCS_VREDRAW = 1\n\nIDC_ARROW = MAKEINTRESOURCEW(32512)\nWHITE_BRUSH = 0\n\nSW_SHOWNORMAL = 1\n\nWM_PAINT = 15\nWM_DESTROY = 2\nDT_SINGLELINE = 32\nDT_CENTER = 1\nDT_VCENTER = 4\n\ndef MainWin():\n # Define Window Class\n wndclass = WNDCLASSW()\n wndclass.style = CS_HREDRAW | CS_VREDRAW\n wndclass.lpfnWndProc = WNDPROC(WndProc)\n wndclass.cbClsExtra = wndclass.cbWndExtra = 0\n wndclass.hInstance = kernel32.GetModuleHandleW(None)\n wndclass.hIcon = user32.LoadIconW(None, IDI_APPLICATION)\n wndclass.hCursor = user32.LoadCursorW(None, IDC_ARROW)\n wndclass.hbrBackground = gdi32.GetStockObject(WHITE_BRUSH)\n wndclass.lpszMenuName = None\n wndclass.lpszClassName = \'MainWin\'\n\n # Register Window Class\n user32.RegisterClassW(byref(wndclass))\n\n # Create Window\n hwnd = user32.CreateWindowExW(0,\n wndclass.lpszClassName,\n \'Python Window\',\n WS_OVERLAPPEDWINDOW,\n CW_USEDEFAULT,\n CW_USEDEFAULT,\n CW_USEDEFAULT,\n CW_USEDEFAULT,\n None,\n None,\n wndclass.hInstance,\n None)\n # Show Window\n user32.ShowWindow(hwnd,SW_SHOWNORMAL)\n user32.UpdateWindow(hwnd)\n\n # Pump Messages\n msg = w.MSG()\n while user32.GetMessageW(byref(msg), None, 0, 0) != 0:\n user32.TranslateMessage(byref(msg))\n user32.DispatchMessageW(byref(msg))\n\n return msg.wParam\n\ndef WndProc(hwnd, message, wParam, lParam):\n ps = PAINTSTRUCT()\n rect = w.RECT()\n\n if message == WM_PAINT:\n hdc = user32.BeginPaint(hwnd,byref(ps))\n user32.GetClientRect(hwnd,byref(rect))\n user32.DrawTextW(hdc,\n \'Python Powered Windows \xe4\xbd\xa0\xe5\xa5\xbd\xe5\x90\x97\xef\xbc\x9f\',\n -1, byref(rect), \n DT_SINGLELINE|DT_CENTER|DT_VCENTER)\n user32.EndPaint(hwnd,byref(ps))\n return 0\n elif message == WM_DESTROY:\n user32.PostQuitMessage(0)\n return 0\n\n return user32.DefWindowProcW(hwnd,message,wParam,lParam)\n\nif __name__==\'__main__\':\n sys.exit(MainWin())\nRun Code Online (Sandbox Code Playgroud)\n\n