我有一个遗留的VB6/COM应用程序,我们正在通过.NET DLL将所有代码迁移到.NET(VB.NET)。所有新表单的开发都是在.NET DLL中完成的。
我们使用函数指针回调.NET表单中的COM函数:
- 我在.NET中创建委托
- 在运行时将委托设置为COM函数的AddressOf(GetDelegateForFunctionPointer)
- 显示.NET窗体
- 调用委托
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