如何通过 COM 接口以编程方式激活 OLE 控件?

发布于 2024-11-08 12:34:00 字数 1405 浏览 0 评论 0原文

我有一个通过 ActiveX 嵌入按钮控件的应用程序。该按钮由第三方提供,它实现了一系列 ActiveX 接口(其中包括 IOleInPlaceObject)。我确实有一个对 IUnknown 的引用 按钮的实现。

我面临的问题是 IOleWindow::GetWindow函数总是返回错误;错误代码是 0x80004005,这显然是一个 常见的 HRESULT值表示E_FAIL。不太描述性。

就其价值而言,该对象还通过其 IDispatch 实现;查询成功,但属性值始终为零。

一些谷歌搜索表明我可能需要在 hWnd 属性产生有用值之前“激活”OLE 对象。有谁知道如何做到这一点,是否有一个专用的 COM 接口用于激活 OLE 对象?

有趣的是,该按钮确实似乎有一个窗口句柄,如间谍++

更新:我刚刚发现IQuickActivate 由我正在处理的按钮控件实现,可用于“快速”(咳咳...)激活项目。但是,填写 QACONTAINER 结构似乎很痛苦,所以我现在不想这样做。

I have an application which embeds a button control via ActiveX. 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

久而酒知 2024-11-15 12:34:00

事实证明,使用 IOleClientSite::DoVerb 函数发送 OLEIVERB_INPLACEACTIVATE 动词有所帮助,如下所示:

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 我正在尝试获取 HWNDCheckAndThrow 函数是一个辅助宏,如果给定的返回代码指示失败,它会产生异常。

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.

那些过往 2024-11-15 12:34:00

当然,按钮有一个有效的 HWND,否则它就不是一个按钮/窗口。
您可以使用 GetDlgItem 或类似方法获取任何控件的 HWND

我也不确定如何以编程方式激活对象。我会尝试以下操作:

  • 调用ReactivateAndUndo。根据文档,这可能会满足您的需要,恕我直言。
  • 如果您有控件 HWND (并且如果存在的话您肯定可以获得它) - 可以模拟用户鼠标输入

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文