下面就是整MVC例子的源码:
#windows应用程序 #开发人员:蔡军生(QQ:9073204) 深圳 2014-9-24 #使用类来描述 from ctypes import * from ctypes.wintypes import * 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 MK_LBUTTON = 0x0001 MK_RBUTTON = 0x0002 MK_SHIFT = 0x0004 MK_CONTROL = 0x0008 MK_MBUTTON = 0x0010 WM_NULL = 0 WM_DESTROY = 2 WM_NCCREATE = 0x0081 WM_PAINT = 0x000F WM_MOUSEMOVE = 0x0200 WM_LBUTTONDOWN = 0x0201 WM_LBUTTONUP = 0x0202 WM_CAPTURECHANGED = 0x0215 WHITE_BRUSH = 0 GWL_USERDATA = -21 IDC_ARROW = 32512 WNDPROCTYPE = WINFUNCTYPE(c_int, HWND, c_uint, WPARAM, LPARAM) #定义窗口类结构 class WNDCLASSEX(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)] #定义创建窗口的参数结构 class CREATESTRUCTW(Structure): _fields_ = [("lpCreateParams", LPVOID), ("hInstance", HANDLE), ("hMenu", HMENU), ("hwndParent", HWND), ("cy", c_int), ("cx", c_int), ("y", c_int), ("x", c_int), ("style", LONG), ("lpszName", LPCWSTR), ("lpszClass", LPCWSTR), ("dwExStyle", DWORD)] #定义窗口绘图结构 class PAINTSTRUCT(Structure): _fields_ = [('hdc', c_int), ('fErase', c_int), ('rcPaint', RECT), ('fRestore', c_int), ('fIncUpdate', c_int), ('rgbReserved', c_wchar * 32)] #窗口类 class Window: def __init__(self, hWnd): self.hWnd = hWnd def Display(self, cmdShow): windll.user32.ShowWindow(self.hWnd, cmdShow) windll.user32.UpdateWindow(self.hWnd) def CaptureMouse(self): windll.user32.SetCapture(self.hWnd) def ReleaseMouse(self): windll.user32.ReleaseCapture() def HasCapture(self): return False def IsCtrl(self, wParam): return (wParam & MK_CONTROL) != 0 def IsShift(self, wParam): return (wParam & MK_SHIFT) != 0 def IsLButton(self, wParam): return (wParam & MK_LBUTTON) != 0 def IsMButton(self, wParam): return (wParam & MK_MBUTTON) != 0 def IsRButton(self, wParam): return (wParam & MK_RBUTTON) != 0 #窗口类型注册类 class WinClassMaker: def __init__(self, wndProc, className, hInst): self.wndClass = WNDCLASSEX() self.wndClass.cbSize = sizeof(WNDCLASSEX) self.wndClass.style = CS_HREDRAW | CS_VREDRAW self.wndClass.lpfnWndProc = wndProc self.wndClass.cbClsExtra = 0 self.wndClass.cbWndExtra = 0 self.wndClass.hInstance = hInst self.wndClass.hIcon = 0 self.wndClass.hCursor = windll.user32.LoadCursorW(0, IDC_ARROW) self.wndClass.hBrush = windll.gdi32.GetStockObject(WHITE_BRUSH) self.wndClass.lpszMenuName = 0 self.wndClass.lpszClassName = className self.wndClass.hIconSm = 0 def Register(self): return windll.user32.RegisterClassExW(byref(self.wndClass)) #创建窗口 class WinMaker: def __init__(self, className, hInst): self.className = className self.hInst = hInst self.style = WS_OVERLAPPEDWINDOW | WS_CAPTION self.exStyle = 0 self.x = CW_USEDEFAULT self.y = 0 self.width = CW_USEDEFAULT self.height = 0 self.hWndParent = HWND(0) self.hMenu = HWND(0) self.wndCreatData = c_void_p(0) def Create(self, wndCreatData, title): self.hWnd = windll.user32.CreateWindowExW( self.exStyle, self.className, title, self.style, self.x, self.y, self.width, self.height, self.hWndParent, self.hMenu, self.hInst, py_object(wndCreatData)) if not self.hWnd: print('Failed to create window') exit(0) return self.hWnd class Controller: def __init__(self): self.hWnd = HWND() self.msgfun = { WM_DESTROY: self.OnDestroy, WM_PAINT: self.OnPaint, WM_MOUSEMOVE: self.OnMouseMove, WM_LBUTTONDOWN: self.OnLButtonDown, WM_LBUTTONUP: self.OnLButtonUp, WM_CAPTURECHANGED: self.OnCaptureChanged, WM_NULL: self.OnNull #最后一个函数处理,方便在前面插入函数 } def SetWnd(self, hWnd): self.hWnd = hWnd def GetWnd(self): return self.hWnd def GetPoint(self, lParam): pt = POINT() pt.x = lParam & 0xFFFF pt.y = (lParam>>16) & 0xFFFF return pt def MyWndProc(self, hWnd, Msg, wParam, lParam): if Msg in self.msgfun and self.msgfun[Msg](wParam, lParam): return 0 else: return windll.user32.DefWindowProcW(hWnd, Msg, wParam, lParam) def OnNull(self, wParam, lParam): pass return False def OnDestroy(self, wParam, lParam): windll.user32.PostQuitMessage(0) print('OnDestroy') return True def OnPaint(self, wParam, lParam): pass return False def OnMouseMove(self, wParam, lParam): pass return False def OnLButtonDown(self, wParam, lParam): pass return False def OnLButtonUp(self, wParam, lParam): pass return False def OnCaptureChanged(self, wParam, lParam): pass return False #窗口消息处理回调函数 def PyWndProc(hWnd, Msg, wParam, lParam): pyCtrl = windll.user32.GetWindowLongW(hWnd, GWL_USERDATA) if Msg == WM_NCCREATE: creatstructw = cast(lParam, POINTER(CREATESTRUCTW)).contents pyCtrl = creatstructw.lpCreateParams windll.user32.SetWindowLongW(hWnd, GWL_USERDATA, pyCtrl) #获取控制类对象 ctrl = cast(pyCtrl, py_object).value ctrl.SetWnd(hWnd) if pyCtrl: #获取控制类对象 ctrl = cast(pyCtrl, py_object).value return ctrl.MyWndProc(hWnd, Msg, wParam, lParam) else: return windll.user32.DefWindowProcW(hWnd, Msg, wParam, lParam) #画布 class Canvas: def __init__(self, hdc): self.hdc = hdc def Gethdc(self): return self.hdc def SetPixel(self, x, y, color): windll.gdi32.SetPixel(self.hdc, x, y, color) def MoveTo(self, x, y): windll.gdi32.MoveToEx(self.hdc, x, y, 0) def LineTo(self, x, y): windll.gdi32.LineTo(self.hdc, x, y) def Line(self, x1, y1, x2, y2): windll.gdi32.MoveToEx(self.hdc, x1, y1, 0) windll.gdi32.LineTo(self.hdc, x2, y2) def Text(self, x, y, text): windll.gdi32.TextOutW(self.hdc ,x, y, text, len(text)) def RGB(self, r, g, b): r = r & 0xFF g = g & 0xFF b = b & 0xFF return (b << 16) | (g << 8) | r class PaintCanvas(Canvas): """用于OnPaint消息处理""" def __init__(self, hWnd): self.hWnd = hWnd self.paint = PAINTSTRUCT() hdc = windll.user32.BeginPaint(self.hWnd, byref(self.paint)) Canvas.__init__(self, hdc) def __del__(self): windll.user32.EndPaint(self.hWnd, byref(self.paint)) class UpdateCanvas(Canvas): """用于更新窗口""" def __init__(self, hWnd): hdc = windll.user32.GetDC(hWnd) Canvas.__init__(self, hdc) self.hWnd = hWnd def __del__(self): windll.user32.ReleaseDC(self.hWnd, self.hdc) #画笔 class Pen: def __init__(self, penstyle, width, color): self.hpe = windll.gdi32.CreatePen(penstyle, width, color) def __del__(self): windll.gdi32.DeleteObject(self.hpe) def Gethpe(self): return self.hpe class Holder: def __init__(self, hdc, hobj): self.hdc = hdc self.old = windll.gdi32.SelectObject(hdc, hobj) def __del__(self): windll.gdi32.SelectObject(self.hdc, self.old) #MVC类 #模型类 class Model: def __init__(self): self.ptList = [] self.maxList = 2000 def AddPoint(self, x, y, isStart): if len(self.ptList) > self.maxList: self.ptList.remove(0) #以元组的方式保存到列表 self.ptList.append((x,y,isStart)) def GetPoint(self): return self.ptList #视图类 class View: def __init__(self): self.x = 0 self.y = 0 def Paint(self, canvas, ptList): pen = Pen(0, 0, canvas.RGB(255, 0, 0)) penhold = Holder(canvas.Gethdc(), pen.Gethpe()) self.PrintPos(canvas, self.x, self.y) for pt in ptList: if pt[2]: canvas.MoveTo(pt[0], pt[1]) else: canvas.LineTo(pt[0], pt[1]) def PrintPos(self, canvas, x, y): self.x = x self.y = y strOut = u'Mouse: %04d, %04d' % (x, y) canvas.Text(0, 0, strOut) def MoveTo(self, canvas, x, y, isVisible): if isVisible: pen = Pen(0, 0, canvas.RGB(255, 0, 0)) penhold = Holder(canvas.Gethdc(), pen.Gethpe()) canvas.Line(self.x, self.y, x, y) self.PrintPos(canvas, x, y) #控制类 class CtrlAll(Controller): def __init__(self): Controller.__init__(self) #调用基类构造方法 self.model = Model() self.view = View() self.win = Window(self.GetWnd()) def OnPaint(self, wParam, lParam): paint = PaintCanvas(self.GetWnd()) self.view.Paint(paint, self.model.GetPoint()) return True def OnMouseMove(self, wParam, lParam): paint = UpdateCanvas(self.GetWnd()) pt = self.GetPoint(lParam) if self.win.IsLButton(wParam): self.model.AddPoint(pt.x, pt.y, False) self.view.MoveTo(paint, pt.x, pt.y, True) else: self.view.PrintPos(paint, pt.x, pt.y) return True def OnLButtonDown(self, wParam, lParam): self.win.CaptureMouse() paint = UpdateCanvas(self.GetWnd()) pt = self.GetPoint(lParam) self.view.MoveTo(paint, pt.x, pt.y, False) self.model.AddPoint(pt.x, pt.y, True) return True def OnLButtonUp(self, wParam, lParam): self.win.ReleaseMouse() return True #主函数入口 def main(): #程序实例句柄 hInst = windll.kernel32.GetModuleHandleW(None) WndProc = WNDPROCTYPE(PyWndProc) #窗口类名称 className = u'ShenzhenCai' #窗口标题 wname = u'MVC' #创建窗口类型 winClass = WinClassMaker(WndProc, className, hInst) winClass.Register() #构造窗口对象 maker = WinMaker(className, hInst) #控制类 ctrl = CtrlAll() #创建窗口 win = Window(maker.Create(ctrl, wname)) #创建显示 win.Display(SW_SHOW) #消息循环 msg = MSG() lpmsg = pointer(msg) print('Entering message loop') while windll.user32.GetMessageW(lpmsg, 0, 0, 0) != 0: windll.user32.TranslateMessage(lpmsg) windll.user32.DispatchMessageW(lpmsg) print('done.') if __name__ == "__main__": print( "Win32 Application in python" ) main()