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();
}
Другие вопросы по тегам