Microsoft KB Archive/253915

= How To Set DHTML Event Properties from C++ =

Article ID: 253915

Article Last Modified on 7/13/2004

-

APPLIES TO


 * Microsoft Internet Explorer 4.0 128-Bit Edition
 * Microsoft Internet Explorer 4.01 Service Pack 2
 * Microsoft Internet Explorer 4.01 Service Pack 1
 * Microsoft Internet Explorer 4.01 Service Pack 2
 * Microsoft Internet Explorer 5.0
 * Microsoft Internet Explorer 5.01
 * Microsoft Internet Explorer 5.5

-



This article was previously published under Q253915



SUMMARY
This article describes how to set C++ event handlers on the DHTML event properties, such as put_onmousedown, from a WebBrowser control host, ActiveX control, or other C++ object.



MORE INFORMATION
The Dynamic HTML object model allows script to assign functions directly to event handlers using event properties:  function mousedownhandler {  // do stuff; }

function afterPageLoads {  someElement.onmousedown = mousedownhandler; }  To duplicate this form of event handling from C++, implement a simple COM object for each function object that implements only the IUnknown and IDispatch interfaces. Pass a reference to this object inside a variant to the appropriate event property. When the event fires, the IDispatch::Invoke function will be executed with a DISPID of 0 to signal the event.

The following example header file implements a template class that can be used to easily create these "function objects" in C++.

FUNCTIONOBJECT.H: // FunctionObject.h: interface for the CFunctionObject class. // // USAGE: // The user of this class is a C++ class (CYourClass) that must: //     // 1. Implement a member function on CYourClass of the form: //             // void MyEventCallback(DISPID id, VARIANT* pVarResult); // // This function will be called with the dispid set in // CreateEventFunctionObject. One event handler function can service // multiple event function objects. // // 2. When setting function object event handlers on MSHTML, use code of // this form: // // _variant_t varFO = //   CFunctionObject::CreateEventFunctionObject(this, //       MyEventCallback, DISPID_MOUSEDOWN); // [HTML object interface]->put_onmousedown(varFO); // // This syntax requires VC++ COM compiler support for the _variant_t class. // Otherwise, pass into the put_mousedown (or other MSHTML event prop) // a VARIANT containing the LPDISPATCH returned from // CreateEventFunctionObject. // // 3. Set all MSHTML function object event handlers to NULL before the // MSHTML document is destroyed: // //  VARIANT varNull; varNull.vt = VT_NULL; //  [HTML object interface]->put_onmousedown(varNull); // // At minimum, do this in an event handler for the HTML window object's // "onbeforeunload" event or WebBrowser control BeforeNavigate2. The // function objects will be stranded in memory if this isn't done before // the HTML document is unloaded.If you set the handlers to NULL in // BeforeNavigate2 then you should also account for the last case when // the application is being shutdown since BeforeNavigate2 will not be // called at that time.

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

template  class CFunctionObject : public IDispatch { typedef void (T::*EVENTFUNCTIONCALLBACK)(DISPID id, VARIANT* pVarResult);

public: CFunctionObject { m_cRef = 0; } ~CFunctionObject {}

HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject) {     *ppvObject = NULL;

if (IsEqualGUID(riid, IID_IUnknown)) *ppvObject = reinterpret_cast (this);

if (IsEqualGUID(riid, IID_IDispatch)) *ppvObject = reinterpret_cast (this);

if (*ppvObject) {        ((IUnknown*)*ppvObject)->AddRef; return S_OK; }     else return E_NOINTERFACE; }

DWORD __stdcall AddRef {     return InterlockedIncrement(&m_cRef); }

DWORD __stdcall Release {     if (InterlockedDecrement(&m_cRef) == 0) {        delete this; return 0; }     return m_cRef; }

STDMETHOD(GetTypeInfoCount)(unsigned int FAR* pctinfo) { return E_NOTIMPL; } STDMETHOD(GetTypeInfo)(unsigned int iTInfo, LCID lcid,      ITypeInfo FAR* FAR*  ppTInfo) { return E_NOTIMPL; } STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames,     unsigned int cNames, LCID lcid, DISPID FAR* rgDispId) { return S_OK; } STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid,     WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,      EXCEPINFO * pExcepInfo, UINT * puArgErr) {     if (DISPID_VALUE == dispIdMember) (m_pT->*m_pFunc)(m_id, pVarResult); else TRACE(_T("CFO Invoke dispid = %d\n"), dispIdMember); return S_OK; }

public: static LPDISPATCH CreateEventFunctionObject(T* pT,                       EVENTFUNCTIONCALLBACK pFunc, DISPID id) {     CFunctionObject* pFO = new CFunctionObject; pFO->m_pT = pT; pFO->m_pFunc = pFunc; pFO->m_id = id; return reinterpret_cast (pFO); }

protected: T* m_pT; EVENTFUNCTIONCALLBACK m_pFunc; DISPID m_id; long m_cRef; };

Keywords: kbhowto kbdhtml KB253915

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.