我们已经知道如何用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;
- }
- };