【问题标题】:Handling events exposed on a .NET class via COM in VB6在 VB6 中通过 COM 处理在 .NET 类上公开的事件
【发布时间】:2011-02-15 12:52:33
【问题描述】:

在 VB6 中通过 COM 处理在 .NET 类上公开的事件

我的测试 .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 接口而存在?

标签: .net com vb6 interop


【解决方案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 中的事件使用&lt;ComSourceInterfaces(GetType(接口名称))&gt; 和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
    

    【讨论】:

    • 有谁知道是否有可能只用一个接口来处理事件和属性/方法?
    • _MathsComInterfaceType.InterfaceIsIDispatch,所以它不应该只能通过后期绑定来使用吗?在示例中用作早期绑定 - 还是我错了?
    猜你喜欢
    • 1970-01-01
    • 2017-01-23
    • 2010-12-31
    • 2011-07-13
    • 2019-06-16
    • 2010-09-21
    • 2011-01-08
    • 2015-06-29
    • 2015-03-21
    相关资源
    最近更新 更多