openmedialibrary_platform_w.../Lib/site-packages/pythonwin/pywin/Demos/threadedgui.py

175 lines
5.6 KiB
Python
Raw Normal View History

2016-04-14 19:54:42 +00:00
# Demo of using just windows, without documents and views.
# Also demo of a GUI thread, pretty much direct from the MFC C++ sample MTMDI.
import win32ui
import win32con
import win32api
import timer
from pywin.mfc import window, docview, thread
from pywin.mfc.thread import WinThread
WM_USER_PREPARE_TO_CLOSE = win32con.WM_USER + 32
# font is a dictionary in which the following elements matter:
# (the best matching font to supplied parameters is returned)
# name string name of the font as known by Windows
# size point size of font in logical units
# weight weight of font (win32con.FW_NORMAL, win32con.FW_BOLD)
# italic boolean; true if set to anything but None
# underline boolean; true if set to anything but None
# This window is a child window of a frame. It is not the frame window itself.
class FontWindow(window.Wnd):
def __init__(self, text = 'Python Rules!'):
window.Wnd.__init__(self)
self.text = text
self.index = 0
self.incr = 1
self.width = self.height = 0
self.ChangeAttributes()
# set up message handlers
def Create(self, title, style, rect, parent):
classStyle = win32con.CS_HREDRAW | win32con.CS_VREDRAW
className = win32ui.RegisterWndClass(classStyle, 0, win32con.COLOR_WINDOW+1, 0)
self._obj_ = win32ui.CreateWnd()
self._obj_.AttachObject(self)
self._obj_.CreateWindow(className, title, style, rect, parent, win32ui.AFX_IDW_PANE_FIRST)
self.HookMessage (self.OnSize, win32con.WM_SIZE)
self.HookMessage (self.OnPrepareToClose, WM_USER_PREPARE_TO_CLOSE)
self.HookMessage (self.OnDestroy, win32con.WM_DESTROY)
self.timerid = timer.set_timer (100, self.OnTimer)
self.InvalidateRect()
def OnDestroy (self, msg):
timer.kill_timer(self.timerid)
def OnTimer(self, id, timeVal):
self.index = self.index + self.incr
if self.index > len(self.text):
self.incr = -1
self.index = len(self.text)
elif self.index < 0:
self.incr = 1
self.index = 0
self.InvalidateRect()
def OnPaint (self):
# print "Paint message from thread", win32api.GetCurrentThreadId()
dc, paintStruct = self.BeginPaint()
self.OnPrepareDC(dc, None)
if (self.width == 0 and self.height == 0):
left, top, right, bottom = self.GetClientRect()
self.width = right - left
self.height = bottom - top
x, y = self.width // 2, self.height // 2
dc.TextOut (x, y, self.text[:self.index])
self.EndPaint(paintStruct)
def ChangeAttributes(self):
font_spec = {'name':'Arial', 'height':42}
self.font = win32ui.CreateFont (font_spec)
def OnPrepareToClose(self, params):
self.DestroyWindow()
def OnSize (self, params):
lParam = params[3]
self.width = win32api.LOWORD(lParam)
self.height = win32api.HIWORD(lParam)
def OnPrepareDC (self, dc, printinfo):
# Set up the DC for forthcoming OnDraw call
dc.SetTextColor (win32api.RGB(0,0,255))
dc.SetBkColor (win32api.GetSysColor (win32con.COLOR_WINDOW))
dc.SelectObject (self.font)
dc.SetTextAlign (win32con.TA_CENTER | win32con.TA_BASELINE)
class FontFrame(window.MDIChildWnd):
def __init__(self):
pass # Dont call base class doc/view version...
def Create(self, title, rect = None, parent = None):
style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_OVERLAPPEDWINDOW
self._obj_ = win32ui.CreateMDIChild()
self._obj_.AttachObject(self)
self._obj_.CreateWindow(None, title, style, rect, parent)
rect = self.GetClientRect()
rect = (0,0,rect[2]-rect[0], rect[3]-rect[1])
self.child = FontWindow("Not threaded")
self.child.Create("FontDemo", win32con.WS_CHILD | win32con.WS_VISIBLE, rect, self)
class TestThread(WinThread):
def __init__(self, parentWindow):
self.parentWindow = parentWindow
self.child = None
WinThread.__init__(self)
def InitInstance(self):
rect = self.parentWindow.GetClientRect()
rect = (0,0,rect[2]-rect[0], rect[3]-rect[1])
self.child = FontWindow()
self.child.Create("FontDemo", win32con.WS_CHILD | win32con.WS_VISIBLE, rect, self.parentWindow)
self.SetMainFrame(self.child)
return WinThread.InitInstance(self)
def ExitInstance(self):
return 0
class ThreadedFontFrame(window.MDIChildWnd):
def __init__(self):
pass # Dont call base class doc/view version...
self.thread = None
def Create(self, title, rect = None, parent = None):
style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_OVERLAPPEDWINDOW
self._obj_ = win32ui.CreateMDIChild()
self._obj_.CreateWindow(None, title, style, rect, parent)
self._obj_.HookMessage(self.OnDestroy, win32con.WM_DESTROY)
self._obj_.HookMessage (self.OnSize, win32con.WM_SIZE)
self.thread = TestThread(self)
self.thread.CreateThread()
def OnSize(self, msg):
pass
def OnDestroy(self, msg):
win32ui.OutputDebugString("OnDestroy\n")
if self.thread and self.thread.child:
child = self.thread.child
child.SendMessage(WM_USER_PREPARE_TO_CLOSE, 0, 0)
win32ui.OutputDebugString("Destroyed\n")
def Demo():
f = FontFrame()
f.Create("Font Demo")
def ThreadedDemo():
rect = win32ui.GetMainFrame().GetMDIClient().GetClientRect()
rect = rect[0], int(rect[3]*3/4), int(rect[2]/4), rect[3]
incr = rect[2]
for i in range(4):
if i==0:
f = FontFrame()
title = "Not threaded"
else:
f = ThreadedFontFrame()
title = "Threaded GUI Demo"
f.Create(title, rect)
rect = rect[0] + incr, rect[1], rect[2]+incr, rect[3]
# Givem a chance to start
win32api.Sleep(100)
win32ui.PumpWaitingMessages()
if __name__=='__main__':
import demoutils
if demoutils.NeedGoodGUI():
ThreadedDemo()
# Demo()