Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

status.py 6.5KB

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