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 |
<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
Factory.cpp FakePre-e5ef132755724088a5ebe21e151f4391-976b4c8096234b8d8d6ab0444256c835 Figure 7 Tags and Their COM Equivalents// 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->GetElement(&m_spElem); // Do something break; case BEHAVIOREVENT_DOCUMENTREADY: m_spSite->GetElement(&m_spElem); // Do something break; } return S_OK;
} ////////////////////////////////////////////////////////////////////// // Detach() HRESULT CBehavior::Detach(void) { if (m_spElem) m_spElem.Release();
return S_OK;
}
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. |