is DISPID_VALUE reliable for invokes on IDispatchs

2019-02-17 12:41发布

问题:

Continuing from this question, i am confused whether DISPID_VALUE on IDispatch::Invoke() for script functions and properties (JavaScript in my case) can be considered standard and reliable for invoking the actual function that is represented by the IDispatch?
If yes, is that mentioned anywhere in MSDN?

Please note that the question is about if that behaviour can be expected, not what some interfaces i can't know in advance might look like.

A simple use case would be:

// usage in JavaScript
myObject.attachEvent("TestEvent", function() { alert("rhubarb"); }); 

// handler in ActiveX, MyObject::attachEvent(), C++
incomingDispatch->Invoke(DISPID_VALUE, IID_NULL, LOCALE_SYSTEM_DEFAULT,
                         DISPATCH_METHOD, par, res, ex, err);

edit: tried to clarify the question.

回答1:

It should be reliable for invokes on objects from scripts if the script defines it consistently. This should be the case for JScript/Javascript in MSHTML, but unfortunately there is really sparse documentation on the subject, I don't have any solid proof in-hand.

In my own experience, a Javascript function passed to attachEvent() should always be consistent- an object received that is a 'function' can only have one callable method that matches itself. Hence the default method is the only one you can find, with DISPID 0. Javascript functions don't ordinarily have member functions, although i'm sure there is a way for this to be possible. If it did have member functions, you would see them the same way as member functions on objects. Member functions in JScript will always be consistent with regard to IDispatchEx, according to the rules of expando functions, as any functions added to an object count as expandos.

IDispatchEx interface @ MSDN



回答2:

The default method or property that DISPID_VALUE invokes should be consistent for a given interface. That method/property has to be specified as DISPID_VALUE in the definition of the interface in the IDL for the type library. The only way it could change is if the owner of the interface released a new version of the interface that changed which method/property was the default but that would violate a fundamental rule of COM interfaces.



回答3:

As meklarian said, DISPID_VALUE (0) seems to work pretty consistantly for JS functions (thus it works great with a custom attachEvent). I've been using them this way for about a year, and it's always worked. I've also found with an activeX control embedded with an <object> tag that to get it to work consistently, I need to implement IConnectionPointContainer and IConnectionPoint for the main (object tag) IDispatch-implementing CComObject, but any others that I expose to javascript as return values from methods or properties (through Invoke) I have to implement attachEvent and detachEvent myself.

When using Connection Points, the IDispatch objects in question will expect events to be fired to the same DISPID as they are attached to on your IDispatch object..

see http://code.google.com/p/firebreath/source/browse/src/ActiveXPlugin/JSAPI_IDispatchEx.h for an example of implementing the ConnectionPoints.



回答4:

You can add DISPID's to a DISPINTERFACE, but you cannot change them once it has been published. If you need to, you can use IDispatch::GetIDsOfNames to map names to DISPIDs.

Pick up a copy of Inside Ole (2nd ed) and Inside Ole 2 (2nd ed) for a few bucks used on Amazon. It's a good reference for these obscure OLE incantations.