IDispatch возвращает DISP_E_UNKNOWNNAME для CommandBarButton.Style
У меня есть надстройка Visual Studio, которая содержит механизм сценариев, реализованный на C++. Надстройка может общаться только с Visual Studio, используя IDispatch
интерфейсы. Я нахожусь в процессе обновления с VS 2005 до VS 2010.
Надстройка делает серию IDispatch::Invoke()
вызовы, эквивалентные этому Visual Basic:
control = commandBar.Controls.Add(MsoControlType.msoControlButton)
control.Caption = "My button"
control.FaceId = 59
В VS 2005 это работало. Но в VS 2010 это не так. GetIDsOfNames()
возвращается DISP_E_UNKNOWNNAME
для "FaceId".
Обратите внимание, что "Заголовок" (который успешно) является свойством CommandBarControl
и "FaceId" (который не работает) является свойством CommandBarButton
подкласс. Имя класса для кнопки IDispatch*
является CommandBarControl
, Так что я думаю, что мне нужно CommandBarControl IDispatch*
к CommandBarButton IDispatch*
как-то.
В Visual Basic я мог бы написать:
button = DirectCast(control, CommandBarButton)
button.FaceId = 59
Но я не знаю что DirectCast()
делает внутренне. Если бы я это сделал, я, вероятно, был бы близок к решению этого.
Спасибо
1 ответ
Просто отвечаю на мой вопрос здесь... блеф.
Сначала я обнаружил, что если я запрашиваю IDispatch
за ICommandBarButton
затем запросите это для IDispatch
Я получаю другое IDispatch
(по другому адресу), который распознает ICommandBarButton
свойства. Это оставило меня с тем, как найти IID некоторого произвольного имени интерфейса, данного мне сценарием (в данном случае, строкой "CommandBarButton").
Но после дальнейших экспериментов, похоже, я могу IDispatch
к самому производному классу, просто запрашивая IUnknown
затем запросить это для IDispatch
снова. Никаких других IID или хитрости не требуется.
В ситуации, которую я описал в вопросе, Второй IDispatch*
возвращенный адрес отличается от первого и имеет тип _CommandBarButton
(обратите внимание на подчеркивание), где оригинал был типа ICommandBarControl
, _CommandBarButton
кажется, есть все функциональные возможности CommandBarButton
, (См. http://technet.microsoft.com/en-us/microsoft.visualstudio.commandbars.commandbarbutton%28v=vs.90%29)
Теперь я включаю этот код в свою подпрограмму, которая возвращает объект IDispatch в обработчик сценариев:
/*
* Query for IUnknown, then for IDispatch again. This APPEARS to return
* an IDispatch for the most derived class, thus exposing all methods and
* properties, and in the process returns a different IDispatch to the
* original (multiple dispatch interfaces on the same object).
*
* For example, calling ICommandBarControls.Add(msoControlButton) returns
* an IDispatch for the CommandBarControl base class, not the
* CommandBarButton class. After casting IDispatch to IUnknown and back,
* we get an IDispatch for _CommandBarButton, which appears to be almost,
* but not quite, a CommandBarButton. That is, CommandBarButton inherits
* just about every one of its properties and methods from
* _CommandBarButton -- certainly all the ones we're interested in anyway.
*/
HRESULT hr;
IUnknown *unknown;
hr = dispatch->QueryInterface(IID_IUnknown, (void**)&unknown);
if (hr == S_OK)
{
IDispatch *dispatch2 = NULL;
unknown->QueryInterface(IID_IDispatch, (void**)&dispatch2);
if (hr == S_OK)
{
dispatch->Release();
dispatch = dispatch2;
}
unknown->Release();
}