Figure 2

Figure 2 COM Interface Methods

IElementalBehavior
Method
Description
Detach
Informs the behavior that it is being detached from the element
Init
Informs the behavior that it's been created
Notify
Notifies the behavior about the various stages in the initialization of both the host document and the attached element
IElementBehaviorFactory
Method
Description
FindBehavior
Instantiates the specified behavior
IElementBehaviorCategory (optional)
Method
Description
GetCategory
Returns the string with the name of the category that the behavior belongs to
IElementBehaviorRender (optional and obsolete in Internet Explorer 5.5)
Method
Description
Draw
Invoked to draw the user interface for the behavior
GetRenderInfo
Retrieves rendering information for the behavior
HitTestPoint
Indicates whether the specified point is contained in the behavior's area
Figure 3 Mouseover Behavior

  <PUBLIC:HTC>
<PUBLIC:ATTACH event="onmouseover" 
    handler="fnOver"/>
<PUBLIC:ATTACH event="onmouseout" 
    handler="fnOut"/>
<script LANGUAGE="jscript">
function fnOver()
{element.style.color="red";}
function fnOut()
{element.style.color="";}
</script>
</PUBLIC:HTC>

Figure 4 Binary Mouseover Behavior in C++

  // Behavior.h : Declaration of the CBehavior

#ifndef __BEHAVIOR_H_
#define __BEHAVIOR_H_

#include "resource.h"               // main symbols
#include "IElementBehaviorImpl.h"   // IElementBehavior
#include "DHTMLEvents.h"            // 

/////////////////////////////////////////////////////////////////////////////
// CBehavior
class ATL_NO_VTABLE CBehavior : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CBehavior, &CLSID_Behavior>,
    public IElementBehaviorImpl,
    public IDispatchImpl<IBehavior, &IID_IBehavior, &LIBID_MYBEHLib>
{
public:
    CBehavior()
    {
        m_pEventSink = NULL;
        m_dwCookie = 0;
    }

DECLARE_REGISTRY_RESOURCEID(IDR_BEHAVIOR)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CBehavior)
    COM_INTERFACE_ENTRY(IElementBehavior)
    COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

// IElementBehavior
public:
    STDMETHOD(Notify)(LONG lEvent, VARIANT *pVar);
    STDMETHOD(Init)(IElementBehaviorSite *pBehaviorSite);
    STDMETHOD(Detach)(void);

    CComPtr<IHTMLElement>           m_spElem;
    CComVariant                     m_oldColor;

private:
    CComPtr<IElementBehaviorSite>   m_spSite;
    CComObject<CDHTMLEvents>*       m_pEventSink;
    DWORD                           m_dwCookie;
};

#endif //__BEHAVIOR_H_


///////////////////////////////////////////////////////////////////////////


// Factory.h : Declaration of the CFactory

#ifndef __FACTORY_H_
#define __FACTORY_H_

#include "resource.h"       // main symbols
#include "behavior.h"       // IElementBehavior


/////////////////////////////////////////////////////////////////////////////
// CFactory
class ATL_NO_VTABLE CFactory : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CFactory, &CLSID_Factory>,
    public IObjectSafetyImpl<CFactory,INTERFACESAFE_FOR_UNTRUSTED_CALLER>,
    public IElementBehaviorFactory
{
public:
    CFactory()
    {
    }

DECLARE_REGISTRY_RESOURCEID(IDR_FACTORY)

BEGIN_COM_MAP(CFactory)
    COM_INTERFACE_ENTRY(IElementBehaviorFactory)
    COM_INTERFACE_ENTRY(IObjectSafety)
END_COM_MAP()

// IFactory
public:
    STDMETHOD(FindBehavior)(BSTR bstrBehavior, 
                            BSTR bstrBehaviorUrl,
                            IElementBehaviorSite* pSite,
                            IElementBehavior** ppBehavior);

// IObjectSafety override
    STDMETHOD(SetInterfaceSafetyOptions)(REFIID riid,
        DWORD dwOptionSetMask, DWORD dwEnabledOptions)
    {
         // Set the safety options we have been asked to set.
        m_dwCurrentSafety = m_dwCurrentSafety  & ~dwEnabledOptions | 
                            dwOptionSetMask;
        return S_OK;
    } 
};

#endif //__FACTORY_H_



///////////////////////////////////////////////////////////////////

Figure 5 Sink Object

  // DHTMLEvents.h : Declaration of the CDHTMLEvents

#ifndef __DHTMLEVENTS_H_
#define __DHTMLEVENTS_H_

#include "resource.h"  // main symbols
#include <mshtmdid.h>  // DHTML Behavior identifiers
#include <mshtmhst.h>  // DHTML Behavior interfaces
#include <mshtml.h>    // DHTML Object model

/////////////////////////////////////////////////////////////////////////////
// CDHTMLEvents

class CBehavior;

class ATL_NO_VTABLE CDHTMLEvents : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CDHTMLEvents, &CLSID_DHTMLEvents>,
    public IDispatchImpl<IDHTMLEvents, &IID_IDHTMLEvents, &LIBID_MYBEHLib>
{
public:
    CDHTMLEvents()
    {
        m_pBehavior = NULL;
    }

DECLARE_REGISTRY_RESOURCEID(IDR_DHTMLEVENTS)
DECLARE_NOT_AGGREGATABLE(CDHTMLEvents)

//DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CDHTMLEvents)
    COM_INTERFACE_ENTRY2(HTMLElementEvents, IDHTMLEvents)
    COM_INTERFACE_ENTRY2(HTMLAnchorEvents, IDHTMLEvents)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(IDHTMLEvents)
END_COM_MAP()

// IDispatchImpl override
    STDMETHOD(Invoke)(DISPID dispidMember,
                      REFIID riid,
                      LCID lcid,
                      WORD wFlags,
                      DISPPARAMS* pdispparams,
                      VARIANT* pvarResult,
                      EXCEPINFO* pexcepinfo,
                      UINT* puArgErr);

// Event Handlers (cfr. <PUBLIC:ATTACH>)
public:
    void OnMouseOver();
    void OnMouseOut();

// data members
    CBehavior *m_pBehavior;
};

#endif //__DHTMLEVENTS_H_

Figure 6 Implementation of the Behavior

Behavior.cpp

// Behavior.cpp : Implementation of CBehavior
#include "stdafx.h"
#include "MyBeh.h"
#include "DHTMLEvents.h"
#include "Behavior.h"

///////////////////////////////////////////////////////////////////////////// // CBehavior

////////////////////////////////////////////////////////////////////// // Init() HRESULT CBehavior::Init(IElementBehaviorSite *pBehaviorSite) { // Cache the IElementBehaviorSite interface pointer m_spSite = pBehaviorSite;

return S_OK; }

////////////////////////////////////////////////////////////////////// // Notify() HRESULT CBehavior::Notify(LONG lEvent, VARIANT *pVar) { // What happens here is equivalent to <PUBLIC:ATTACH> for // oncontentready and ondocumentready

switch(lEvent)
{
    case BEHAVIOREVENT_CONTENTREADY:
        m_spSite-&gt;GetElement(&amp;m_spElem);
        
        // Do something
        break;

    case BEHAVIOREVENT_DOCUMENTREADY:
        m_spSite-&gt;GetElement(&amp;m_spElem);
        
        // Do something
        break;
}

return S_OK;

} ////////////////////////////////////////////////////////////////////// // Detach() HRESULT CBehavior::Detach(void) { if (m_spElem) m_spElem.Release();

return S_OK;

}

Factory.cpp FakePre-e5ef132755724088a5ebe21e151f4391-976b4c8096234b8d8d6ab0444256c835 Figure 7 Tags and Their COM Equivalents

HTC Tag
COM Equivalent
<PUBLIC:ATTACH event="oncontentready" />
<PUBLIC:ATTACH event="ondocumentready" />
IElementBehavior::Notify
<PUBLIC:ATTACH event="Any DHTML Event" />
Sink object exposing IDispatch
<PUBLIC:PROPERTY name="Property">
IDispatch on behavior's coclass
<PUBLIC:METHOD name="Method">
IDispatch on behavior's coclass
<PUBLIC:EVENT name="Event">
Methods of IElementBehaviorSiteOM
addBehavior or behavior CSS
IElementBehaviorFactory
removeBehavior
IElementBehavior::Detach

Figure 8 Firing oninitcomplete

  if (m_spSiteOM)
{
    LONG cookie;
    
    HRESULT hr;
    hr = m_spSiteOM->GetEventCookie(L"oninitcomplete", &cookie);
        if (SUCCEEDED(hr))
        {
        IHTMLEventObject* pEvent;
        hr = m_spSiteOM->CreateEventObject(&pEvent);
        if (SUCCEEDED(hr))
        {
            m_spSiteOM->FireEvent(cookie, pEvent);
            pEvent->Release();
        }
    }
}

Figure 9 Sinking DHTML Events

  // DHTMLEvents.h : Declaration of the CDHTMLEvents

#ifndef __DHTMLEVENTS_H_
#define __DHTMLEVENTS_H_

#include "resource.h"      // main symbols
#include <mshtmdid.h>      // DHTML Behavior identifiers
#include <mshtmhst.h>      // DHTML Behavior interfaces
#include <mshtml.h>        // DHTML Object model

///////////////////////////////////////////////////////////////////////////
// CDHTMLEvents

class CBehavior;

class ATL_NO_VTABLE CDHTMLEvents : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CDHTMLEvents, &CLSID_DHTMLEvents>,
    public IDispatchImpl<IDHTMLEvents, &IID_IDHTMLEvents, &LIBID_MYBEHLib>
{
public:
    CDHTMLEvents()
    {
        m_pBehavior = NULL;
    }

DECLARE_REGISTRY_RESOURCEID(IDR_DHTMLEVENTS)
DECLARE_NOT_AGGREGATABLE(CDHTMLEvents)

//DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CDHTMLEvents)
    COM_INTERFACE_ENTRY2(HTMLElementEvents, IDHTMLEvents)
    COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

// IDispatchImpl override
    STDMETHOD(Invoke)(DISPID dispidMember,
                      REFIID riid,
                      LCID lcid,
                      WORD wFlags,
                      DISPPARAMS* pdispparams,
                      VARIANT* pvarResult,
                      EXCEPINFO* pexcepinfo,
                      UINT* puArgErr);

// Event Handlers (cfr. <PUBLIC:ATTACH>)
public:
    void OnMouseOver();
    void OnMouseOut();

// data members
    CBehavior *m_pBehavior;
};

#endif //__DHTMLEVENTS_H_

Figure 10 DHTML Events

  // DHTMLEvents.cpp : Implementation of CDHTMLEvents
#include "stdafx.h"
#include "MyBeh.h"
#include "DHTMLEvents.h"
#include "Behavior.h"

/////////////////////////////////////////////////////////////////////////////
// CDHTMLEvents

HRESULT CDHTMLEvents::Invoke(DISPID dispidMember, REFIID riid, LCID lcid,
    WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, 
    EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
    switch (dispidMember)
    {
    case DISPID_HTMLELEMENTEVENTS_ONMOUSEOVER:
        OnMouseOver();
        break;

    case DISPID_HTMLELEMENTEVENTS_ONMOUSEOUT:
            OnMouseOut();
        break;

    default:
        break;
    }

    return S_OK;
}


// OnMouseOver event handler
void CDHTMLEvents::OnMouseOver()
{
    // highlight the text
    if (m_pBehavior)
    {
            CComPtr<IHTMLStyle> spStyle;
            m_pBehavior->m_spElem->get_style(&spStyle);
            spStyle->put_color(CComVariant(L"red"));    
    }
}

// OnMouseOut event handler
void CDHTMLEvents::OnMouseOut()
{
    // restore the text
    if (m_pBehavior)
    {
            CComPtr<IHTMLStyle> spStyle;
            m_pBehavior->m_spElem->get_style(&spStyle);
            spStyle->put_color(m_pBehavior->m_oldColor);    
    }
}

Figure 15 Rendering Methods

Method
Description
Draw
Renders a behavior in the browser's client area.
GetPainterInfo
Provides MSHTML with the information it needs in order to issue proper calls to Draw. In particular, it relates the required z-order and whether DirectX is being used or not.
HitTestPoint
MSHTML calls this method when calls are made to elementFromPoint on the attached element. The implementation must check whether the point is within the behavior's area.
OnResize
Called by MSHTML to allow a behavior to resize when the element to which it is attached gets resized.