Spaces:
Sleeping
Sleeping
File size: 6,620 Bytes
d12bc25 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
# No cancel button.
import threading
import time
import win32api
import win32con
import win32ui
from pywin.mfc import dialog
from pywin.mfc.thread import WinThread
def MakeProgressDlgTemplate(caption, staticText=""):
style = (
win32con.DS_MODALFRAME
| win32con.WS_POPUP
| win32con.WS_VISIBLE
| win32con.WS_CAPTION
| win32con.WS_SYSMENU
| win32con.DS_SETFONT
)
cs = win32con.WS_CHILD | win32con.WS_VISIBLE
w = 215
h = 36 # With button
h = 40
dlg = [
[caption, (0, 0, w, h), style, None, (8, "MS Sans Serif")],
]
s = win32con.WS_TABSTOP | cs
dlg.append([130, staticText, 1000, (7, 7, w - 7, h - 32), cs | win32con.SS_LEFT])
# dlg.append([128,
# "Cancel",
# win32con.IDCANCEL,
# (w - 60, h - 18, 50, 14), s | win32con.BS_PUSHBUTTON])
return dlg
class CStatusProgressDialog(dialog.Dialog):
def __init__(self, title, msg="", maxticks=100, tickincr=1):
self.initMsg = msg
templ = MakeProgressDlgTemplate(title, msg)
dialog.Dialog.__init__(self, templ)
self.maxticks = maxticks
self.tickincr = tickincr
self.pbar = None
def OnInitDialog(self):
rc = dialog.Dialog.OnInitDialog(self)
self.static = self.GetDlgItem(1000)
self.pbar = win32ui.CreateProgressCtrl()
self.pbar.CreateWindow(
win32con.WS_CHILD | win32con.WS_VISIBLE, (10, 30, 310, 44), self, 1001
)
self.pbar.SetRange(0, self.maxticks)
self.pbar.SetStep(self.tickincr)
self.progress = 0
self.pincr = 5
return rc
def Close(self):
self.EndDialog(0)
def SetMaxTicks(self, maxticks):
if self.pbar is not None:
self.pbar.SetRange(0, maxticks)
def Tick(self):
if self.pbar is not None:
self.pbar.StepIt()
def SetTitle(self, text):
self.SetWindowText(text)
def SetText(self, text):
self.SetDlgItemText(1000, text)
def Set(self, pos, max=None):
if self.pbar is not None:
self.pbar.SetPos(pos)
if max is not None:
self.pbar.SetRange(0, max)
# a progress dialog created in a new thread - especially suitable for
# console apps with no message loop.
MYWM_SETTITLE = win32con.WM_USER + 10
MYWM_SETMSG = win32con.WM_USER + 11
MYWM_TICK = win32con.WM_USER + 12
MYWM_SETMAXTICKS = win32con.WM_USER + 13
MYWM_SET = win32con.WM_USER + 14
class CThreadedStatusProcessDialog(CStatusProgressDialog):
def __init__(self, title, msg="", maxticks=100, tickincr=1):
self.title = title
self.msg = msg
self.threadid = win32api.GetCurrentThreadId()
CStatusProgressDialog.__init__(self, title, msg, maxticks, tickincr)
def OnInitDialog(self):
rc = CStatusProgressDialog.OnInitDialog(self)
self.HookMessage(self.OnTitle, MYWM_SETTITLE)
self.HookMessage(self.OnMsg, MYWM_SETMSG)
self.HookMessage(self.OnTick, MYWM_TICK)
self.HookMessage(self.OnMaxTicks, MYWM_SETMAXTICKS)
self.HookMessage(self.OnSet, MYWM_SET)
return rc
def _Send(self, msg):
try:
self.PostMessage(msg)
except win32ui.error:
# the user closed the window - but this does not cancel the
# process - so just ignore it.
pass
def OnTitle(self, msg):
CStatusProgressDialog.SetTitle(self, self.title)
def OnMsg(self, msg):
CStatusProgressDialog.SetText(self, self.msg)
def OnTick(self, msg):
CStatusProgressDialog.Tick(self)
def OnMaxTicks(self, msg):
CStatusProgressDialog.SetMaxTicks(self, self.maxticks)
def OnSet(self, msg):
CStatusProgressDialog.Set(self, self.pos, self.max)
def Close(self):
assert self.threadid, "No thread!"
win32api.PostThreadMessage(self.threadid, win32con.WM_QUIT, 0, 0)
def SetMaxTicks(self, maxticks):
self.maxticks = maxticks
self._Send(MYWM_SETMAXTICKS)
def SetTitle(self, title):
self.title = title
self._Send(MYWM_SETTITLE)
def SetText(self, text):
self.msg = text
self._Send(MYWM_SETMSG)
def Tick(self):
self._Send(MYWM_TICK)
def Set(self, pos, max=None):
self.pos = pos
self.max = max
self._Send(MYWM_SET)
class ProgressThread(WinThread):
def __init__(self, title, msg="", maxticks=100, tickincr=1):
self.title = title
self.msg = msg
self.maxticks = maxticks
self.tickincr = tickincr
self.dialog = None
WinThread.__init__(self)
self.createdEvent = threading.Event()
def InitInstance(self):
self.dialog = CThreadedStatusProcessDialog(
self.title, self.msg, self.maxticks, self.tickincr
)
self.dialog.CreateWindow()
try:
self.dialog.SetForegroundWindow()
except win32ui.error:
pass
self.createdEvent.set()
return WinThread.InitInstance(self)
def ExitInstance(self):
return 0
def StatusProgressDialog(title, msg="", maxticks=100, parent=None):
d = CStatusProgressDialog(title, msg, maxticks)
d.CreateWindow(parent)
return d
def ThreadedStatusProgressDialog(title, msg="", maxticks=100):
t = ProgressThread(title, msg, maxticks)
t.CreateThread()
# Need to run a basic "PumpWaitingMessages" loop just incase we are
# running inside Pythonwin.
# Basic timeout incase things go terribly wrong. Ideally we should use
# win32event.MsgWaitForMultipleObjects(), but we use a threading module
# event - so use a dumb strategy
end_time = time.time() + 10
while time.time() < end_time:
if t.createdEvent.isSet():
break
win32ui.PumpWaitingMessages()
time.sleep(0.1)
return t.dialog
def demo():
d = StatusProgressDialog("A Demo", "Doing something...")
import win32api
for i in range(100):
if i == 50:
d.SetText("Getting there...")
if i == 90:
d.SetText("Nearly done...")
win32api.Sleep(20)
d.Tick()
d.Close()
def thread_demo():
d = ThreadedStatusProgressDialog("A threaded demo", "Doing something")
import win32api
for i in range(100):
if i == 50:
d.SetText("Getting there...")
if i == 90:
d.SetText("Nearly done...")
win32api.Sleep(20)
d.Tick()
d.Close()
if __name__ == "__main__":
thread_demo()
# demo()
|