Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>From what I've read, you should be using the <code>OBJECT</code> tag and the <code>SCRIPT for</code> tag to hook up ATL/COM events in HTML. Something like this:</p> <pre><code>&lt;object id="myCtrlObj" classid="CLSID:00000000-0000-0000-0000-000000000003" height="32" width="32"/&gt; &lt;script language="javascript" id="myCtrlHandler1" event="OnCtrlEvent1()" for="myCtrlObj"&gt; alert("OnCtrlEvent1 fired"); &lt;/script&gt; &lt;script language="javascript" id="myCtrlHandler2" event="OnCtrlEvent2(reason)" for="myCtrlObj"&gt; alert("OnCtrlEvent2 fired with parameter: " + reason.toString()); &lt;/script&gt; </code></pre> <p>Because you're using JScript, I sometimes like to cheat and make an IDispatch VARIANT property simulate the behavior of an event. In the following JScript code snippet note how OnCtrlEvent1 and OnCtrlEvent2 are being assigned to functions:</p> <pre><code>function tst() { var ctrl = new ActiveXObject("MyControl.Ctrl"); ctrl.OnCtrlEvent1 = myevent1; ctrl.OnCtrlEvent2 = myevent2; ctrl.CtrlMethod1(); ctrl.CtrlMethod2(); } function myevent1() { alert("Event1"); } function myevent2(reason) { alert("Event2 " + reason.toString()); } </code></pre> <p>The trickery is done by handling it as a property in the IDL. Where those JScript functions are being passed to us as VARIANTs containing invokable IDispatch interfaces. Here's my MyControl.idl:</p> <pre><code>import "oaidl.idl"; import "ocidl.idl"; [ object, // uuid replaced with dummy uuid(00000000-0000-0000-0000-000000000000) dual, nonextensible, helpstring("ICtrl Interface"), pointer_default(unique) ] interface ICtrl : IDispatch{ [id(1), helpstring("method CtrlMethod1")] HRESULT CtrlMethod1(void); [id(2), helpstring("method CtrlMethod2")] HRESULT CtrlMethod2(void); [propget, id(3), helpstring("property OnCtrlEvent1")] HRESULT OnCtrlEvent1([out, retval] VARIANT* pVal); [propput, id(3), helpstring("property OnCtrlEvent1")] HRESULT OnCtrlEvent1([in] VARIANT newVal); [propget, id(4), helpstring("property OnCtrlEvent2")] HRESULT OnCtrlEvent2([out, retval] VARIANT* pVal); [propput, id(4), helpstring("property OnCtrlEvent2")] HRESULT OnCtrlEvent2([in] VARIANT newVal); }; [ // uuid replaced with dummy uuid(00000000-0000-0000-0000-000000000001), version(1.0), helpstring("MyControl 1.0 Type Library") ] library MyControlLib { importlib("stdole2.tlb"); [ // uuid replaced with dummy uuid(00000000-0000-0000-0000-000000000003) helpstring("Ctrl Class") ] coclass Ctrl { [default] interface ICtrl; }; }; </code></pre> <p>Here's my Ctrl.h where you see the JScript functions will be saved in VARIANT members:</p> <pre><code>class ATL_NO_VTABLE CCtrl : public CComObjectRootEx&lt;CComSingleThreadModel&gt;, public CComCoClass&lt;CCtrl, &amp;CLSID_Ctrl&gt;, public IDispatchImpl&lt;ICtrl, &amp;IID_ICtrl, &amp;LIBID_MyControlLib, /*wMajor =*/ 1, /*wMinor =*/ 0&gt; { public: DECLARE_REGISTRY_RESOURCEID(IDR_CTRL) BEGIN_COM_MAP(CCtrl) COM_INTERFACE_ENTRY(ICtrl) COM_INTERFACE_ENTRY(IDispatch) END_COM_MAP() DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct() { return S_OK; } void FinalRelease() { } public: STDMETHOD(CtrlMethod1)(void); STDMETHOD(CtrlMethod2)(void); STDMETHOD(get_OnCtrlEvent1)(VARIANT* pVal); STDMETHOD(put_OnCtrlEvent1)(VARIANT newVal); STDMETHOD(get_OnCtrlEvent2)(VARIANT* pVal); STDMETHOD(put_OnCtrlEvent2)(VARIANT newVal); private: CComVariant m_ctrlEvent1; CComVariant m_ctrlEvent2; STDMETHOD(Invoke_CtrlEvent1)(); STDMETHOD(Invoke_CtrlEvent2)(LONG nReason); }; OBJECT_ENTRY_AUTO(__uuidof(Ctrl), CCtrl) </code></pre> <p>In Ctrl.cpp the trickery is we look for the JScript function's IDispatch interfaces in those VARIANTs and with our 'knowledge' of the parameters, we invoke each event with the right parameters:</p> <pre><code>#include "stdafx.h" #include "Ctrl.h" STDMETHODIMP CCtrl::CtrlMethod1(void) { Invoke_CtrlEvent1(); return S_OK; } STDMETHODIMP CCtrl::CtrlMethod2(void) { Invoke_CtrlEvent2(12345); return S_OK; } STDMETHODIMP CCtrl::get_OnCtrlEvent1(VARIANT* pVal) { VariantInit(pVal); return VariantCopy(pVal, &amp;m_ctrlEvent1); return S_OK; } STDMETHODIMP CCtrl::put_OnCtrlEvent1(VARIANT newVal) { m_ctrlEvent1 = newVal; return S_OK; } STDMETHODIMP CCtrl::get_OnCtrlEvent2(VARIANT* pVal) { VariantInit(pVal); return VariantCopy(pVal, &amp;m_ctrlEvent2); } STDMETHODIMP CCtrl::put_OnCtrlEvent2(VARIANT newVal) { m_ctrlEvent2 = newVal; return S_OK; } STDMETHODIMP CCtrl::Invoke_CtrlEvent1() { if (m_ctrlEvent1.vt != VT_DISPATCH) { return S_OK; } DISPPARAMS DispParams = { 0, 0, 0, 0 }; VARIANT Var = { 0 }; return V_DISPATCH(&amp;m_ctrlEvent1)-&gt;Invoke((DISPID) 0, IID_NULL, 0, DISPATCH_METHOD, &amp;DispParams, &amp;Var, NULL, NULL); } STDMETHODIMP CCtrl::Invoke_CtrlEvent2(LONG nReason) { if (m_ctrlEvent1.vt != VT_DISPATCH) { return S_OK; } VARIANTARG Arg = {0}; Arg.vt = VT_I4; Arg.lVal = nReason; DISPPARAMS DispParams = { &amp;Arg, 0, 1, 0 }; VARIANT Var = { 0 }; return V_DISPATCH(&amp;m_ctrlEvent2)-&gt;Invoke((DISPID) 0, IID_NULL, 0, DISPATCH_METHOD, &amp;DispParams, &amp;Var, NULL, NULL); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload