I have a Visual Studio add-in, which contains a scripting engine implemented in C++.
The add-in can only communicate with Visual Studio using IDispatch
interfaces.
I am in the process of upgrading it from VS 2005 to VS 2010.
The add-in makes a series of IDispatch::Invoke()
calls equivalent to this Visual Basic:
control = commandBar.Controls.Add(MsoControlType.msoControlButton)
control.Caption = "My button"
control.FaceId = 59
In VS 2005, this used to work. But in VS 2010 it doesn't. GetIDsOfNames()
returns DISP_E_UNKNOWNNAME
for "FaceId".
Note that "Caption" (which succeeds) is a property of CommandBarControl
, and "FaceId" (which fails) is a property of the CommandBarButton
subclass. The classname for the button's IDispatch*
is CommandBarControl
. So I think I need to downcast the CommandBarControl IDispatch*
to a CommandBarButton IDispatch*
somehow.
In Visual Basic I could write:
button = DirectCast(control, CommandBarButton)
button.FaceId = 59
But I don't know what DirectCast()
does internally. If I did I'd probably be close to solving this.
Thanks
Just answering my own question here... bleah.
First I discovered that if I query the
IDispatch
forICommandBarButton
, then query that forIDispatch
, I get a differentIDispatch
(at a different address) which recognises theICommandBarButton
properties. That left me with how to find the IID of some arbitrary interface name given to me by the script (in this case, the string "CommandBarButton").But after more experimenting, it looks like I can downcast an
IDispatch
to the most derived class by simply querying forIUnknown
, then querying that forIDispatch
again. No other IIDs or trickery needed.In the situation I described in the question, The second
IDispatch*
returned is a different address to the first, and is of type_CommandBarButton
(note the underscore) where the original was of typeICommandBarControl
._CommandBarButton
seems to have all the functionality ofCommandBarButton
. (See http://technet.microsoft.com/en-us/microsoft.visualstudio.commandbars.commandbarbutton%28v=vs.90%29)I now include this code in my routine which returns an IDispatch object to the script engine: