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.

eventsApartmentThreaded.py 3.6KB

1 year ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. # A sample originally provided by Richard Bell, and modified by Mark Hammond.
  2. # This sample demonstrates how to use COM events in an aparment-threaded
  3. # world. In this world, COM itself ensures that all calls to and events
  4. # from an object happen on the same thread that created the object, even
  5. # if they originated from different threads. For this cross-thread
  6. # marshalling to work, this main thread *must* run a "message-loop" (ie,
  7. # a loop fetching and dispatching Windows messages). Without such message
  8. # processing, dead-locks can occur.
  9. # See also eventsFreeThreaded.py for how to do this in a free-threaded
  10. # world where these marshalling considerations do not exist.
  11. # NOTE: This example uses Internet Explorer, but it should not be considerd
  12. # a "best-practices" for writing against IE events, but for working with
  13. # events in general. For example:
  14. # * The first OnDocumentComplete event is not a reliable indicator that the
  15. # URL has completed loading
  16. # * As we are demonstrating the most efficient way of handling events, when
  17. # running this sample you will see an IE Windows briefly appear, but
  18. # vanish without ever being repainted.
  19. import time
  20. # sys.coinit_flags not set, so pythoncom initializes apartment-threaded.
  21. import pythoncom
  22. import win32api
  23. import win32com.client
  24. import win32event
  25. class ExplorerEvents:
  26. def __init__(self):
  27. self.event = win32event.CreateEvent(None, 0, 0, None)
  28. def OnDocumentComplete(self, pDisp=pythoncom.Empty, URL=pythoncom.Empty):
  29. thread = win32api.GetCurrentThreadId()
  30. print("OnDocumentComplete event processed on thread %d" % thread)
  31. # Set the event our main thread is waiting on.
  32. win32event.SetEvent(self.event)
  33. def OnQuit(self):
  34. thread = win32api.GetCurrentThreadId()
  35. print("OnQuit event processed on thread %d" % thread)
  36. win32event.SetEvent(self.event)
  37. def WaitWhileProcessingMessages(event, timeout=2):
  38. start = time.perf_counter()
  39. while True:
  40. # Wake 4 times a second - we can't just specify the
  41. # full timeout here, as then it would reset for every
  42. # message we process.
  43. rc = win32event.MsgWaitForMultipleObjects(
  44. (event,), 0, 250, win32event.QS_ALLEVENTS
  45. )
  46. if rc == win32event.WAIT_OBJECT_0:
  47. # event signalled - stop now!
  48. return True
  49. if (time.perf_counter() - start) > timeout:
  50. # Timeout expired.
  51. return False
  52. # must be a message.
  53. pythoncom.PumpWaitingMessages()
  54. def TestExplorerEvents():
  55. iexplore = win32com.client.DispatchWithEvents(
  56. "InternetExplorer.Application", ExplorerEvents
  57. )
  58. thread = win32api.GetCurrentThreadId()
  59. print("TestExplorerEvents created IE object on thread %d" % thread)
  60. iexplore.Visible = 1
  61. try:
  62. iexplore.Navigate(win32api.GetFullPathName("..\\readme.html"))
  63. except pythoncom.com_error as details:
  64. print("Warning - could not open the test HTML file", details)
  65. # Wait for the event to be signalled while pumping messages.
  66. if not WaitWhileProcessingMessages(iexplore.event):
  67. print("Document load event FAILED to fire!!!")
  68. iexplore.Quit()
  69. #
  70. # Give IE a chance to shutdown, else it can get upset on fast machines.
  71. # Note, Quit generates events. Although this test does NOT catch them
  72. # it is NECESSARY to pump messages here instead of a sleep so that the Quit
  73. # happens properly!
  74. if not WaitWhileProcessingMessages(iexplore.event):
  75. print("OnQuit event FAILED to fire!!!")
  76. iexplore = None
  77. if __name__ == "__main__":
  78. TestExplorerEvents()