2

我们在 VB.NET 2010 中实现了一个基于 WinForms UserControl 的 ActiveX 控件。它通过 COM Interop 在 VBA UserForms 上使用。一切正常 - 除了一件事。当输入焦点从 ActiveX 移动到用户窗体上的另一个 VBA 本机控件(比如命令按钮)时,我们无法检测到这个东西。在这种情况下,不会触发诸如 Leave 或 Validating 等标准 WinForms 控件事件。

如何跟踪它(更好地使用“托管”方式,没有 WinAPI 技巧)?

请注意,我们的 UserControl 包含其他 WinForms 控件,例如按钮或文本框,因此无论选择了哪个组成部分,我们都需要将整个控件公开为 ActiveX 的 LostFocus 事件。

4

1 回答 1

1

我认为您无法使用托管 API 解决此问题。如果您对 P/invoke 没问题,SetWindowsHookEx //将是可行的方法。WH_CBTHCBT_SETFOCUS

您可能会遇到另一个怪癖。尝试将文本光标(插入符号)放入托管控件内的任何可编辑字段中,然后使用 Alt-Tab 切换到另一个应用程序。然后使用 Alt-Tab 返回您的应用程序。光标是还在原处还是消失了?在后一种情况下,您在HCBT_ACTIVATE.

ActiveX 控件 COM 接口的 .NET Framework 实现UserControl需要来自 ActiveX 主机的一些协议调用。例如,它期望IOleInPlaceObject::UIDeactivate在焦点移到外部的另一个位置时被调用UserControl,或者IOleInPlaceActiveObject::OnFrameWindowActivate method在宿主的框架窗口变为非活动状态时被调用,因为用户已经切换到另一个应用程序。您可以研究框架源代码以获取更多详细信息。

不幸的是,并不是所有的 ActiveX 容器都严格遵循这个协议。显然,VBA 没有。一个最终的解决方案是实现一个中间层(最好在 C++/ATL 中),它可以作为 VBA 主机的 ActiveX 控件和托管 .NET 控件的 ActiveX 容器,从而解决所有这些问题。这是可行的,但相当乏味。

于 2013-10-08T13:51:59.260 回答