在 VB6 中通过 COM 处理在 .NET 类上公开的事件
Posted
技术标签:
【中文标题】在 VB6 中通过 COM 处理在 .NET 类上公开的事件【英文标题】:Handling events exposed on a .NET class via COM in VB6 【发布时间】:2011-02-15 12:52:33 【问题描述】:我的测试 .NET(在编译器设置中为互操作注册的类库)代码:
Imports System.Runtime.InteropServices
<InterfaceType(ComInterfaceType.InterfaceIsIDispatch), ComVisible(True)> _
Public Interface MyEventInterface
<DispId(1)> Event Exploded(ByVal Text As String)
<DispId(2)> Sub PushRedButton()
End Interface
<ClassInterface(ClassInterfaceType.None)> _
Public Class EventTest
Implements MyEventInterface
Public Event Exploded(ByVal Text As String) Implements MyEventInterface.Exploded
Public Sub PushRedButton() Implements MyEventInterface.PushRedButton
RaiseEvent Exploded("Bang")
End Sub
End Class
我的测试VB6应用程序winforms代码(引用了上面的类库):
Public ct As New ComTest1.EventTest
Private Sub Command1_Click()
ct.add_Exploded (ExplodedHandler)
ct.PushRedButton
ct.remove_Exploded (ExplodedHandler)
End Sub
Private Sub ExplodedHandler(ByVal Text As String)
MsgBox Text
End Sub
特别是我不确定如何在 VB6 中设置处理程序,我得到的编译错误是 VB6 中这一行的“Argument not optional”:
ct.add_Exploded (ExplodedHandler)
【问题讨论】:
你的 add_Exploded 声明在哪里? COM 属性创建了它。即在 VB6 中智能感知 add_ 和 remove_ 由于我相信的 Idispatch 接口而存在? 【参考方案1】:C#
[ComVisible(true)] //Exposed
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] //Our managed interface will be IDispatch
public interface IMathEvents
void OnOperationCompleted(string message);
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IMathEvents))] //Our event source is IMathEvents interface
[ComDefaultInterface(typeof(IMath))]
public class Math:IMath /*IMath interface just declares a method named Add */
public int Add(int x, int y)
if (null != this.OnOperationCompleted)
this.OnOperationCompleted("Operation completed, result: " + (x+y).ToString());
return x + y;
[ComVisible(false)]
public delegate void OperationCompletedDel(string message); //No need to expose this delegate
public event OperationCompletedDel OnOperationCompleted;
[ComVisible(true)]
public interface IMath
int Add(int x, int y);
vb
Private WithEvents m As Math
私有子Form_Load()
Set m = New PayClient.Math
结束子
Private Sub m_OnOperationCompleted(ByVal Text As String)
MsgBox Text
结束子
私有子 Command2_Click() m.加1, 2
结束子
【讨论】:
【参考方案2】:.NET 中的事件使用<ComSourceInterfaces(GetType(
接口名称))>
和VB6 中的WithEvents
.NET 类库:
Imports System.Runtime.InteropServices
' This interface is to expose the events
<Guid("28C7DCE1-90EF-4a30-AF7F-4187F9FFFDEB")> _
<InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface MathsEvents
<DispId(1)> _
Sub Calculated(ByVal Result As Double)
End Interface
' This interface is to expose the properties and methods
<Guid("86CE5E8D-777D-4cd5-8A7D-7F58737F1DB4")> _
<InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface _Maths
<DispId(2)> _
Property ValueA() As Double
<DispId(3)> _
Property ValueB() As Double
<DispId(4)> _
ReadOnly Property Result() As Double
<DispId(5)> _
Sub Add()
End Interface
' This is the actual class
' The events are exposed by using the ComSourceInterfaces attribute
' The properties and methods are exposed using the Implements keyword
<Guid("C58721B1-15B3-4eeb-9E1E-BCDA33D38EE6")> _
<ClassInterface(ClassInterfaceType.None)> _
<ComSourceInterfaces(GetType(MathsEvents))> _
Public Class Maths
Implements _Maths
Public Event Calculated(ByVal Result As Double)
Private mValueA As Double
Private mValueB As Double
Private mResult As Double
Public Property ValueA() As Double Implements _Maths.ValueA
Get
Return mValueA
End Get
Set(ByVal value As Double)
mValueA = value
End Set
End Property
Public Property ValueB() As Double Implements _Maths.ValueB
Get
Return mValueB
End Get
Set(ByVal value As Double)
mValueB = value
End Set
End Property
Public ReadOnly Property Result() As Double Implements _Maths.Result
Get
Return mResult
End Get
End Property
Public Sub New()
mValueA = 0
mValueB = 0
mResult = 0
End Sub
Public Sub Add() Implements _Maths.Add
mResult = mValueA + mValueB
RaiseEvent Calculated(mResult)
End Sub
End Class
VB6 测试应用:
Private WithEvents calc As Maths
Private Sub btnAdd_Click()
calc.ValueA = CDbl(txtValueA.Text)
calc.ValueB = CDbl(txtValueB.Text)
calc.Add
End Sub
Private Sub calc_Calculated(ByVal Result As Double)
txtResult.Text = CStr(Result)
End Sub
Private Sub Form_Load()
Set calc = New Maths
End Sub
【讨论】:
有谁知道是否有可能只用一个接口来处理事件和属性/方法?_Maths
是ComInterfaceType.InterfaceIsIDispatch
,所以它不应该只能通过后期绑定来使用吗?在示例中用作早期绑定 - 还是我错了?以上是关于在 VB6 中通过 COM 处理在 .NET 类上公开的事件的主要内容,如果未能解决你的问题,请参考以下文章
如何在vb6中注册一个不能用作com互操作的.net DLL?