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.

ietoolbar.py 11KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. # -*- coding: latin-1 -*-
  2. # PyWin32 Internet Explorer Toolbar
  3. #
  4. # written by Leonard Ritter (paniq@gmx.net)
  5. # and Robert Förtsch (info@robert-foertsch.com)
  6. """
  7. This sample implements a simple IE Toolbar COM server
  8. supporting Windows XP styles and access to
  9. the IWebBrowser2 interface.
  10. It also demonstrates how to hijack the parent window
  11. to catch WM_COMMAND messages.
  12. """
  13. # imports section
  14. import sys
  15. import winreg
  16. import pythoncom
  17. import win32com
  18. from win32com import universal
  19. from win32com.axcontrol import axcontrol
  20. from win32com.client import Dispatch, DispatchWithEvents, constants, gencache, getevents
  21. from win32com.shell import shell
  22. from win32com.shell.shellcon import *
  23. try:
  24. # try to get styles (winxp)
  25. import winxpgui as win32gui
  26. except:
  27. # import default module (win2k and lower)
  28. import win32gui
  29. import array
  30. import struct
  31. import commctrl
  32. import win32con
  33. import win32ui
  34. # ensure we know the ms internet controls typelib so we have access to IWebBrowser2 later on
  35. win32com.client.gencache.EnsureModule("{EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}", 0, 1, 1)
  36. #
  37. IDeskBand_methods = ["GetBandInfo"]
  38. IDockingWindow_methods = ["ShowDW", "CloseDW", "ResizeBorderDW"]
  39. IOleWindow_methods = ["GetWindow", "ContextSensitiveHelp"]
  40. IInputObject_methods = ["UIActivateIO", "HasFocusIO", "TranslateAcceleratorIO"]
  41. IObjectWithSite_methods = ["SetSite", "GetSite"]
  42. IPersistStream_methods = ["GetClassID", "IsDirty", "Load", "Save", "GetSizeMax"]
  43. _ietoolbar_methods_ = (
  44. IDeskBand_methods
  45. + IDockingWindow_methods
  46. + IOleWindow_methods
  47. + IInputObject_methods
  48. + IObjectWithSite_methods
  49. + IPersistStream_methods
  50. )
  51. _ietoolbar_com_interfaces_ = [
  52. shell.IID_IDeskBand, # IDeskBand
  53. axcontrol.IID_IObjectWithSite, # IObjectWithSite
  54. pythoncom.IID_IPersistStream,
  55. axcontrol.IID_IOleCommandTarget,
  56. ]
  57. class WIN32STRUCT:
  58. def __init__(self, **kw):
  59. full_fmt = ""
  60. for name, fmt, default in self._struct_items_:
  61. self.__dict__[name] = None
  62. if fmt == "z":
  63. full_fmt += "pi"
  64. else:
  65. full_fmt += fmt
  66. for name, val in kw.items():
  67. self.__dict__[name] = val
  68. def __setattr__(self, attr, val):
  69. if not attr.startswith("_") and attr not in self.__dict__:
  70. raise AttributeError(attr)
  71. self.__dict__[attr] = val
  72. def toparam(self):
  73. self._buffs = []
  74. full_fmt = ""
  75. vals = []
  76. for name, fmt, default in self._struct_items_:
  77. val = self.__dict__[name]
  78. if fmt == "z":
  79. fmt = "Pi"
  80. if val is None:
  81. vals.append(0)
  82. vals.append(0)
  83. else:
  84. str_buf = array.array("c", val + "\0")
  85. vals.append(str_buf.buffer_info()[0])
  86. vals.append(len(val))
  87. self._buffs.append(str_buf) # keep alive during the call.
  88. else:
  89. if val is None:
  90. val = default
  91. vals.append(val)
  92. full_fmt += fmt
  93. return struct.pack(*(full_fmt,) + tuple(vals))
  94. class TBBUTTON(WIN32STRUCT):
  95. _struct_items_ = [
  96. ("iBitmap", "i", 0),
  97. ("idCommand", "i", 0),
  98. ("fsState", "B", 0),
  99. ("fsStyle", "B", 0),
  100. ("bReserved", "H", 0),
  101. ("dwData", "I", 0),
  102. ("iString", "z", None),
  103. ]
  104. class Stub:
  105. """
  106. this class serves as a method stub,
  107. outputting debug info whenever the object
  108. is being called.
  109. """
  110. def __init__(self, name):
  111. self.name = name
  112. def __call__(self, *args):
  113. print("STUB: ", self.name, args)
  114. class IEToolbarCtrl:
  115. """
  116. a tiny wrapper for our winapi-based
  117. toolbar control implementation.
  118. """
  119. def __init__(self, hwndparent):
  120. styles = (
  121. win32con.WS_CHILD
  122. | win32con.WS_VISIBLE
  123. | win32con.WS_CLIPSIBLINGS
  124. | win32con.WS_CLIPCHILDREN
  125. | commctrl.TBSTYLE_LIST
  126. | commctrl.TBSTYLE_FLAT
  127. | commctrl.TBSTYLE_TRANSPARENT
  128. | commctrl.CCS_TOP
  129. | commctrl.CCS_NODIVIDER
  130. | commctrl.CCS_NORESIZE
  131. | commctrl.CCS_NOPARENTALIGN
  132. )
  133. self.hwnd = win32gui.CreateWindow(
  134. "ToolbarWindow32",
  135. None,
  136. styles,
  137. 0,
  138. 0,
  139. 100,
  140. 100,
  141. hwndparent,
  142. 0,
  143. win32gui.dllhandle,
  144. None,
  145. )
  146. win32gui.SendMessage(self.hwnd, commctrl.TB_BUTTONSTRUCTSIZE, 20, 0)
  147. def ShowWindow(self, mode):
  148. win32gui.ShowWindow(self.hwnd, mode)
  149. def AddButtons(self, *buttons):
  150. tbbuttons = ""
  151. for button in buttons:
  152. tbbuttons += button.toparam()
  153. return win32gui.SendMessage(
  154. self.hwnd, commctrl.TB_ADDBUTTONS, len(buttons), tbbuttons
  155. )
  156. def GetSafeHwnd(self):
  157. return self.hwnd
  158. class IEToolbar:
  159. """
  160. The actual COM server class
  161. """
  162. _com_interfaces_ = _ietoolbar_com_interfaces_
  163. _public_methods_ = _ietoolbar_methods_
  164. _reg_clsctx_ = pythoncom.CLSCTX_INPROC_SERVER
  165. # if you copy and modify this example, be sure to change the clsid below
  166. _reg_clsid_ = "{F21202A2-959A-4149-B1C3-68B9013F3335}"
  167. _reg_progid_ = "PyWin32.IEToolbar"
  168. _reg_desc_ = "PyWin32 IE Toolbar"
  169. def __init__(self):
  170. # put stubs for non-implemented methods
  171. for method in self._public_methods_:
  172. if not hasattr(self, method):
  173. print("providing default stub for %s" % method)
  174. setattr(self, method, Stub(method))
  175. def GetWindow(self):
  176. return self.toolbar.GetSafeHwnd()
  177. def Load(self, stream):
  178. # called when the toolbar is loaded
  179. pass
  180. def Save(self, pStream, fClearDirty):
  181. # called when the toolbar shall save its information
  182. pass
  183. def CloseDW(self, dwReserved):
  184. del self.toolbar
  185. def ShowDW(self, bShow):
  186. if bShow:
  187. self.toolbar.ShowWindow(win32con.SW_SHOW)
  188. else:
  189. self.toolbar.ShowWindow(win32con.SW_HIDE)
  190. def on_first_button(self):
  191. print("first!")
  192. self.webbrowser.Navigate2("http://starship.python.net/crew/mhammond/")
  193. def on_second_button(self):
  194. print("second!")
  195. def on_third_button(self):
  196. print("third!")
  197. def toolbar_command_handler(self, args):
  198. hwnd, message, wparam, lparam, time, point = args
  199. if lparam == self.toolbar.GetSafeHwnd():
  200. self._command_map[wparam]()
  201. def SetSite(self, unknown):
  202. if unknown:
  203. # retrieve the parent window interface for this site
  204. olewindow = unknown.QueryInterface(pythoncom.IID_IOleWindow)
  205. # ask the window for its handle
  206. hwndparent = olewindow.GetWindow()
  207. # first get a command target
  208. cmdtarget = unknown.QueryInterface(axcontrol.IID_IOleCommandTarget)
  209. # then travel over to a service provider
  210. serviceprovider = cmdtarget.QueryInterface(pythoncom.IID_IServiceProvider)
  211. # finally ask for the internet explorer application, returned as a dispatch object
  212. self.webbrowser = win32com.client.Dispatch(
  213. serviceprovider.QueryService(
  214. "{0002DF05-0000-0000-C000-000000000046}", pythoncom.IID_IDispatch
  215. )
  216. )
  217. # now create and set up the toolbar
  218. self.toolbar = IEToolbarCtrl(hwndparent)
  219. buttons = [
  220. ("Visit PyWin32 Homepage", self.on_first_button),
  221. ("Another Button", self.on_second_button),
  222. ("Yet Another Button", self.on_third_button),
  223. ]
  224. self._command_map = {}
  225. # wrap our parent window so we can hook message handlers
  226. window = win32ui.CreateWindowFromHandle(hwndparent)
  227. # add the buttons
  228. for i in range(len(buttons)):
  229. button = TBBUTTON()
  230. name, func = buttons[i]
  231. id = 0x4444 + i
  232. button.iBitmap = -2
  233. button.idCommand = id
  234. button.fsState = commctrl.TBSTATE_ENABLED
  235. button.fsStyle = commctrl.TBSTYLE_BUTTON
  236. button.iString = name
  237. self._command_map[0x4444 + i] = func
  238. self.toolbar.AddButtons(button)
  239. window.HookMessage(self.toolbar_command_handler, win32con.WM_COMMAND)
  240. else:
  241. # lose all references
  242. self.webbrowser = None
  243. def GetClassID(self):
  244. return self._reg_clsid_
  245. def GetBandInfo(self, dwBandId, dwViewMode, dwMask):
  246. ptMinSize = (0, 24)
  247. ptMaxSize = (2000, 24)
  248. ptIntegral = (0, 0)
  249. ptActual = (2000, 24)
  250. wszTitle = "PyWin32 IE Toolbar"
  251. dwModeFlags = DBIMF_VARIABLEHEIGHT
  252. crBkgnd = 0
  253. return (
  254. ptMinSize,
  255. ptMaxSize,
  256. ptIntegral,
  257. ptActual,
  258. wszTitle,
  259. dwModeFlags,
  260. crBkgnd,
  261. )
  262. # used for HKLM install
  263. def DllInstall(bInstall, cmdLine):
  264. comclass = IEToolbar
  265. # register plugin
  266. def DllRegisterServer():
  267. comclass = IEToolbar
  268. # register toolbar with IE
  269. try:
  270. print("Trying to register Toolbar.\n")
  271. hkey = winreg.CreateKey(
  272. winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Internet Explorer\\Toolbar"
  273. )
  274. subKey = winreg.SetValueEx(
  275. hkey, comclass._reg_clsid_, 0, winreg.REG_BINARY, "\0"
  276. )
  277. except WindowsError:
  278. print(
  279. "Couldn't set registry value.\nhkey: %d\tCLSID: %s\n"
  280. % (hkey, comclass._reg_clsid_)
  281. )
  282. else:
  283. print(
  284. "Set registry value.\nhkey: %d\tCLSID: %s\n" % (hkey, comclass._reg_clsid_)
  285. )
  286. # TODO: implement reg settings for standard toolbar button
  287. # unregister plugin
  288. def DllUnregisterServer():
  289. comclass = IEToolbar
  290. # unregister toolbar from internet explorer
  291. try:
  292. print("Trying to unregister Toolbar.\n")
  293. hkey = winreg.CreateKey(
  294. winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Internet Explorer\\Toolbar"
  295. )
  296. winreg.DeleteValue(hkey, comclass._reg_clsid_)
  297. except WindowsError:
  298. print(
  299. "Couldn't delete registry value.\nhkey: %d\tCLSID: %s\n"
  300. % (hkey, comclass._reg_clsid_)
  301. )
  302. else:
  303. print("Deleting reg key succeeded.\n")
  304. # entry point
  305. if __name__ == "__main__":
  306. import win32com.server.register
  307. win32com.server.register.UseCommandLine(IEToolbar)
  308. # parse actual command line option
  309. if "--unregister" in sys.argv:
  310. DllUnregisterServer()
  311. else:
  312. DllRegisterServer()
  313. else:
  314. # import trace utility for remote debugging
  315. import win32traceutil