在 VB6 中禁用自动停用 .NET ActiveX 控件的最佳实践?

Best Practice for disable automatically deactivating .NET ActiveX Controls in VB6?

提问人:Michael 提问时间:11/6/2023 最后编辑:Michael 更新时间:11/13/2023 访问量:89

问:

我正在移植一个旧的 Visual Basic 6 程序。我在 WPF 中部署了迁移的组件,并将该组件作为 ActiveX 控件(C#、Windows 窗体、.NET Framework)提供,以便在 VB6 应用程序中临时添加控件(将移植过程分解为更小的部分)。

如果将外部 ActiveX 控件添加到 VB6 中,则效果很好,例如

Private Sub Form_Load()
    Set mCtrl = Controls.Add("ActiveX_Control.UserControl1", "UserControl1", Me)
    Set mActiveX = mCtrl.object
    mCtrl.Visible = True
End Sub

但是,如果我将控件添加到容器中(Picture1 = 图片框),则该控件将自动停用(如果 .NET 控件失去焦点):

Private Sub Form_Load()
    Set mCtrl = Controls.Add("ActiveX_Control.UserControl1", "UserControl1", Picture1)
    Set mActiveX = mCtrl.object
    mCtrl.Visible = True
End Sub

我了解到接口 IOleInPlaceObject 负责这种行为。此外,有关 C# 接口 ICustomQueryInterface。 因此,我使用以下知识在运行时抑制接口:

public CustomQueryInterfaceResult GetInterface(ref Guid iid, out IntPtr ppv)
{
    if (iid == typeof(IOleInPlaceObject).GUID)
    {
        ppv = IntPtr.Zero;
        return CustomQueryInterfaceResult.Failed;
    }
    ppv = IntPtr.Zero;
    return CustomQueryInterfaceResult.NotHandled;
}

这似乎有效,但新的问题是,如果按 Tab 键(VB6 中 ActiveX 控件之前的最后一个控件),ActiveX 控件不会自动获得焦点。

这是正确的方法吗? 有没有更好的方法?也许通过ActiveX控件的IOleObject::GetMiscStatus的不同返回值?

可以在此处下载示例 C# 和 VB6 项目。

C#-4.0 COM ActiveX VB6迁移

评论

0赞 Simon Mourier 11/6/2023
对我来说,这两种情况下的问题完全相同:一旦焦点离开 .NET 控件,它的 Visible 属性就会设置为 False,因为它由于某些内部 VB 原因而被停用(就像 .NET 控件未启用/可聚焦)。您可以重写 SetVisibleCore,当 value 为 false 时不执行任何操作,当 Visible 更改为 false 时,您可以重置 Visible,等等。还可以实现 IOleInPlaceObject,并在调用 InPlaceDeactivate 和 UIDeactivate 时不执行任何操作。但它不会使用键盘自动将焦点重新聚焦在 .NET 控件上。不过,它应该适用于鼠标。
0赞 Michael 11/6/2023
@SimonMourier 我不认为这是 vb 的错。在调试器中,可以看到接口 IOleInPlaceObject 是从 .NET 调用的!原则上,如果接口存在,则调用 InPlaceDeactivate 和 UIDeactivate 是正确的。但问题是这个接口是由 .NET 自动添加的。有趣的是,如果直接在 Windows 窗体中使用 .NET 控件,则不存在此问题。我认为这里忽略了COM接口。
0赞 Simon Mourier 11/6/2023
它不容忽视。如果实现它,则可以看到它被使用(由 VB OLE 站点实现)。如果在使用 false 调用 OnVisibleChanged 时放置断点,则可以看到堆栈跟踪,原始原因是 VB 在 TAB 通过 IOleInPlaceActiveObject.TranslateAccelerator 时调用 deactivate。如果按照 OnGotFocus/OnLostFocus 进行操作,则会看到 .NET 控件永远不会获得焦点。.NET 现在是开源的,VB6 不是,我不能 100% 确定是谁的错,我不明白为什么 VB 会停用控件。
2赞 StayOnTarget 11/7/2023
我强烈建议重写这个问题的标题,使其与实际被问到的核心相对应。现在它没有传达任何特别有用的信息。这些标签涵盖了正在使用的技术堆栈。
0赞 StayOnTarget 11/7/2023
它被标记为 c#-4.0 有什么特殊原因吗?我不认为这个问题可以解释这一点。

答: 暂无答案