1. Create a new ATL project named TestBehavior.
2. Click Finish when the ATL wizard opens.
3. In the TestBehavior project, add a reference to:
C:\WINDOWS\System32\stdole2.tlb
C:\WINDOWS\System32\MSHTML.TLB
C:\WINDOWS\System32\shdocvw.dll
objsafe.tlb (See KB article Q182598 from MSDN)
4. In Class Vew, add a new class using the ATL Simple Object tempalte.
5. Set the short name to CBehavior and then click Finish.
6. In the CBehavior.h file, implement the IElementBehavior, IElementBehaviorFactory, IElementNamespaceFactory, IElementNamespaceFactoryCallback, and IObjectSafety interfaces by chaning the class declaration to the following:
class ATL_NO_VTABLE CBehavior :
public ICBehavior,
public SHDOCVW::IElementBehavior,
public SHDOCVW::IElementBehaviorFactory,
public SHDOCVW::IElementNamespaceFactory,
public SHDOCVW::IElementNamespaceFactoryCallback,
public IObjectSafety
7. Add the following public declarations under the CBehavior(){} constructor in Behavior.h:
//IObjectSafety
STDMETHOD(GetInterfaceSafetyOptions)(REFIID riid, DWORD* pdwSupportedOptions, DWORD* pdwEnabledOptions);
STDMETHOD(SetInterfaceSafetyOptions)(REFIID riid, DWORD dwOptionsSetMask, DWORD dwEnabledOptions);
// IElementBehavior
STDMETHOD(Init)(IElementBehaviorSite* pBehaviorSite);
STDMETHOD(Notify)(LONG lEvent, VARIANT* pVar);
STDMETHOD(Detach)();
// IElementBehaviorFactory
STDMETHOD(FindBehavior)(BSTR bstrBehavior, BSTR bstrBehaviorUrl,
IElementBehaviorSite* pSite, IElementBehavior** ppBehavior);
// IElementNamespaceFactory
STDMETHOD(Create)(IElementNamespace * pNamespace);
// IElementNamespaceFactoryCallback
STDMETHOD(Resolve)(BSTR bstrNamespace, BSTR bstrTagName, BSTR bstrAttrs, IElementNamespace* pNamespace);
8. Add the following public members to the CBehavior class in the header file:
public:
// Members
IElementBehaviorSite *theBehaviorSite;
IElementBehaviorSiteOM2 *theBehaviorSiteOM2;
IHTMLBodyElement *theBodyElement;
IHTMLElement *theBodyHTMLElement;
IDispatch *theWindowDisp;
IDispatch *theDocumentDisp;
IHTMLDocument2 *theHTMLDocument;
IHTMLWindow2 *theHTMLWindow;
9. Create a private function declaration in the CBehavior class in the header file:
private:
void DoMyCustomThing(void);
10. In the Behavior.cpp file, add the following code:
void CBehavior::DoMyCustomThing(void)
{
BSTR s = L"Hello World!";
theBodyHTMLElement->put_innerHTML(s);
}
STDMETHODIMP CBehavior::Init(IElementBehaviorSite* pBehaviorSite)
{
HRESULT hr;
// Cache the IElementBehaviorSite interface pointer.
theBehaviorSite = pBehaviorSite;
theBehaviorSite->AddRef();
// Cache the IElementBehaviorSiteOM interface pointer.
hr = theBehaviorSite->QueryInterface(&theBehaviorSiteOM2);
return hr;
}
STDMETHODIMP CBehavior::Notify(LONG lEvent, VARIANT* pVar)
{
HRESULT hr = S_OK;
IDispatch *pWinDisp = NULL;
IHTMLElement *pElem = NULL;
IDispatch *pDisp = NULL;
IHTMLDocument2 *pDoc = NULL;
IHTMLWindow2 *pWindow = NULL;
switch (lEvent)
{
case BEHAVIOREVENT_CONTENTREADY:
// End tag of the master element has been parsed (we can access the element).
break;
case BEHAVIOREVENT_DOCUMENTREADY:
// HTML document has been parsed (we can access the document object model).
hr = theBehaviorSite->GetElement(&pElem);
if (hr)
goto Cleanup;
hr = pElem->get_document(&pDisp);
if (hr)
goto Cleanup;
hr = pDisp->QueryInterface(IID_IHTMLDocument2, (LPVOID *) &pDoc);
if (hr)
goto Cleanup;
hr = pDoc->get_parentWindow(&pWindow);
if (hr)
goto Cleanup;
//Custom Process
theBodyHTMLElement = pElem;
theDocumentDisp = pDisp;
theHTMLDocument = pDoc;
theHTMLWindow = pWindow;
this->DoMyCustomThing();
default:
break;
}
Cleanup:
if (pElem)
pElem->Release();
if (pDisp)
pDisp->Release();
if (pDoc)
pDoc->Release();
if (pWindow)
pWindow->Release();
if (pWinDisp)
pWinDisp->Release();
return hr;
}
STDMETHODIMP CBehavior::Detach()
{
if (theBehaviorSite)
theBehaviorSite->Release();
if (theBehaviorSiteOM2)
theBehaviorSiteOM2->Release();
return S_OK;
}
STDMETHODIMP CBehavior::FindBehavior(BSTR bstrBehavior, BSTR bstrBehaviorUrl,
IElementBehaviorSite* pSite, IElementBehavior** ppBehavior)
{
HRESULT hr = E_FAIL;
//For Debugging
//Sleep(10000);
CComObject * pBehavior;
hr = CComObject::CreateInstance(&pBehavior);
if (hr)
goto Cleanup;
hr = pBehavior->QueryInterface(IID_IElementBehavior, (void**)ppBehavior);
Cleanup:
return hr;
}
STDMETHODIMP CBehavior::Create(IElementNamespace * pNamespace)
{
return S_OK;
}
STDMETHODIMP CBehavior::Resolve(BSTR bstrNamespace, BSTR bstrTagName,
BSTR bstrAttrs, IElementNamespace* pNamespace)
{
return S_OK;
}
STDMETHODIMP CBehavior::GetInterfaceSafetyOptions(REFIID riid, DWORD* pdwSupportedOptions,
DWORD* pdwEnabledOptions)
{
return S_OK;
}
STDMETHODIMP CBehavior::SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionsSetMask,
DWORD dwEnabledOptions)
{
return S_OK;
}
11. From the build menu, click Build Solution.
12. Create a new HTML file and add the following HTML, with the exception of setting the clsid value to the value specified in the CBehavior.h file just above the CBehavior class declaration.
<HTML XMLNS:CUSTOM>
<HEAD>
<TITLE>Production Code</title>
<!-- DON'T FORGET TO CHANGE THE clsid: VALUE!!! -->
<object ID=objStart CLASSID="clsid:23B312F9-E480-4BB1-B8C6-F7E251015CE5"></object>
</HEAD>
<BODY Style="behavior:url(#objStart)" bColor='gray'>
</BODY>
</HTML>