我已经google了一段时间但是找不到用于创建和显示窗口的python3 ctypes和Win32 API的简单示例。请在这里指出好的链接或显示代码。
提前致谢!
答案 0 :(得分:7)
这对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()
答案 1 :(得分:2)
找到了这个漂亮的小饰品,花了一些时间让它只能在标准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())
答案 2 :(得分:2)
这是一个基于 @Tcll 答案的纯 ctypes
版本,也移植到“宽”API。原始版本没有正确处理 64 位 Python(将句柄转换为 c_int)并且使用了 ANSI API,不再推荐使用。它还为所有内容声明了完整的 argtypes/restype,以帮助捕获编码错误。
如您所见,使用 pywin32
更容易。
在 Python 2.7 32 位、Python 3.6 64 位和 Python 3.8 32 位上测试。
#coding:utf8
from __future__ import unicode_literals
import sys
from ctypes import *
from ctypes import wintypes as w # ctypes has many pre-defined Windows types
def errcheck(result,func,args):
if result is None or result == 0:
raise WinError(get_last_error())
return result
# Missing from ctypes.wintypes...
LRESULT = c_int64
HCURSOR = c_void_p
WNDPROC = WINFUNCTYPE(LRESULT,w.HWND,w.UINT,w.WPARAM,w.LPARAM)
def MAKEINTRESOURCEW(x):
return w.LPCWSTR(x)
class WNDCLASSW(Structure):
_fields_ = [('style', w.UINT),
('lpfnWndProc', WNDPROC),
('cbClsExtra', c_int),
('cbWndExtra', c_int),
('hInstance', w.HINSTANCE),
('hIcon', w.HICON),
('hCursor', HCURSOR),
('hbrBackground', w.HBRUSH),
('lpszMenuName', w.LPCWSTR),
('lpszClassName', w.LPCWSTR)]
class PAINTSTRUCT(Structure):
_fields_ = [('hdc', w.HDC),
('fErase', w.BOOL),
('rcPaint', w.RECT),
('fRestore', w.BOOL),
('fIncUpdate', w.BOOL),
('rgbReserved', w.BYTE * 32)]
kernel32 = WinDLL('kernel32',use_last_error=True)
kernel32.GetModuleHandleW.argtypes = w.LPCWSTR,
kernel32.GetModuleHandleW.restype = w.HMODULE
kernel32.GetModuleHandleW.errcheck = errcheck
user32 = WinDLL('user32',use_last_error=True)
user32.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
user32.CreateWindowExW.restype = w.HWND
user32.CreateWindowExW.errcheck = errcheck
user32.LoadIconW.argtypes = w.HINSTANCE,w.LPCWSTR
user32.LoadIconW.restype = w.HICON
user32.LoadIconW.errcheck = errcheck
user32.LoadCursorW.argtypes = w.HINSTANCE,w.LPCWSTR
user32.LoadCursorW.restype = HCURSOR
user32.LoadCursorW.errcheck = errcheck
user32.RegisterClassW.argtypes = POINTER(WNDCLASSW),
user32.RegisterClassW.restype = w.ATOM
user32.RegisterClassW.errcheck = errcheck
user32.ShowWindow.argtypes = w.HWND,c_int
user32.ShowWindow.restype = w.BOOL
user32.UpdateWindow.argtypes = w.HWND,
user32.UpdateWindow.restype = w.BOOL
user32.UpdateWindow.errcheck = errcheck
user32.GetMessageW.argtypes = POINTER(w.MSG),w.HWND,w.UINT,w.UINT
user32.GetMessageW.restype = w.BOOL
user32.TranslateMessage.argtypes = POINTER(w.MSG),
user32.TranslateMessage.restype = w.BOOL
user32.DispatchMessageW.argtypes = POINTER(w.MSG),
user32.DispatchMessageW.restype = LRESULT
user32.BeginPaint.argtypes = w.HWND,POINTER(PAINTSTRUCT)
user32.BeginPaint.restype = w.HDC
user32.BeginPaint.errcheck = errcheck
user32.GetClientRect.argtypes = w.HWND,POINTER(w.RECT)
user32.GetClientRect.restype = w.BOOL
user32.GetClientRect.errcheck = errcheck
user32.DrawTextW.argtypes = w.HDC,w.LPCWSTR,c_int,POINTER(w.RECT),w.UINT
user32.DrawTextW.restype = c_int
user32.EndPaint.argtypes = w.HWND,POINTER(PAINTSTRUCT)
user32.EndPaint.restype = w.BOOL
user32.PostQuitMessage.argtypes = c_int,
user32.PostQuitMessage.restype = None
user32.DefWindowProcW.argtypes = w.HWND,w.UINT,w.WPARAM,w.LPARAM
user32.DefWindowProcW.restype = LRESULT
gdi32 = WinDLL('gdi32',use_last_error=True)
gdi32.GetStockObject.argtypes = c_int,
gdi32.GetStockObject.restype = w.HGDIOBJ
CW_USEDEFAULT = -2147483648
IDI_APPLICATION = MAKEINTRESOURCEW(32512)
WS_OVERLAPPEDWINDOW = 13565952
CS_HREDRAW = 2
CS_VREDRAW = 1
IDC_ARROW = MAKEINTRESOURCEW(32512)
WHITE_BRUSH = 0
SW_SHOWNORMAL = 1
WM_PAINT = 15
WM_DESTROY = 2
DT_SINGLELINE = 32
DT_CENTER = 1
DT_VCENTER = 4
def MainWin():
# Define Window Class
wndclass = WNDCLASSW()
wndclass.style = CS_HREDRAW | CS_VREDRAW
wndclass.lpfnWndProc = WNDPROC(WndProc)
wndclass.cbClsExtra = wndclass.cbWndExtra = 0
wndclass.hInstance = kernel32.GetModuleHandleW(None)
wndclass.hIcon = user32.LoadIconW(None, IDI_APPLICATION)
wndclass.hCursor = user32.LoadCursorW(None, IDC_ARROW)
wndclass.hbrBackground = gdi32.GetStockObject(WHITE_BRUSH)
wndclass.lpszMenuName = None
wndclass.lpszClassName = 'MainWin'
# Register Window Class
user32.RegisterClassW(byref(wndclass))
# Create Window
hwnd = user32.CreateWindowExW(0,
wndclass.lpszClassName,
'Python Window',
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
None,
None,
wndclass.hInstance,
None)
# Show Window
user32.ShowWindow(hwnd,SW_SHOWNORMAL)
user32.UpdateWindow(hwnd)
# Pump Messages
msg = w.MSG()
while user32.GetMessageW(byref(msg), None, 0, 0) != 0:
user32.TranslateMessage(byref(msg))
user32.DispatchMessageW(byref(msg))
return msg.wParam
def WndProc(hwnd, message, wParam, lParam):
ps = PAINTSTRUCT()
rect = w.RECT()
if message == WM_PAINT:
hdc = user32.BeginPaint(hwnd,byref(ps))
user32.GetClientRect(hwnd,byref(rect))
user32.DrawTextW(hdc,
'Python Powered Windows 你好吗?',
-1, byref(rect),
DT_SINGLELINE|DT_CENTER|DT_VCENTER)
user32.EndPaint(hwnd,byref(ps))
return 0
elif message == WM_DESTROY:
user32.PostQuitMessage(0)
return 0
return user32.DefWindowProcW(hwnd,message,wParam,lParam)
if __name__=='__main__':
sys.exit(MainWin())