def OnPaint(self, event): ps = PAINTSTRUCT() ps.fErase = True hdc = self.BeginPaint(ps) if WINVER >= 0x0400: gdi.SetGraphicsMode(hdc, gdi.GM_ADVANCED) gdi.SetMapMode(hdc, gdi.MM_ANISOTROPIC) rect = self.GetClientRect() self.Drawing_a_Shaded_Rectangle(hdc, rect) gdi.SelectObject(hdc, gdi.GetStockObject(gdi.DC_PEN)) gdi.SetDCPenColor(hdc, gdi.RGB(00, 0xff, 00)) gdi.SelectObject(hdc, gdi.GetStockObject(gdi.DC_BRUSH)) gdi.SetDCBrushColor(hdc, gdi.RGB(00, 00, 0xff)) gdi.PolyPolyline(hdc, self.pt, self.pts, self.set_size) self.EndPaint(ps)
class MyWindow(Window): _window_title_ = __doc__ _window_background_ = gdi.GetStockObject(gdi.WHITE_BRUSH) _window_class_style_ = CS_HREDRAW | CS_VREDRAW rgbCurrent = 0 # initial color selection cc = CHOOSECOLOR() # common dialog box structure acrCustClr = (COLORREF * 16)() # array of custom colors ZeroMemory(cc, sizeof(CHOOSECOLOR)) cc.lStructSize = sizeof(CHOOSECOLOR) cc.lpCustColors = cast(acrCustClr, LPCOLORREF) cc.rgbResult = rgbCurrent cc.Flags = CC_FULLOPEN | CC_RGBINIT if ChooseColor(cc): rgbCurrent = cc.rgbResult def OnPaint(self, event): ps = PAINTSTRUCT() hdc = self.BeginPaint(ps) rc = self.GetClientRect() gdi.SetTextColor(hdc, self.rgbCurrent) msg = 'Choosed color is %s' % hex(self.rgbCurrent) gdi.TextOut(hdc, rc.width / 2 - 80, rc.height / 2, msg, len(msg)) self.EndPaint(ps) msg_handler(WM_PAINT)(OnPaint) def OnDestroy(self, event): PostQuitMessage(NULL) msg_handler(WM_DESTROY)(OnDestroy)
class track_bar(Window): _window_style_ = WS_VISIBLE | WS_CHILD _window_style_ex_ = WS_EX_STATICEDGE _window_background_ = gdi.GetStockObject(gdi.LTGRAY_BRUSH) def __init__(self, *args, **kwargs): self.form = kwargs.pop('form', None) if not self.form: MessageBox('WARNING', 'form parameter must be filled') Window.__init__(self, *args, **kwargs) caption_pos = RECT(0, 0, self.clientRect.width, self.clientRect.height / 3) self.caption = comctl.StaticText(title=kwargs['title'] or '', rcPos=caption_pos, parent=self) tb_pos = RECT(0, caption_pos.height, self.clientRect.width, self.clientRect.height) self.tb = trackbar.TrackBar(rcPos=tb_pos, parent=self) self.current_position = self.tb.GetPos() self.tb.OnScroll = self.OnScroll def SetRange(self, min=0, max=0): self.tb.SetRange(min, max) def SetPos(self, position=0): self.tb.SetPos(position) self.current_position = position def OnScroll(self, event): position = self.tb.GetPos() if self.current_position != position: self.current_position = position title = self.caption.GetText() if 'Recursion Levels' in title: self.form.fc.maxLevels = position self.caption.SetText(self.form.FMT_RECURSION % self.form.fc.maxLevels) elif 'Bend Angle' in title: self.form.fc.initBendAngle = position - 60 self.caption.SetText(self.form.FMT_BEND_ANGLE % self.form.fc.initBendAngle) elif 'Branch Angle' in title: self.form.fc.initBranchAngle = position self.caption.SetText(self.form.FMT_BRANCH_ANGLE % self.form.fc.initBranchAngle) elif 'Trunk Ratio' in title: self.form.fc.trunkRatio = position / 100.0 self.caption.SetText(self.form.FMT_TRUNK_RATIO % self.form.fc.trunkRatio) elif 'Branch Ratio' in title: self.form.fc.branchRatio = position / 10.0 self.caption.SetText(self.form.FMT_BRANCH_RATIO % self.form.fc.branchRatio) elif 'Height Scale' in title: self.form.fc.heightScale = position / 10.0 self.caption.SetText(self.form.FMT_HEIGHT_SCALE % self.form.fc.heightScale) self.form.fc.InvalidateRect(self.form.fc.GetClientRect(), True)
class main_window(Window): _window_title_ = __doc__ _window_background_ = gdi.GetStockObject(gdi.LTGRAY_BRUSH) _window_icon_ = _window_icon_sm_ = Icon(lpIconName=IDI_ASTERISK) color_background = gdiplus.MakeARGB(255, 155, 155, 255) #~ grid = live_grid_2d(cellw = 64, cellh = 64, size_point = 5.0) grid = live_grid_2d() #is_draw_points = False def OnDestroy(self, event): application.Quit() def OnPaint(self, event): ps = PAINTSTRUCT() ps.fErase = True hdc = self.BeginPaint(ps) rect = self.GetClientRect() status, graphics = gdiplus.GdipCreateFromHDC(hdc) status = gdiplus.GdipGraphicsClear(graphics, self.color_background) self.grid.draw(graphics) gdiplus.GdipDeleteGraphics(graphics) self.EndPaint(ps) def OnSize(self, event): self.grid.screen_size = POINT(*event.size) self.grid.create_cells() self.grid.create_lines() def OnCreate(self, event): if not self.grid.path_lines: status, self.grid.path_lines = gdiplus.GdipCreatePath() if not self.grid.path_points: status, self.grid.path_points = gdiplus.GdipCreatePath() self.grid.create_brush_cell() self.grid.create_pen_cell() self.grid.create_pen_lines() self.grid.create_pen_points() def OnMouseMove(self, event): self.mouse_event = True self.grid.current_point = GET_POINT_LPARAM(event.lParam) if self.grid.is_cell_changed(): hdc = self.GetDC() status, graphics = gdiplus.GdipCreateFromHDC(hdc) clip_rect = self.grid.current_cell + self.grid.old_cell status = gdiplus.GdipSetClipRectI(graphics, clip_rect.left, clip_rect.top, clip_rect.width, clip_rect.height, gdiplus.CombineModeReplace) status = gdiplus.GdipGraphicsClear(graphics, self.color_background) self.grid.draw(graphics) gdiplus.GdipDeleteGraphics(graphics) self.ReleaseDC(hdc) msg_handler(WM_DESTROY)(OnDestroy) msg_handler(WM_PAINT)(OnPaint) msg_handler(WM_SIZE)(OnSize) msg_handler(WM_MOUSEMOVE)(OnMouseMove) msg_handler(WM_CREATE)(OnCreate)
class ClientForm(Window): '''A class representing client window with child windows. This form can be send to other window, for example on notebook(tab control) page.''' _window_style_ = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS _window_style_ex_ = WS_EX_CLIENTEDGE _window_background_ = gdi.GetStockObject(gdi.LTGRAY_BRUSH) #~ _window_dbg_msg_ = True #~ enum_child_proc = winuser.WNDENUMPROC(EnumChildProc) _childs_ = [] def __init__(self, *args, **kwargs): Window.__init__(self, *args, **kwargs) self.m_interceptor = self.Intercept(self.GetParent(), self._msg_map_) self.enum_child_proc = WNDENUMPROC(self.EnumChildProc) #~ def dispose(self): #~ self.m_interceptor.dispose() #~ del self.m_interceptor #~ del self._childs_ def add(self, wnd): self._childs_.append(wnd) def EnumChildProc(self, hWnd, lParam): 'must be custom replaced as valid' x, y = GET_XY_LPARAM(lParam) rc = RECT() GetClientRect(hWnd, byref(rc)) #~ parent_rc = self.GetClientRect() child.MoveWindow(rc.left, rc.top, x, y, True) #ShowWindow(hWnd, SW_SHOW) return True def DoLayout(self, size): #~ if not hasattr(self, 'enum_child_proc'): #~ self.enum_child_proc = WNDENUMPROC(self.EnumChildProc) #~ if not winuser.EnumChildWindows(self.handle, self.enum_child_proc, size): #~ print(FormatError()) rc = self.GetClientRect() pl, pt, pw, ph = rc.left, rc.top, rc.width, rc.height for wnd, wrc in self._childs_: l, t, w, h = wrc[0] + pl, wrc[1] + pt, wrc[2], wrc[3] if w <= 0: w = pw - l - 5 if h <= 0: h = 20 wnd.MoveWindow(l, t, w, h, True) #~ wnd.ShowWindow(SW_SHOW) def OnSize(self, event): if len(self._childs_): self.DoLayout(event.lParam) msg_handler(WM_SIZE)(OnSize)
def __init__(self, *args, **kwargs): comctl.TabControl.__init__(self, *args, **kwargs) hfnt = gdi.GetStockObject(gdi.DEFAULT_GUI_FONT) SendMessage(self.handle, WM_SETFONT, hfnt, 0) #intercept msgs tabctrl sends to parent in order to detect current #tab changes: self.m_interceptor = self.Intercept(self.GetParent(), self._msg_map2_) #remove the default CS_HREDRAW and CS_VREDRAW class styles from #tab ctrl, these produce much flicker! #may produce some artifacts, anybody got a solution? clsStyle = self.GetClassLong(GCL_STYLE) clsStyle &= ~CS_HREDRAW clsStyle &= ~CS_VREDRAW self.SetClassLong(GCL_STYLE, clsStyle)
class CrossWindow(Window): _window_style_ = WS_VISIBLE | WS_CHILD _window_style_ex_ = 0 _window_background_ = gdi.GetStockObject(gdi.WHITE_BRUSH) #make windows automatically invalidate window on resize, forces repaint of client area: _window_class_style_ = CS_HREDRAW | CS_VREDRAW #@msg_handler(WM_PAINT) #python 2.4 style decorator def OnPaint(self, event): ps = PAINTSTRUCT() hdc = self.BeginPaint(ps) rc = self.GetClientRect() gdi.LineTo(hdc, rc.width, rc.height) gdi.MoveToEx(hdc, rc.width, 0, None) gdi.LineTo(hdc, 0, rc.height) self.EndPaint(ps) msg_handler(WM_PAINT)(OnPaint) #python 2.3 style decorator
class MyWindow(Window): _window_title_ = "Hello World" _window_background_ = gdi.GetStockObject(gdi.WHITE_BRUSH) _window_class_style_ = CS_HREDRAW | CS_VREDRAW #@msg_handler(WM_PAINT) #python 2.4 style decorator def OnPaint(self, event): ps = PAINTSTRUCT() hdc = self.BeginPaint(ps) rc = self.GetClientRect() msg = "Hello World" gdi.TextOut(hdc, rc.width / 2, rc.height / 2, msg, len(msg)) self.EndPaint(ps) msg_handler(WM_PAINT)(OnPaint) #python 2.3 style decorator def OnDestroy(self, event): PostQuitMessage(NULL) msg_handler(WM_DESTROY)(OnDestroy)
class main_window(Window): _window_title_ = __doc__ _window_background_ = gdi.GetStockObject(gdi.LTGRAY_BRUSH) _window_icon_ = _window_icon_sm_ = Icon(lpIconName=IDI_ASTERISK) #~ def timer(self, hwnd, uMsg, idEvent, dwTime): #~ print hwnd, uMsg, idEvent, dwTime def OnDestroy(self, event): application.Quit() def OnPaint(self, event): ps = PAINTSTRUCT() ps.fErase = True hdc = self.BeginPaint(ps) rect = self.GetClientRect() self.Drawing_a_Shaded_Rectangle(hdc, rect) status, graphics = gdiplus.GdipCreateFromHDC(hdc) status, pen = gdiplus.GdipCreatePen1( gdiplus.MakeARGB(100, randint(0, 255), randint(0, 255), randint(0, 255)), 30.0) status = gdiplus.GdipDrawLineI(graphics, pen, 0, 0, rect.width, rect.height) status = gdiplus.GdipDrawLineI(graphics, pen, rect.width, 0, 0, rect.height) points = [(rect.width / 2, 0), (rect.width / 2, rect.height), (0, rect.height), (0, rect.height / 2), (rect.width, rect.height / 2)] lines = (POINT * len(points))(*points) status = gdiplus.GdipDrawLinesI(graphics, pen, lines, len(lines)) x, y = rect.width / 3, rect.height / 3 status = gdiplus.GdipDrawEllipseI(graphics, pen, x, y, x, y) status = gdiplus.GdipDrawRectangleI(graphics, pen, rect.left, rect.top, rect.right, rect.bottom) self.EndPaint(ps) def OnTimer(self, event): self.InvalidateRect(self.GetClientRect(), False) #~ self.UpdateWindow() msg_handler(WM_DESTROY)(OnDestroy) msg_handler(WM_PAINT)(OnPaint) msg_handler(WM_TIMER)(OnTimer) def Drawing_a_Shaded_Rectangle(self, hdc, rc): vert = (gdi.TRIVERTEX * 2)() gRect = gdi.GRADIENT_RECT() vert[0].x = 0 vert[0].y = 0 vert[0].Red = randint(0x0000, 0xffff) vert[0].Green = randint(0x0000, 0xffff) vert[0].Blue = randint(0x0000, 0xffff) vert[0].Alpha = 0x8000 vert[1].x = rc.width vert[1].y = rc.height vert[1].Red = randint(0x0000, 0xffff) vert[1].Green = randint(0x0000, 0xffff) vert[1].Blue = randint(0x0000, 0xffff) vert[1].Alpha = 0x8000 gRect.UpperLeft = 0 gRect.LowerRight = 1 gdi.GradientFill(hdc, vert, 2, byref(gRect), 1, gdi.GRADIENT_FILL_RECT_H)
class main_window(form.Form): _window_title_ = __doc__ _window_background_ = gdi.GetStockObject(gdi.LTGRAY_BRUSH) _window_icon_ = _window_icon_sm_ = Icon(lpIconName=IDI_ASTERISK) color_background = gdiplus.MakeARGB(255, 155, 155, 255) grid = live_grid_2d(cellw=64, cellh=64, size_point=5.0) current_operation = OPERATION_EMPTY color_active_cell_paste = grid.color_active_cell current_open_dir = getcwd() current_open_filter_index = 1 _form_menu_ = [ (MF_POPUP, "&File", [(MF_STRING, "&New Grid\tCtrl+N", form.ID_NEW), (MF_STRING, "&Open Image\tCtrl+O", form.ID_OPEN), (MF_SEPARATOR, ), (MF_STRING, "&Exit", form.ID_EXIT)]), (MF_POPUP, "&Edit", [(MF_STRING, "&Undo\tCtrl+Z", form.ID_UNDO), (MF_STRING, "&Redo\tCtrl+Y", form.ID_REDO), (MF_SEPARATOR, ), (MF_STRING, "Cu&t\tCtrl+X", form.ID_CUT), (MF_STRING, "&Copy\tCtrl+C", form.ID_COPY), (MF_STRING, "&Paste\tCtrl+V", form.ID_PASTE), (MF_STRING, "&Delete\tDel", form.ID_CLEAR), (MF_SEPARATOR, ), (MF_STRING, "Select &All\tCtrl+A", form.ID_SELECTALL)]) ] def OnDestroy(self, event): application.Quit() def OnPaint(self, event): ps = PAINTSTRUCT() ps.fErase = True hdc = self.BeginPaint(ps) rect = self.GetClientRect() status, graphics = gdiplus.GdipCreateFromHDC(hdc) status = gdiplus.GdipGraphicsClear(graphics, self.color_background) self.grid.draw(graphics) gdiplus.GdipDeleteGraphics(graphics) self.EndPaint(ps) def OnSize(self, event): self.grid.screen_size = POINT(*event.size) self.grid.create_cells() self.grid.create_lines() def OnCreate(self, event): if not self.grid.path_lines: status, self.grid.path_lines = gdiplus.GdipCreatePath() if not self.grid.path_points: status, self.grid.path_points = gdiplus.GdipCreatePath() self.grid.create_brush_cell() self.grid.create_pen_cell() self.grid.create_pen_lines() self.grid.create_pen_points() self.current_operation = OPERATION_PASTE_IMAGE def OnLButtonUp(self, event): if self.current_operation == OPERATION_PASTE_IMAGE: self.grid.add_current_image() if self.current_operation == OPERATION_DELETE_IMAGE: self.grid.delete_image() def OnMouseMove(self, event): self.grid.current_point = GET_POINT_LPARAM(event.lParam) if self.grid.is_cell_changed(): hdc = self.GetDC() status, graphics = gdiplus.GdipCreateFromHDC(hdc) clip_rect = self.grid.current_cell + self.grid.old_cell status = gdiplus.GdipSetClipRectI(graphics, clip_rect.left, clip_rect.top, clip_rect.width, clip_rect.height, gdiplus.CombineModeReplace) status = gdiplus.GdipGraphicsClear(graphics, self.color_background) self.grid.draw(graphics) gdiplus.GdipDeleteGraphics(graphics) self.ReleaseDC(hdc) def OnOpenImage(self, event): dlg = OpenFileDialog() dlg.lpstrInitialDir = getcwd() dlg.lpstrInitialDir = self.current_open_dir dlg.nFilterIndex = self.current_open_filter_index dlg.SetFilter( 'BMP Image(*.bmp)|*.bmp|PNG Image(*.png)|*.png|JPG Image(*.jpg)|*.jpg|GIF Image(*.gif)|*.gif|Icon Image(*.ico)|*.ico|Cursor Image(*.cur)|*.cur|EMF Image(*.emf)|*.emf|WMF Image(*.wmf)|*.wmf|All files(*.*)|*.*' ) if dlg.DoModal(self): self.current_open_dir = dlg.lpstrFile self.current_open_filter_index = dlg.nFilterIndex status = -1 if dlg.nFilterIndex == 1: #BMP status, image = gdiplus.GdipCreateBitmapFromFile(dlg.lpstrFile) elif dlg.nFilterIndex in (5, 6): #ICO#CUR hicon = ExtractIcon(None, dlg.lpstrFile, 0) if hicon: status, image = gdiplus.GdipCreateBitmapFromHICON(hicon) else: status, image = gdiplus.GdipLoadImageFromFile(dlg.lpstrFile) if status == gdiplus.Ok: self.grid.current_image = (image, dlg.lpstrFile) self.set_paste_property() def set_paste_property(self): self.current_operation = OPERATION_PASTE_IMAGE self.grid.color_active_cell = self.color_active_cell_paste self.grid.create_brush_cell() def OnGetClear(self, event): self.grid.current_image = (None, '') self.current_operation = OPERATION_DELETE_IMAGE self.grid.color_active_cell = gdiplus.MakeARGB(128, 255, 0, 0) self.grid.create_brush_cell() cmd_handler(form.ID_OPEN)(OnOpenImage) cmd_handler(form.ID_CLEAR)(OnGetClear) msg_handler(WM_DESTROY)(OnDestroy) msg_handler(WM_PAINT)(OnPaint) msg_handler(WM_SIZE)(OnSize) msg_handler(WM_LBUTTONUP)(OnLButtonUp) msg_handler(WM_MOUSEMOVE)(OnMouseMove) msg_handler(WM_CREATE)(OnCreate)
def OnCreate(self, event): self.sp = splitter.Splitter(splitPos=self.clientRect.width / 2, parent=self) self.fc = fern_canvas(parent=self.sp, orExStyle=WS_EX_STATICEDGE) self.sp.Add(1, self.fc) self.controls.Add(self.fc) self.prop = form.Form(parent=self.sp, style=WS_CHILD | WS_VISIBLE, orExStyle=WS_EX_STATICEDGE) self.prop._window_background_ = gdi.GetStockObject(gdi.LTGRAY_BRUSH) tb = track_bar(title=self.FMT_RECURSION % self.fc.maxLevels, rcPos=RECT(5, 0, 300, 50), parent=self.prop, form=self) tb.SetRange(1, 10) tb.SetPos(self.fc.maxLevels) self.controls.Add(tb) tb = track_bar(title=self.FMT_BEND_ANGLE % self.fc.initBendAngle, rcPos=RECT(5, 60, 300, 110), parent=self.prop, form=self) tb.SetRange(0, 120) tb.SetPos(self.fc.initBendAngle + 60) self.controls.Add(tb) tb = track_bar(title=self.FMT_BRANCH_ANGLE % self.fc.initBranchAngle, rcPos=RECT(5, 120, 300, 170), parent=self.prop, form=self) tb.SetRange(0, 90) tb.SetPos(self.fc.initBranchAngle) self.controls.Add(tb) tb = track_bar(title=self.FMT_TRUNK_RATIO % self.fc.trunkRatio, rcPos=RECT(5, 180, 300, 230), parent=self.prop, form=self) tb.SetRange(0, 75) tb.SetPos(int(self.fc.trunkRatio * 100)) self.controls.Add(tb) tb = track_bar(title=self.FMT_BRANCH_RATIO % self.fc.branchRatio, rcPos=RECT(5, 240, 300, 290), parent=self.prop, form=self) tb.SetRange(1, 20) tb.SetPos(int(self.fc.branchRatio * 10)) self.controls.Add(tb) tb = track_bar(title=self.FMT_HEIGHT_SCALE % self.fc.heightScale, rcPos=RECT(5, 300, 300, 350), parent=self.prop, form=self) tb.SetRange(1, 80) tb.SetPos(int(self.fc.heightScale * 10)) self.controls.Add(tb) self.sp.Add(0, self.prop) self.controls.Add(form.CTRL_VIEW, self.sp) self.controls.Add(form.CTRL_STATUSBAR, comctl.StatusBar(parent=self))
class fern_canvas(Window): _window_style_ = WS_CHILD | WS_VISIBLE | WS_TABSTOP _window_background_ = gdi.GetStockObject(gdi.WHITE_BRUSH) _window_style_ex_ = WS_EX_CLIENTEDGE maxLevels = 6 initBendAngle = 15 initBranchAngle = 37 trunkRatio = 0.1 branchRatio = 0.4 heightScale = 1.5 redrawing = True def draw(self, graphics, px, py, a, rad, level): cx = int(px + math.cos(a) * rad * self.trunkRatio) cy = int(py + math.sin(a) * rad * self.trunkRatio) status, pen = gdiplus.GdipCreatePen1( gdiplus.MakeARGB(100, 0, 100 + level * 3, 0), level) status = gdiplus.GdipDrawLineI(graphics, pen, px, py, cx, cy) if (level > 0): a = a + self.bendAngle level = level - 1 self.draw(graphics, cx, cy, a - self.branchAngle, rad * self.branchRatio, level) status = gdiplus.GdipDrawLineI(graphics, pen, px, py, cx, cy) self.draw(graphics, cx, cy, a + self.branchAngle, rad * self.branchRatio, level) status = gdiplus.GdipDrawLineI(graphics, pen, px, py, cx, cy) self.draw(graphics, cx, cy, a, rad * self.antiTrunkRatio, level) def redraw(self, hdc, rect): w, h = rect.width, rect.height status, graphics = gdiplus.GdipCreateFromHDC(hdc) if graphics: self.bendAngle = self.initBendAngle * math.pi / 180 self.branchAngle = self.initBranchAngle * math.pi / 180 self.lastMaxLevels = self.maxLevels self.antiTrunkRatio = 1 - self.trunkRatio self.startAngle = -math.pi / 2 px = w / 2 py = h - 5 #~ gdiplus.GdipSetCompositingMode(graphics, 1) gdiplus.GdipSetSmoothingMode(graphics, 4) # turn on antialiasing self.draw(graphics, px, py, self.startAngle, (h - 100) * self.heightScale, self.maxLevels) self.redrawing = not self.redrawing def OnPaint(self, event): if self.redrawing: ps = PAINTSTRUCT() ps.fErase = True hdc = self.BeginPaint(ps) rect = self.GetClientRect() self.redraw(hdc, rect) self.EndPaint(ps) self.redrawing = not self.redrawing def OnSize(self, event): self.InvalidateRect(self.GetClientRect(), True) msg_handler(WM_PAINT)(OnPaint) msg_handler(WM_SIZE)(OnSize)
class main_window(Window): _window_title_ = __doc__ _window_background_ = gdi.GetStockObject(gdi.LTGRAY_BRUSH) _window_icon_ = _window_icon_sm_ = Icon(lpIconName=IDI_ASTERISK) pt_size = 11 # count points set_size = 3 # count figures pt = (POINT * pt_size)( (10, 10), (100, 10), (50, 100), (10, 10), # 0 figure (triangle) (10, 110), (200, 110), (200, 180), (10, 180), (10, 110), # 1 figure (parallelogram) (10, 200), (200, 200)) # 2 figure (line) pts = (c_ulong * set_size)(4, 5, 2) # count points in every figure def OnDestroy(self, event): application.Quit() def OnPaint(self, event): ps = PAINTSTRUCT() ps.fErase = True hdc = self.BeginPaint(ps) if WINVER >= 0x0400: gdi.SetGraphicsMode(hdc, gdi.GM_ADVANCED) gdi.SetMapMode(hdc, gdi.MM_ANISOTROPIC) rect = self.GetClientRect() self.Drawing_a_Shaded_Rectangle(hdc, rect) gdi.SelectObject(hdc, gdi.GetStockObject(gdi.DC_PEN)) gdi.SetDCPenColor(hdc, gdi.RGB(00, 0xff, 00)) gdi.SelectObject(hdc, gdi.GetStockObject(gdi.DC_BRUSH)) gdi.SetDCBrushColor(hdc, gdi.RGB(00, 00, 0xff)) gdi.PolyPolyline(hdc, self.pt, self.pts, self.set_size) self.EndPaint(ps) def OnTimer(self, event): self.InvalidateRect(self.GetClientRect(), False) msg_handler(WM_DESTROY)(OnDestroy) msg_handler(WM_PAINT)(OnPaint) msg_handler(WM_TIMER)(OnTimer) def Drawing_a_Shaded_Rectangle(self, hdc, rc): vert = (gdi.TRIVERTEX * 2)() gRect = gdi.GRADIENT_RECT() vert[0].x = 0 vert[0].y = 0 vert[0].Red = randint(0x0000, 0xffff) #0xff00 vert[0].Green = randint(0x0000, 0xffff) #0xff00 vert[0].Blue = randint(0x0000, 0xffff) #0x0000 vert[0].Alpha = 0x8000 vert[1].x = rc.width vert[1].y = rc.height vert[1].Red = randint(0x0000, 0xffff) #0x0000 vert[1].Green = randint(0x0000, 0xffff) #0x0000 vert[1].Blue = randint(0x0000, 0xffff) #0xff00 vert[1].Alpha = 0x8000 gRect.UpperLeft = 0 gRect.LowerRight = 1 gdi.GradientFill(hdc, vert, 2, byref(gRect), 1, gdi.GRADIENT_FILL_RECT_H)
class Form(Window): """A class representing an applications main window. This class supports accelerators, automatic closing of the application with simple window management For status bar support make sure you have a statusBar property in your derived Form and provide _form_status_msgs_ to enable help msgs on the statusbar. A single child view is supported and it must be available in the derived class as 'view' property. """ _window_style_ex_ = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_WINDOWEDGE | WS_EX_APPWINDOW _window_background_ = gdi.GetStockObject(gdi.WHITE_BRUSH) _form_accels_ = [] _form_exit_ = EXIT_ONDESTROY _form_count_ = 0 _form_status_msgs_ = {} #maps command_id's to status bar msgs _form_menu_ = [(MF_POPUP, "&File", [(MF_SEPARATOR, ), (MF_STRING, "&Exit", ID_EXIT)])] def __init__(self, *args, **kwargs): self.m_controls = Controls() aMenu = kwargs.get('menu', None) or (self._form_menu_ and menu.EvalMenu(self._form_menu_)) if aMenu: kwargs['menu'] = aMenu #install accelerator support self.CreateAccels() GetMessageLoop().AddFilter(self.PreTranslateMessage) Form._form_count_ += 1 Window.__init__(self, *args, **kwargs) controls = property(lambda self: self.m_controls) def dispose(self): self.controls.dispose() #TODO weak ref on filter GetMessageLoop().RemoveFilter(self.PreTranslateMessage) #TODO dispose Accel Table weak refs? _haccel_ = 0 def CreateAccels(self): """Create accelerator table from _form_accels_""" if self._form_accels_ and not Form._haccel_: accels = (ACCEL * len(self._form_accels_))() for i in range(len(self._form_accels_)): accels[i].fVirt = self._form_accels_[i][0] accels[i].key = self._form_accels_[i][1] accels[i].cmd = self._form_accels_[i][2] Form._haccel_ = CreateAcceleratorTable(byref(accels), len(self._form_accels_)) def PreTranslateMessage(self, msg): if Form._haccel_ and self.handle == GetForegroundWindow(): return TranslateAccelerator(self.handle, Form._haccel_, byref(msg)) else: return 0 def OnMenuSelect(self, event): """displays short help msg for menu command on statusbar""" statusBar = self.controls.get(CTRL_STATUSBAR, None) if not statusBar: return wFlags = HIWORD(event.wParam) if wFlags == 0xffff and event.lParam == 0: statusBar.Simple(0) else: txt = self._form_status_msgs_.get(LOWORD(event.wParam), "") statusBar.Simple(1) statusBar.SetText(txt) class CmdUIUpdateEvent(object): def __init__(self): self.m_enabled = 0 def Enable(self, fEnable): self.m_enabled = fEnable enabled = property(lambda self: self.m_enabled) def OnInitMenuPopup(self, event): """querys cmd ui update map to see if menu items must be enabled/disabled""" if HIWORD(event.lParam) == 1: return #it's the window menu cmdUiUpdateMap = self._msg_map_._msg_map_.get("CMD_UI_UPDATE_MAP", {}) hMenu = event.wParam minfo = MENUITEMINFO() minfo.cbSize = sizeof(MENUITEMINFO) minfo.fMask = MIIM_ID | MIIM_TYPE for i in range(GetMenuItemCount(hMenu)): minfo.fMask = MIIM_ID | MIIM_TYPE GetMenuItemInfo(hMenu, i, True, byref(minfo)) if minfo.fType == MFT_STRING: handler = cmdUiUpdateMap.get(minfo.wID, None) if handler: cmdUiUpdateEvent = self.CmdUIUpdateEvent() handler(self, cmdUiUpdateEvent) minfo.fMask = MIIM_STATE if cmdUiUpdateEvent.enabled: minfo.fState = MFS_ENABLED else: minfo.fState = MFS_DISABLED SetMenuItemInfo(hMenu, i, True, minfo) def DoLayout(self, cx, cy): """Lays out the form. A form consists of an optional toolbar, view and statusbar""" deferWindowPos = [] coolBar = self.controls.get(CTRL_COOLBAR, None) if coolBar: coolBarHeight = coolBar.windowRect.height deferWindowPos.append((coolBar, 0, 0, cx, coolBarHeight)) else: coolBarHeight = 0 statusBar = self.controls.get(CTRL_STATUSBAR, None) if statusBar: statusBarHeight = statusBar.windowRect.height deferWindowPos.append( (statusBar, 0, cy - statusBarHeight, cx, statusBarHeight)) else: statusBarHeight = 0 view = self.controls.get(CTRL_VIEW, None) if view: deferWindowPos.append((view, 0, coolBarHeight, cx, cy - statusBarHeight - coolBarHeight)) hdwp = BeginDeferWindowPos(len(deferWindowPos)) for ctrl, x, y, dx, dy in deferWindowPos: DeferWindowPos(hdwp, ctrl.handle, NULL, x, y, dx, dy, SWP_NOACTIVATE | SWP_NOZORDER) EndDeferWindowPos(hdwp) if coolBar: coolBar.Invalidate() def OnDestroy(self, event): self.dispose() Form._form_count_ -= 1 if self._form_exit_ == EXIT_ONDESTROY: PostQuitMessage(0) elif self._form_exit_ == EXIT_ONLASTDESTROY and \ self._form_count_ == 0: PostQuitMessage(0) def OnSize(self, event): self.DoLayout(*event.size) def OnCreate(self, event): pass def OnExitCmd(self, event): self.SendMessage(WM_CLOSE) def OnCloseCmd(self, event): self.SendMessage(WM_CLOSE) ##override and set event.handled = True to prevent ##form from closing def OnClose(self, event): event.handled = False #event will buble and invoke window destroy eventually _msg_map_ = MSG_MAP([ MSG_HANDLER(WM_DESTROY, OnDestroy), MSG_HANDLER(WM_CREATE, OnCreate), MSG_HANDLER(WM_SIZE, OnSize), MSG_HANDLER(WM_CLOSE, OnClose), MSG_HANDLER(WM_MENUSELECT, OnMenuSelect), MSG_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup), CMD_ID_HANDLER(ID_EXIT, OnExitCmd), CMD_ID_HANDLER(ID_CLOSE, OnCloseCmd), NTF_HANDLER(comctl.RBN_HEIGHTCHANGE, lambda self, event: self.DoLayout(*self.clientRect.size)), ])
class main_window(Window): _window_title_ = __doc__ _window_background_ = gdi.GetStockObject(gdi.LTGRAY_BRUSH) _window_icon_ = _window_icon_sm_ = Icon(lpIconName=IDI_ASTERISK) pt_size = 11 # count points set_size = 3 # count figures graphics = 0 full_redraw_counter = 0 ClockDiameter = 180.0 Width = Height = ClockDiameter + 2 # make width and height slightly bigger to avoid cut away edges CenterX = CenterY = floor(ClockDiameter / 2) # Center x def draw_clock_marks(self, pen, items, r1, r2): for i in range(items): gdiplus.GdipDrawLine( self.graphics, pen, self.CenterX - ceil(r1 * cos( ((i - 1) * 360 / items) * atan(1) * 4 / 180)), self.CenterY - ceil(r1 * sin( ((i - 1) * 360 / items) * atan(1) * 4 / 180)), self.CenterX - ceil(r2 * cos( ((i - 1) * 360 / items) * atan(1) * 4 / 180)), self.CenterY - ceil(r2 * sin( ((i - 1) * 360 / items) * atan(1) * 4 / 180))) def draw_outer_circle(self): Diameter = self.ClockDiameter status, pBrush_outer = gdiplus.GdipCreateSolidFill(0x66008000) gdiplus.GdipFillEllipse(self.graphics, pBrush_outer, self.CenterX - (Diameter / 2), self.CenterY - (Diameter / 2), Diameter, Diameter) #~ gdiplus.GdipDeleteBrush(pBrush_outer) def draw_inner_circle(self): Diameter = ceil( self.ClockDiameter - self.ClockDiameter * 0.08) # inner circle is 8 % smaller than clock's diameter status, pBrush_inner = gdiplus.GdipCreateSolidFill(0x80008000) gdiplus.GdipFillEllipse(self.graphics, pBrush_inner, self.CenterX - (Diameter / 2), self.CenterY - (Diameter / 2), Diameter, Diameter) #~ gdiplus.GdipDeleteBrush(pBrush_inner) def draw_second_marks(self): Diameter = self.ClockDiameter R1 = Diameter / 2 - 1 # outer position R2 = Diameter / 2 - 1 - ceil(Diameter / 2 * 0.05) # inner position Items = 60 # we have 60 seconds status, pPen = gdiplus.GdipCreatePen1( 0xff00a000, floor((self.ClockDiameter / 100) * 1.2)) # 1.2 % of total diameter is our pen width self.draw_clock_marks(pPen, Items, R1, R2) #~ gdiplus.GdipDeletePen(pPen) def draw_hour_marks(self): Diameter = self.ClockDiameter R1 = Diameter / 2 - 1 # outer position R2 = Diameter / 2 - 1 - ceil(Diameter / 2 * 0.1) # inner position Items = 12 # we have 12 hours status, pPen = gdiplus.GdipCreatePen1( 0xc0008000, ceil((self.ClockDiameter / 100) * 2.3)) # 2.3 % of total diameter is our pen width self.draw_clock_marks(pPen, Items, R1, R2) #~ gdiplus.GdipDeletePen(pPen) def draw_arrows(self): Diameter = self.ClockDiameter CenterX, CenterY = self.CenterX, self.CenterY current_time = datetime.now() A_Hour, A_Min, A_Sec = current_time.hour, current_time.minute, current_time.second # prepare to empty previously drawn stuff #~ gdiplus.GdipSetSmoothingMode(self.graphics, 1) # turn off aliasing #~ gdiplus.GdipSetCompositingMode(self.graphics, 1) # set to overdraw # delete previous graphic and redraw background #~ Diameter = ceil(self.ClockDiameter - self.ClockDiameter*0.18) # 18 % less than clock's outer diameter # delete whatever has been drawn here #~ status, pBrush = gdiplus.GdipCreateSolidFill(0x00000000) # fully transparent brush 'eraser' #~ gdiplus.GdipFillEllipse(self.graphics, pBrush, CenterX-(Diameter/2), CenterY-(Diameter/2), Diameter, Diameter) #~ gdiplus.GdipDeleteBrush(pBrush) #~ gdiplus.GdipSetCompositingMode(self.graphics, 0) # switch off overdraw #~ status, pBrush = gdiplus.GdipCreateSolidFill(0x66008000) #~ gdiplus.GdipFillEllipse(self.graphics, pBrush, CenterX-(Diameter/2), CenterY-(Diameter/2), Diameter, Diameter) #~ gdiplus.GdipDeleteBrush(pBrush) #~ status, pBrush = gdiplus.GdipCreateSolidFill(0x80008000) #~ gdiplus.GdipFillEllipse(self.graphics, pBrush, CenterX-(Diameter/2), CenterY-(Diameter/2), Diameter, Diameter) #~ gdiplus.GdipDeleteBrush(pBrush) # Draw HoursPointer gdiplus.GdipSetSmoothingMode(self.graphics, 4) # turn on antialiasing t = A_Hour * 360 / 12 + (A_Min * 360 / 60) / 12 + 90 R1 = self.ClockDiameter / 2 - ceil( (self.ClockDiameter / 2) * 0.5) # outer position status, pPen = gdiplus.GdipCreatePen1( 0xa0008000, floor((self.ClockDiameter / 100) * 3.5)) gdiplus.GdipDrawLine(self.graphics, pPen, CenterX, CenterY, ceil(CenterX - (R1 * cos(t * atan(1) * 4 / 180))), ceil(CenterY - (R1 * sin(t * atan(1) * 4 / 180)))) gdiplus.GdipDeletePen(pPen) # Draw MinutesPointer t = A_Min * 360 / 60 + 90 R1 = self.ClockDiameter / 2 - ceil( (self.ClockDiameter / 2) * 0.25) # outer position status, pPen = gdiplus.GdipCreatePen1( 0xa0008000, floor((self.ClockDiameter / 100) * 2.7)) gdiplus.GdipDrawLine(self.graphics, pPen, CenterX, CenterY, ceil(CenterX - (R1 * cos(t * atan(1) * 4 / 180))), ceil(CenterY - (R1 * sin(t * atan(1) * 4 / 180)))) gdiplus.GdipDeletePen(pPen) # Draw SecondsPointer t = A_Sec * 360 / 60 + 90 R1 = self.ClockDiameter / 2 - ceil( (self.ClockDiameter / 2) * 0.2) # outer position status, pPen = gdiplus.GdipCreatePen1( 0xa000FF00, floor((self.ClockDiameter / 100) * 1.2)) gdiplus.GdipDrawLine(self.graphics, pPen, CenterX, CenterY, ceil(CenterX - (R1 * cos(t * atan(1) * 4 / 180))), ceil(CenterY - (R1 * sin(t * atan(1) * 4 / 180)))) gdiplus.GdipDeletePen(pPen) def Drawing_a_Shaded_Rectangle(self, hdc, rc): vert = (gdi.TRIVERTEX * 2)() gRect = gdi.GRADIENT_RECT() vert[0].x = 0 vert[0].y = 0 vert[0].Red = randint(0x0000, 0xffff) vert[0].Green = randint(0x0000, 0xffff) vert[0].Blue = randint(0x0000, 0xffff) vert[0].Alpha = 0x8000 vert[1].x = rc.width vert[1].y = rc.height vert[1].Red = randint(0x0000, 0xffff) vert[1].Green = randint(0x0000, 0xffff) vert[1].Blue = randint(0x0000, 0xffff) vert[1].Alpha = 0x8000 gRect.UpperLeft = 0 gRect.LowerRight = 1 gdi.GradientFill(hdc, vert, 2, byref(gRect), 1, gdi.GRADIENT_FILL_RECT_H) def OnDestroy(self, event): if self.graphics: status = gdiplus.GdipDeleteGraphics(self.graphics) application.Quit() def OnPaint(self, event): ps = PAINTSTRUCT() ps.fErase = True hdc = self.BeginPaint(ps) rect = self.GetClientRect() self.ClockDiameter = rect.width if self.ClockDiameter > rect.height: self.ClockDiameter = rect.height self.Width = self.Height = self.ClockDiameter + 2 self.CenterX = self.CenterY = floor(self.ClockDiameter / 2) # redraw background with new color self.Drawing_a_Shaded_Rectangle(hdc, rect) status, self.graphics = gdiplus.GdipCreateFromHDC(hdc) #~ status = gdiplus.GdipSetSmoothingMode(self.graphics, 4) #~ if self.full_redraw_counter == 0: #~ self.draw_outer_circle() #~ self.draw_inner_circle() self.draw_second_marks() self.draw_hour_marks() self.draw_arrows() self.EndPaint(ps) def OnTimer(self, event): self.InvalidateRect(self.GetClientRect()) #, False) #~ self.full_redraw_counter += 1 #~ if self.full_redraw_counter > 60: #~ self.full_redraw_counter = 0 #~ windll.user32.UpdateLayeredWindow(self.m_handle, self.GetDC(), pointer(POINT(0, 0)), pointer(SIZE(self.Width, self.Height)), gdi.CreateCompatibleDC(self.GetDC()), pointer(POINT(0, 0)), 0, None, 0) msg_handler(WM_DESTROY)(OnDestroy) msg_handler(WM_PAINT)(OnPaint) msg_handler(WM_TIMER)(OnTimer)