开发者

How can I programmatically activate an OLE control via COM interfaces?

I have an application which embeds a button control via Ac开发者_Go百科tiveX. The button was provided by a third party, and it implements a whole range of ActiveX interfaces (among which is IOleInPlaceObject). I do have an reference to the IUnknown implementation of the button.

The problem I'm facing is that the IOleWindow::GetWindow function provided by the object always returns an error; the error code is 0x80004005 which is apparently a common HRESULT value meaning E_FAIL. Not too descriptive.

For what it's worth, the object also exposes a hWnd property via it's IDispatch implementation; querying it succeeds, but the value of the property is always zero.

A bit of googling suggested that I may need to 'activate' the OLE object before the hWnd property yields a useful value. Does anybody know how to do this, is there a dedicated COM interface for activating OLE objects?

Interestingly, the button does seem to have a window handle, as is visible in Spy++.

UPDATE: I just found IQuickActivate which is implemented by the button control I'm dealing with, and which can be used to 'quickly' (ahem...) activate an item. However, filling the QACONTAINER structure seems to be quite a pain, so I'll rather not do that right now.


It turned out that sending the OLEIVERB_INPLACEACTIVATE verb using the IOleClientSite::DoVerb function helped, like this:

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 is an IUnknownPtr for which I'm trying to get the HWND. The CheckAndThrow function is a helper macro which yields an exception in case the given return code indicates a failure.


Naturally button has a valid HWND, othrewise it wouldn't be a button/window. You may get the HWND of any control by using GetDlgItem or similar.

I'm not certain either about how to activate the object programmatically. I'd try the following:

  • Call ReactivateAndUndo. According to doc this may do what you need IMHO.
  • If you have the control HWND (and you definitely may obtain it if it exists) - it's possible to simulate user mouse input
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜