🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.nativeapi
Article #13548

Re: BHO question

#13548
From: Remy Lebeau (TeamB)
Date: Wed, 08 Oct 2003 23:43
288 lines
10095 bytes
"Martin C" <martinc@aol.com> wrote in message
news:3f84957c@newsgroups.borland.com...

> So can someone tell me please were I can find any
> sample/tutorial on using BHO under BCB.
>
> P.S. If anyone have a sample that will be more than great...

There's nothing too special about making a BHO:

1) Create a new ActiveX Library containing a TypeLibrary with an interface
and CoClass.  The easiest way to make that is to use the "File | New |
ActiveX | ActiveX Library" and "File | New | ActiveX | COM Object" wizards.
Make the COM object apartment-threaded, marked with OleAutomation, and no
events support.

2) In the resulting TypeLibrary, leave the interface empty (containing no
methods) and make it derive from IDispatch.

3) In the interface's generated Impl unit, add IObjectWithSiteImpl and
IDispatchImpl to the Impl class's ancestor list, and add IDispatch and
IObjectWithSite to the COM_MAP

4) Add an IWebBrowser2 member to the class.  Optionally, if you plan on
intercepting the browser's events, then add an IConnectionPointContainer
member and a DWORD member as well.

5) Update the Impl class's UpdateRegistry() method to register the BHO with
IE when the interface itself it registered with the OS in general.

6) Override the inherited IObjectWithSite::SetSite() method.  This is where
the browser will give your BHO its IWebBrowser2 instance for your use.

7) If you plan on supporting the browser's events, then also override the
IDispatch::Invoke() method.  This is where the events will come through.

8) open up the main source file for the project and edit the DllEntryPoint()
to look for explorer.exe.  Since Windows Explorer is integrated with
Internet Explorer starting with IE4, BHOs can be loaded by both Windows
Explorer and IE for different purposes.  If you only want to wok with IE,
then you need to have DllEntryPoint() return FALSE if explorer.exe is
detected.


Now, with all of that said, here is a snippet from my own BHO implementation
(names changed to protect the innocent):


    --- MyBHO.cpp ---

    // auto-generated stuff ...

    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
    {
        if (reason == DLL_PROCESS_ATTACH)
        {
            TCHAR pszLoader[MAX_PATH+1] = {0};
            GetModuleFileName(NULL, pszLoader, MAX_PATH);
            if( AnsiSameText(pszLoader, "explorer.exe") )
                return FALSE;
            _Module.Init(ObjectMap, hinst);
            DisableThreadLibraryCalls(hinst);
        }
        return TRUE;
    }

    // more auto-generated stuff ...


    --- MyBHOImpl.h ---

    // MYBHOIMPL.H : Declaration of the TMyBHOImpl

    #ifndef MyBHOImplH
    #define MyBHOImplH

    #include "MyBHO_TLB.H"
    #include <Exdisp.h> // for IWebBrowser2


////////////////////////////////////////////////////////////////////////////
/
    // TMyBHOImpl     Implements IMyBHO, default interface of MyBHO
    // ThreadingModel : Apartment
    // Dual Interface : FALSE
    // Event Support  : FALSE
    // Default ProgID : MyBHO.MyBHO
    // Description    : My Browser Helper Object

////////////////////////////////////////////////////////////////////////////
/
    class ATL_NO_VTABLE TMyBHOImpl :
        public CComObjectRootEx<CComSingleThreadModel>,
        public CComCoClass<TMyBHOImpl, &CLSID_MyBHO>,
        public IObjectWithSiteImpl<TMyBHOImpl>,
        public IDispatchImpl<IMyBHO, &IID_IMyBHO, &LIBID_MyBHO>
    {
    private:
        CComQIPtr<IWebBrowser2, &IID_IWebBrowser2> m_spWebBrowser2;
        CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer>
m_spCPC;
        DWORD m_dwCookie;

        static void UpdateBrowserRegistration(REFCLSID rclsid, BOOL
bRegister);
        HRESULT ManageConnection(bool DoAdvise);

    public:
        TMyBHOImpl();

        STDMETHOD(SetSite)(IUnknown *pUnkSite);
        STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, LCID lcid, WORD
wFlags, DISPPARAMS* pDispParams, VARIANT* pvarResult, EXCEPINFO* pExcepInfo,
UINT* puArgErr);

        // Data used when registering Object
        //
        DECLARE_THREADING_MODEL(otApartment);
        DECLARE_PROGID("MyBHO.MyBHO");
        DECLARE_DESCRIPTION("My Browser Helper Object");

        // Function invoked to (un)register object
        //
        static HRESULT WINAPI UpdateRegistry(BOOL bRegister)
        {
            TTypedComServerRegistrarT<TURLStripperImpl>
            regObj(GetObjectCLSID(), GetProgID(), GetDescription());
            UpdateBrowserRegistration(GetObjectCLSID(), bRegister);
            return regObj.UpdateRegistry(bRegister);
        }

        BEGIN_COM_MAP(TMyBHOImpl)
            COM_INTERFACE_ENTRY(IMyBHO)
            COM_INTERFACE_ENTRY2(IDispatch, IMyBHO)
            COM_INTERFACE_ENTRY(IObjectWithSite)
        END_COM_MAP()
    };

    #endif //MyBHOImplH


    --- MyBHOImpl.cpp ---

    // MYBHOIMPL : Implementation of TMyBHOImpl (CoClass: MyBHO, Interface:
IMyBHO)

    #include <vcl.h>
    #pragma hdrstop

    #include "MYBHOIMPL.H"
    #include <exdispid.h>
    #include <mshtml.h>


////////////////////////////////////////////////////////////////////////////
/
    // TMyBHOImpl

    TMyBHOImpl::TMyBHOImpl()
        : m_dwCookie(0)
    {
    }

    void TMyBHOImpl::UpdateBrowserRegistration(REFCLSID rclsid, BOOL
bRegister)
    {
        OLECHAR str[64] = {0};
        StringFromGUID2(rclsid, str, 64);

        HKEY hKey = NULL;
        HKEY hTempKey = NULL;
        DWORD Disposition;

        if( RegCreateKeyEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper
Objects", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hKey,
&Disposition) == ERROR_SUCCESS )
        {
            if( bRegister )
            {
                if( RegCreateKeyEx(hKey, AnsiString(str).c_str(), 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hTempKey, &Disposition) ==
ERROR_SUCCESS )
                {
                    RegSetValueEx(hTempKey, "", 0, REG_SZ,
reinterpret_cast<BYTE*>("My BHO"), 7);
                    RegCloseKey(hTempKey);
                }
            }
            else
                RegDeleteKey(hKey, AnsiString(str).c_str());

            RegCloseKey(hKey);
        }
    }

    STDMETHODIMP TMyBHOImpl::SetSite(IUnknown *pUnkSite)
    {
        HRESULT hr = IObjectWithSiteImpl<TMyBHOImpl>::SetSite(pUnkSite);
        if( FAILED(hr) )
            return hr;

        // Retrieve and store the IWebBrowser2 pointer
        m_spWebBrowser2 = pUnkSite;
        if( m_spWebBrowser2 == NULL )
            return E_INVALIDARG;

        // Retrieve and store the IConnectionPointerContainer pointer
        m_spCPC = m_spWebBrowser2;
        if( m_spCPC == NULL )
            return E_POINTER;

        // Connect to the container for receiving event notifications
        return ManageConnection(true);
    }

    HRESULT TMyBHOImpl::ManageConnection(bool DoAdvise)
    {
        if( m_spCPC )
        {
            if( DoAdvise )
                return AtlAdvise(m_spCPC, GetUnknown(),
DIID_DWebBrowserEvents2, &m_dwCookie);
            else
                return AtlUnadvise(m_spCPC, DIID_DWebBrowserEvents2,
m_dwCookie);
        }

        return S_OK;
    }

    STDMETHODIMP TMyBHOImpl::Invoke(DISPID dispidMember, REFIID riid, LCID
lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pvarResult, EXCEPINFO*
pExcepInfo, UINT* puArgErr)
    {
        switch( dispidMember )
        {
            case DISPID_BEFORENAVIGATE2:
            {
                /*
                void BeforeNavigate2(IDispatch *pDisp, VARIANT *&url,
VARIANT *&Flags, VARIANT *&TargetFrameName, VARIANT *&PostData, VARIANT
*&Headers, VARIANT_BOOL *&Cancel)
                */

                if( !pDispParams )
                    return E_INVALIDARG;

                CComQIPtr<IWebBrowser2, &IID_IWebBrowser2>
m_spWebBrowser2Tmp;
                m_spWebBrowser2Tmp = pDispParams->rgvarg[6].pdispVal;

                if( m_spWebBrowser2Tmp )
                {
                    // manipulate the browser as needed
                }
                break;

            case DISPID_NEWWINDOW2:
                /*
                void NewWindow2(IDispatch **&ppDisp, VARIANT_BOOL *&Cancel)
                */

                if( !pDispParams )
                    return E_INVALIDARG;

                // only allow a new window if SHIFT or CONTROL are held down
                if( ((GetKeyState(VK_SHIFT) & 0x8000) == 0) &&
((GetKeyState(VK_CONTROL) & 0x8000) == 0) )
                    *(pDispParams->rgvarg[0].pboolVal) = VARIANT_TRUE;

                break;

            case DISPID_ONQUIT:
                /*
                void OnQuit()
                */

                ManageConnection(false);
                break;
        }

        return S_OK;
    }


Gambit
Technical Details
Message-ID: <3f84a0b8@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!sn-xit-02!sn-xit-06!sn-xit-09!supernews.com!news.maxwell.syr.edu!small1.nntp.aus1.giganews.com!border1.nntp.aus1.giganews.com!nntp.giganews.com!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mail
References: <3f84957c@newsgroups.borland.com>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 10cc67,15b7dd6889830f4f
X-Google-Attributes: gid10cc67,public
X-Google-ArrivalTime: 2003-10-08 16:59:16 PST
From: "Remy Lebeau \(TeamB\)" <gambit47.no.spam@no.spam.yahoo.com>
Newsgroups: borland.public.cppbuilder.nativeapi
References: <3f84957c@newsgroups.borland.com>
Subject: Re: BHO question
Date: Wed, 8 Oct 2003 16:43:18 -0700
Lines: 290
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2800.1158
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
NNTP-Posting-Host: 67.22.137.75
Message-ID: <3f84a0b8@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1065656504 67.22.137.75 (8 Oct 2003 16:41:44 -0700)
Path: arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!sn-xit-02!sn-xit-06!sn-xit-09!supernews.com!news.maxwell.syr.edu!small1.nntp.aus1.giganews.com!border1.nntp.aus1.giganews.com!nntp.giganews.com!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mail