Как программно активировать элемент управления OLE через интерфейсы COM? - PullRequest
2 голосов
/ 19 мая 2011

У меня есть приложение, которое встраивает управление кнопками через ActiveX. Кнопка была предоставлена ​​третьей стороной, и она реализует целый ряд интерфейсов ActiveX (среди которых IOleInPlaceObject). У меня есть ссылка на реализацию кнопки IUnknown.

Проблема, с которой я сталкиваюсь, заключается в том, что функция IOleWindow::GetWindow, предоставляемая объектом, всегда возвращает ошибку; код ошибки 0x80004005, который, по-видимому, является общим значением HRESULT , означающим E_FAIL. Не слишком наглядно.

Для чего бы то ни было, объект также предоставляет свойство hWnd через реализацию IDispatch; запрос выполняется успешно, но значение свойства всегда равно нулю.

Немного погуглив, я предположил, что мне может понадобиться «активировать» объект OLE, прежде чем свойство hWnd даст полезное значение. Кто-нибудь знает, как это сделать, есть ли выделенный COM-интерфейс для активации объектов OLE?

Интересно, что кнопка имеет , кажется, имеет дескриптор окна, как это видно в Spy ++ .

ОБНОВЛЕНИЕ: Я только что нашел IQuickActivate, который реализован с помощью кнопки управления, с которой я имею дело, и который можно использовать для «быстрого» (хм ... ) активировать предмет. Однако заполнение структуры QACONTAINER выглядит довольно болезненно, поэтому я не буду сейчас этого делать.

Ответы [ 2 ]

1 голос
/ 08 августа 2011

Оказалось, что отправка глагола OLEIVERB_INPLACEACTIVATE с использованием функции IOleClientSite::DoVerb помогла, например:

IOleInPlaceObjectPtr oleInPlaceObj;
CheckAndThrow( unk->QueryInterface( &oleInPlaceObj ) ) );

HWND hwnd;
CheckAndThrow( oleInPlaceObj->GetWindow( &hwnd ) );

IOleObjectPtr oleObj;
if ( SUCCEEDED( unk->QueryInterface( &oleObj ) ) ) {
    IOleClientSitePtr clientSite;
    if ( SUCCEEDED( oleObj->GetClientSite( &clientSite ) ) ) {
        hr = oleObj->DoVerb( OLEIVERB_INPLACEACTIVATE,
                             NULL,
                             clientSite,
                             0,
                             NULL,
                             NULL );
        if ( SUCCEEDED( hr ) ) {
            if ( SUCCEEDED( oleInPlaceObj->GetWindow( &hwnd ) ) ) {
                return hwnd;
            }
        }
    }
}

unk - это IUnknownPtr, для которого я пытаюсь получить HWND. Функция CheckAndThrow является вспомогательным макросом, который выдает исключение в случае, если данный код возврата указывает на ошибку.

0 голосов
/ 19 мая 2011

Естественно, кнопка имеет действительный HWND, иначе это не будет кнопка / окно. Вы можете получить HWND любого элемента управления, используя GetDlgItem или аналогичный.

Я тоже не уверен, как активировать объект программно . Я бы попробовал следующее:

  • Звоните ReactivateAndUndo. Согласно доку это может делать то что нужно ИМХО.
  • Если у вас есть элемент управления HWND (и вы определенно можете получить его, если он существует) - можно смоделировать ввод данных мышью пользователя
...