|
|
|
|
# -*- 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)
|