我們已經知道如何用VC++訪問並調用javascript中的函數了。那麼如何在VC++中實現一個函數,以便在javascript中進行調用呢?比如,我們用VC++提供一個函數綁定某個網頁元素的onclick事件,當事件到達時,可以調用VC++中的這個函數。
其實,在javascript中,函數(function)也是一個對象。從VC++的角度來看,當我們調用function時,事實上是在調用function對象的0方法(也就是預設方法)。什麼是0方法呢?任何對象都為自己管理的所有成員(包括所有屬性和方法)分配一個唯一的DISPID,當調用對象的某個方法時,先通過方法名稱取得它的DISPID,然後使用DISPID調用對象的Invoke方法(如果提供了IDispatchEx介面,則調用InvokeEx方法)。當某個成員的DISPID等於0時,它就是這個對象的預設屬性或預設方法(我們就叫做0方法吧)。0方法的好處就在於,在實際的調用中,我們可以不必指定0方法的名稱從而完成調用。如果大家使用過VB編程,就知道0屬性或0方法是很普遍的用法了。
於是,我們就可以用VC++實現一個COM對象,繼承自IDispatch介面,並提供一個0方法,然後用這個COM對象綁定網頁元素的onclick事件就可以了。另外,要想使這個COM對象支援帶this指標的調用,就必須繼承自IDispatchEx介面。在實戰中,綁定網頁元素的事件只需繼承自IDispatch介面就可以了。
下面,我們就實現一個帶0方法的COM對象
- // IVCFunction
- [
- object,
- uuid("E0B4E698-945D-4CD5-BF8B-ECE65DA39DFE"),
- dual, helpstring("IVCFunction Interface"),
- pointer_default(unique)
- ]
- __interface IVCFunction : IDispatch
- {
- };
- // CVCFunction
- [
- coclass,
- default(IVCFunction),
- threading(apartment),
- vi_progid("PIMShellDemo.VCFunction"),
- progid("PIMShellDemo.VCFunction.1"),
- version(1.0),
- uuid("F4BA402B-3A59-49CC-85A1-12E91E5A0F99"),
- helpstring("VCFunction Class")
- ]
- class ATL_NO_VTABLE CVCFunction :
- public IDispatchImpl<IVCFunction>
- {
- public:
- CVCFunction()
- {
- }
- DECLARE_PROTECT_FINAL_CONSTRUCT()
- HRESULT FinalConstruct()
- {
- return S_OK;
- }
- void FinalRelease()
- {
- }
- public:
- STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,
- DISPPARAMS* pDispParams, VARIANT* pvarResult,
- EXCEPINFO* pExcepInfo, UINT* puArgErr)
- {
- //只支援0方法
- if(dispidMember!=0)
- return E_INVALIDARG;
- //如果是通過attachEvent綁定網頁元素的事件,那麼傳入的第一個參數就是event對象
- MSHTML::IHTMLEventobjPtr pEvent=pDispParams->rgvarg[0].pdispVal;
- //event.type
- _bstr_t bstrType=pEvent->type;
- //
- if(::wcscmp(bstrType,L"click")==0)
- {
- //這裡執行響應onclick事件的代碼
- }
-
- return S_OK;
- }
- };