COM应用程序调用.NET窗体调用COM窗体,在编译时可以工作,但不能在VB6 IDE中工作



我有一个遗留的VB6/COM应用程序,我们正在通过.NET DLL将所有代码迁移到.NET(VB.NET)。所有新表单的开发都是在.NET DLL中完成的。

我们使用函数指针回调.NET表单中的COM函数:

  1. 我在.NET中创建委托
  2. 在运行时将委托设置为COM函数的AddressOf(GetDelegateForFunctionPointer)
  3. 显示.NET窗体
  4. 调用委托

COM应用程序-->.NET窗体-->COM函数

这适用于函数。当我调用显示窗体的COM函数时,就会出现这种情况。

COM应用程序-->.NET窗体-->COM函数-->COM窗体

COM函数将执行,表单将显示,但在VB6 IDE中执行时,COM表单的逻辑不会执行。显示控件,但不执行任何单击或form_load事件。编译VB6应用程序时,这不是问题。

我注意到的另一个问题是VB6IDE"冻结",直到.NET表单卸载。我无法停止调试器、设置断点或与IDE的菜单交互。就好像VB6 IDE允许.NET DLL完全控制线程一样。我认为这两个问题是相关的。

编辑:.NET表单是模态的,这可能是IDE线程锁定的原因。我只是想知道是否有办法解决这个问题。此外,我还查看了InteropForms工具包。它不能解决我的问题。即使将它们的示例表单设置为模态,也会导致发生相同的IDE线程锁定。

编辑2:我之前的编辑确实提到了另一种解决方法:当宿主应用程序是VB6时,使.NET表单显示为无模式。

If InStr(Process.GetCurrentProcess().ProcessName, "vb6", CompareMethod.Text) > 0 Then
    frm.Show()
Else
    frm.ShowDialog()
    frm.Dispose()
End If

简单的COM App-->.NET Form-->COM函数-->COM Form场景可以使用InteropForms Toolkit 2.1工作。以下是一些执行此操作的代码,不使用委托或AddressOf

首先,我们有我们的COM库,我称之为ComLibrary。我们有以下代码:

SimpleForm.frm:

Option Explicit
Private Sub Form_Load()
    MsgBox "In SimpleForm_Load"
End Sub
Private Sub OkButton_Click()
    Unload Me
End Sub
Private Sub TalkButton_Click()
    MsgBox "Hello"
End Sub

SimpleClass.cls:

Option Explicit
Public Function ShowTheDialog() As Long
    Dim f As SimpleForm
    Set f = New SimpleForm
    f.Show vbModal
    ShowTheDialog = 1
End Function

将其编译为.dll,以便我们可以在.NET库中引用它。

接下来,我们将创建.NET表单库。我使用"VB6 InteropForms Library"项目模板,使用InteropFormsLibrary1的默认项目名称。我添加了对ComLibrary项目的引用。该表单有一个名为"CallComFunction"的按钮

InteropForm1.vb:

Imports Microsoft.InteropFormTools
<InteropForm()> _
Public Class InteropForm1
    Private Sub CallComFunction_Click(sender As System.Object, e As System.EventArgs) Handles CallComFunction.Click
        Dim sc As ComLibrary.SimpleClass
        sc = New ComLibrary.SimpleClass
        Dim result As Integer
        result = sc.ShowTheDialog()
    End Sub
End Class

在编译之前,我们需要根据工具包文档创建InteropForms包装器类。通过访问"工具">"生成器InteropForms包装类"菜单来执行此操作。

最后,我们创建了VB6主机应用程序。

Form1.frm:

Option Explicit
Private Sub DialogButton_Click()
    Dim f As InteropFormLibrary1.InteropForm1
    Set f = New InteropForm1
    f.Show vbModal
End Sub

当我在VB6 IDE中运行主机应用程序时,我可以单击按钮VB6窗体,然后显示VB.NET窗体。从那里,我单击另一个按钮,它使用SimpleClass的实例来显示SimpleForm。表单加载事件中的MsgBox语句和按钮单击处理程序起作用。编译VB6主机应用程序时一切都正常。

看起来你的VB6 IDE正在将你的VB应用程序加载为一个"进程中"COM对象,尽管这对我来说没有多大意义……然而,如果是这样的话,这意味着你的应用程序和调试器只有一个消息循环,这可能至少可以解释其中的一些问题。我已经很多年没有使用VB的经典IDE了,所以我不知道它是如何工作的。也许有一个选项可以在单独的过程中加载你的应用程序?

更新-看来我的猜测是正确的。有关更多信息和可能的解决方案,请参阅其他问题及其答案:

https://stackoverflow.com/a/518217/501196

最新更新