【问题标题】:Handling VB.NET events in VB6 code在 VB6 代码中处理 VB.NET 事件
【发布时间】:2009-05-12 06:59:58
【问题描述】:

我有一些 VB6 代码实例化一个类,该类处理从 VB.NET 组件引发的事件。 VB6 非常简单:

private m_eventHandler as new Collection

...

public sub InitSomething()
  dim handler as EventHandler

  set handler = new EventHandler
  m_eventHandler.Add handler
  ...
  m_engine.Start

end sub 

请注意,事件处理程序对象必须超出 init 方法的范围(这就是它被存储在 Collection 中的原因)。另请注意,m_engine.Start 表示程序中 VB.NET 组件将开始引发事件的点。

实际的事件处理程序(按要求):

Private WithEvents m_SomeClass As SomeClass
Private m_object as Object
...

Private Sub m_SomeClass_SomeEvent(obj As Variant)
    Set obj = m_object
End Sub

请注意,m_object 是在创建 EventHandler 的实例时初始化的。

引发事件的 VB.NET 代码更加简单:

Public ReadOnly Property SomeProp() As Object
    Get
        Dim obj As Object
        obj = Nothing
        RaiseEvent SomeEvent(obj)
        SomeProp = obj
    End Get
End Property

我的问题是,当我调试 VB6 程序时,第一次调用InitSomething,事件将 被处理(VB6 事件处理程序永远不会输入)。对InitSomething 的后续调用确实有效。

当我在调试器之外运行程序时,一切正常。在这一点上,我什至不确定这是否是我应该担心的。

它可能相关也可能不相关,但 VB.NET 是使用 Visual Studio 代码转换工具从 VB6 转换而来的(随后手动清理)。

【问题讨论】:

  • 你能显示实际的事件处理程序和处理对象的声明吗? (带有“WithEvents”的那个)?

标签: vb.net debugging events vb6


【解决方案1】:

我发现,如果您在 VB6(或任何其他 COM 环境)中编写用于消费的 .Net 组件,那么接口的使用绝对是至关重要的。

VStudio 开箱即用的 COM 模板还有很多不足之处,尤其是当您尝试让事件工作时。

这是我用过的。

Imports System.Runtime.InteropServices
Imports System.ComponentModel

<InterfaceType(ComInterfaceType.InterfaceIsDual), Guid(ClientAction.InterfaceId)> Public Interface IClientAction
        <DispId(1), Description("Make the system raise the event")> sub SendMessage(ByVal theMessage As String)
    End Interface


    <InterfaceType(ComInterfaceType.InterfaceIsIDispatch), Guid(ClientAction.EventsId)> Public Interface IClientActionEvents
        <DispId(1)> Sub TestEvent(ByVal sender As Object, ByVal e As PacketArrivedEventArgs)
    End Interface



    <ComSourceInterfaces(GetType(IClientActionEvents)), Guid(ClientAction.ClassId), ClassInterface(ClassInterfaceType.None)> _
    Public Class ClientAction
        Implements IClientAction

        Public Delegate Sub TestEventDelegate(ByVal sender As Object, ByVal e As PacketArrivedEventArgs)

        Public Event TestEvent As TestEventDelegate

    public sub New()
        //Init etc
    end sub

    public sub SendMessage(theMessage as string) implements IClientAction.SendMessage
        onSendMessage(theMessage)
    end sub 

        Protected Sub onSendMessage(message as string)
            If mRaiseEvents Then
                RaiseEvent TestEvent(Me, New PacketArrivedEventArgs(theMessage))
            End If
        End Sub

    end Class

我已经能够让程序集/组件的 COM 和 .Net 使用者正常处理事件,并能够在组件内外进行调试。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    只是尝试一下 - 我对“As New ..”有一种与生俱来的不信任

    你可以试试

    private m_eventHandler as Collection
    
    public sub InitSomething()
      dim handler as EventHandler
    
      set handler = new EventHandler
    
      If m_eventHandler Is Nothing Then
        Set m_eventHandler = New Collection
      End if
    
      m_eventHandler.Add handler
     ...
    
      m_engine.Start
    
    end sub
    

    唉,我不知道为什么这在正常执行中有效,而不是在调试中,除了一些模糊的怀疑,它与 .NET 无法实例化 VBA.Collection 对象有关(MS 建议您编写一个快速的 VB6组件),但由于您不是在 .NET 代码中创建集合,所以它仍然只是一个模糊的怀疑。

    【讨论】:

      猜你喜欢
      • 2018-06-14
      • 2012-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-27
      • 2010-09-21
      • 1970-01-01
      相关资源
      最近更新 更多