# -*- coding: latin-1 -*- # PyWin32 Internet Explorer Button # # written by Leonard Ritter (paniq@gmx.net) # and Robert Förtsch (info@robert-foertsch.com) """ This sample implements a simple IE Button COM server with access to the IWebBrowser2 interface. To demonstrate: * Execute this script to register the server. * Open Pythonwin's Tools -> Trace Collector Debugging Tool, so you can see the output of 'print' statements in this demo. * Open a new IE instance. The toolbar should have a new "scissors" icon, with tooltip text "IE Button" - this is our new button - click it. * Switch back to the Pythonwin window - you should see: IOleCommandTarget::Exec called. This is the button being clicked. Extending this to do something more useful is left as an exercise. Contribtions to this sample to make it a little "friendlier" welcome! """ # imports section import sys, os from win32com import universal from win32com.client import gencache, DispatchWithEvents, Dispatch from win32com.client import constants, getevents import win32com.server.register import win32com import pythoncom import win32api # This demo uses 'print' - use win32traceutil to see it if we have no # console. try: win32api.GetConsoleTitle() except win32api.error: import win32traceutil from win32com.axcontrol import axcontrol import array, struct # ensure we know the ms internet controls typelib so we have access to IWebBrowser2 later on win32com.client.gencache.EnsureModule('{EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}',0,1,1) # IObjectWithSite_methods = ['SetSite','GetSite'] IOleCommandTarget_methods = ['Exec','QueryStatus'] _iebutton_methods_ = IOleCommandTarget_methods + IObjectWithSite_methods _iebutton_com_interfaces_ = [ axcontrol.IID_IOleCommandTarget, axcontrol.IID_IObjectWithSite, # IObjectWithSite ] class Stub: """ this class serves as a method stub, outputting debug info whenever the object is being called. """ def __init__(self,name): self.name = name def __call__(self,*args): print('STUB: ',self.name,args) class IEButton: """ The actual COM server class """ _com_interfaces_ = _iebutton_com_interfaces_ _public_methods_ = _iebutton_methods_ _reg_clsctx_ = pythoncom.CLSCTX_INPROC_SERVER _button_text_ = 'IE Button' _tool_tip_ = 'An example implementation for an IE Button.' _icon_ = '' _hot_icon_ = '' def __init__( self ): # put stubs for non-implemented methods for method in self._public_methods_: if not hasattr(self,method): print('providing default stub for %s' % method) setattr(self,method,Stub(method)) def QueryStatus (self, pguidCmdGroup, prgCmds, cmdtextf): # 'cmdtextf' is the 'cmdtextf' element from the OLECMDTEXT structure, # or None if a NULL pointer was passed. result = [] for id, flags in prgCmds: flags |= axcontrol.OLECMDF_SUPPORTED | axcontrol.OLECMDF_ENABLED result.append((id, flags)) if cmdtextf is None: cmdtext = None # must return None if nothing requested. # IE never seems to want any text - this code is here for # demo purposes only elif cmdtextf == axcontrol.OLECMDTEXTF_NAME: cmdtext = "IEButton Name" else: cmdtext = "IEButton State" return result, cmdtext def Exec(self, pguidCmdGroup, nCmdID, nCmdExecOpt, pvaIn): print(pguidCmdGroup, nCmdID, nCmdExecOpt, pvaIn) print("IOleCommandTarget::Exec called.") #self.webbrowser.ShowBrowserBar(GUID_IETOOLBAR, not is_ietoolbar_visible()) def SetSite(self,unknown): if unknown: # first get a command target cmdtarget = unknown.QueryInterface(axcontrol.IID_IOleCommandTarget) # then travel over to a service provider serviceprovider = cmdtarget.QueryInterface(pythoncom.IID_IServiceProvider) # finally ask for the internet explorer application, returned as a dispatch object self.webbrowser = win32com.client.Dispatch(serviceprovider.QueryService('{0002DF05-0000-0000-C000-000000000046}',pythoncom.IID_IDispatch)) else: # lose all references self.webbrowser = None def GetClassID(self): return self._reg_clsid_ def register(classobj): import winreg subKeyCLSID = "SOFTWARE\\Microsoft\\Internet Explorer\\Extensions\\%38s" % classobj._reg_clsid_ try: hKey = winreg.CreateKey( winreg.HKEY_LOCAL_MACHINE, subKeyCLSID ) subKey = winreg.SetValueEx( hKey, "ButtonText", 0, winreg.REG_SZ, classobj._button_text_ ) winreg.SetValueEx( hKey, "ClsidExtension", 0, winreg.REG_SZ, classobj._reg_clsid_ ) # reg value for calling COM object winreg.SetValueEx( hKey, "CLSID", 0, winreg.REG_SZ, "{1FBA04EE-3024-11D2-8F1F-0000F87ABD16}" ) # CLSID for button that sends command to COM object winreg.SetValueEx( hKey, "Default Visible", 0, winreg.REG_SZ, "Yes" ) winreg.SetValueEx( hKey, "ToolTip", 0, winreg.REG_SZ, classobj._tool_tip_ ) winreg.SetValueEx( hKey, "Icon", 0, winreg.REG_SZ, classobj._icon_) winreg.SetValueEx( hKey, "HotIcon", 0, winreg.REG_SZ, classobj._hot_icon_) except WindowsError: print("Couldn't set standard toolbar reg keys.") else: print("Set standard toolbar reg keys.") def unregister(classobj): import winreg subKeyCLSID = "SOFTWARE\\Microsoft\\Internet Explorer\\Extensions\\%38s" % classobj._reg_clsid_ try: hKey = winreg.CreateKey( winreg.HKEY_LOCAL_MACHINE, subKeyCLSID ) subKey = winreg.DeleteValue( hKey, "ButtonText" ) winreg.DeleteValue( hKey, "ClsidExtension" ) # for calling COM object winreg.DeleteValue( hKey, "CLSID" ) winreg.DeleteValue( hKey, "Default Visible" ) winreg.DeleteValue( hKey, "ToolTip" ) winreg.DeleteValue( hKey, "Icon" ) winreg.DeleteValue( hKey, "HotIcon" ) winreg.DeleteKey( winreg.HKEY_LOCAL_MACHINE, subKeyCLSID ) except WindowsError: print("Couldn't delete Standard toolbar regkey.") else: print("Deleted Standard toolbar regkey.") # # test implementation # class PyWin32InternetExplorerButton(IEButton): _reg_clsid_ = "{104B66A9-9E68-49D1-A3F5-94754BE9E0E6}" _reg_progid_ = "PyWin32.IEButton" _reg_desc_ = 'Test Button' _button_text_ = 'IE Button' _tool_tip_ = 'An example implementation for an IE Button.' _icon_ = '' _hot_icon_ = _icon_ def DllRegisterServer(): register(PyWin32InternetExplorerButton) def DllUnregisterServer(): unregister(PyWin32InternetExplorerButton) if __name__ == '__main__': win32com.server.register.UseCommandLine(PyWin32InternetExplorerButton, finalize_register = DllRegisterServer, finalize_unregister = DllUnregisterServer)