218 lines
6.9 KiB
Python
218 lines
6.9 KiB
Python
# -*- 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 pythoncom
|
|
import win32api
|
|
import win32com
|
|
import win32com.server.register
|
|
from win32com import universal
|
|
from win32com.client import Dispatch, DispatchWithEvents, constants, gencache, getevents
|
|
|
|
# This demo uses 'print' - use win32traceutil to see it if we have no
|
|
# console.
|
|
try:
|
|
win32api.GetConsoleTitle()
|
|
except win32api.error:
|
|
import win32traceutil
|
|
|
|
import array
|
|
|
|
from win32com.axcontrol import axcontrol
|
|
|
|
# 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,
|
|
)
|