通过互操作传递VB6对象到.net对象
本文关键字:对象 net VB6 互操作 | 更新日期: 2023-09-27 18:18:11
我有一个VB6应用程序,通过互操作显示。net DLL表单。
我想在。net DLL中的一个事件,以导致在VB6应用程序中的表单显示。
我的想法是让VB6应用程序传递对窗体的引用到。net DLL。如:
[VB6]
Dim objNetDllObject As New NetDllObject
objNetDllObject.PassVb6Form(MyForm)
objNetDllObject.ShowForm
[C#]
object Vb6Form;
private void PassVb6Form(object form) { Vb6Form = form; }
private void button1_Click(object sender, EventArgs e) { Vb6Form.Show(); }
这能行吗?
我在其他地方读到过跨"进程边界"发送对象可能会导致问题。这是正确的吗?
一种方法是在。net中定义一个COM接口:
<System.Runtime.InteropServices.GuidAttribute("0896D946-8A8B-4E7D-9D0D-BB29A52B5D08"), _
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface IEventHandler
Sub OnEvent(ByRef sender As Object, ByRef e As Object)
End Interface
在VB6中实现这个接口
Implements MyInterop.IEventHandler
Private Sub IEventHandler_OnEvent(ByRef sender As Variant, ByRef e As Variant)
Dim id
id = e.Entity.Id
' As long as e is COM Visible (not necessarily COM registered, this will work)
End Sub
,然后在。net中有一个注册器,带有一个静态的ieventhandler集合:
<ComClass(ComRegistrar.ClassId, ComRegistrar.InterfaceId, ComRegistrar.EventsId>
Public Class ComRegistrar
Private Shared ReadOnly _eventHandlers As New Dictionary(Of String, List(Of IEventHandler))
' This is called by .NET code to fire events to VB6
Public Shared Sub FireEvent(ByVal eventName As String, ByVal sender As Object, ByVal e As Object)
For Each eventHandler In _eventHandlers(eventName)
eventHandler.OnEvent(sender, e)
Next
End Sub
Public Sub RegisterHandler(ByVal eventName As String, ByVal handler As IEventHandler)
Dim handlers as List(Of IEventHandler)
If Not _eventHandlers.TryGetValue(eventName, handlers)
handlers = New List(Of IEventHandler)
_eventHandlers(eventName) = handlers
End If
handlers.Add(handler)
End Sub
End Class
你的。net代码将调用FireEvent,如果VB6之前调用了RegisterHandler,你的VB6 IEventHandler将被调用。
您还可以使用ComSourceInterfacesAttribute,这可以使您的代码更简单一点(或至少从VB6方面更自然)。您将有如下代码:
c#库:namespace WindowsFormsControlLibrary1
{
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IMyFormEvents
{
[DispId(1)]
void MyEvent();
}
public delegate void MyEventEventHandler();
[ComSourceInterfaces(typeof(IMyFormEvents))]
public partial class MyForm : Form
{
public event MyEventEventHandler MyEvent;
public MyForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (this.MyEvent != null)
{
this.MyEvent();
}
}
}
}
和VB6客户端:
Option Explicit
Private WithEvents f As WindowsFormsControlLibrary1.MyForm
Private Sub Command1_Click()
Set f = New WindowsFormsControlLibrary1.MyForm
Call f.Show
End Sub
Private Sub f_MyEvent()
MsgBox "Event was raised from .NET"
'Open another VB6 form or do whatever is needed
End Sub
如果你打算在你的VB6应用程序中使用大量。net UI,我强烈推荐Interop Forms Toolkit,它可以使事情变得更简单。(它有助于生成类似这些示例的代码,以及处理一些其他常见场景)。