ietoolbar.py 10 KB

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