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