在VB6代码中处理VB.NET事件 [英] Handling VB.NET events in VB6 code
问题描述
private m_eventHandler作为新集合
...
public sub InitSomething()
dim handler作为EventHandler
set handler = new EventHandler
m_eventHandler.Add handler
...
m_engine 。开始
end sub
请注意,事件处理程序对象必须生活超出了init方法的范围(这就是为什么它被存储在Collection中)。还请注意, m_engine.Start
表示程序中VB.NET组件将开始提高事件的点。
实际的事件处理程序(根据请求):
Private WithEvents m_SomeClass As SomeClass
$ p $请注意,当
私有m_object作为对象
...
Private Sub m_SomeClass_SomeEvent(obj As Variant)
设置obj = m_object
End Sub
EventHandler
的实例是m_object
被初始化创建。
引发事件的VB.NET代码更简单:
Public ReadOnly Property SomeProp()As Object
Get
Dim obj As Object
obj = Nothing
RaiseEvent SomeEvent(obj)
SomeProp = obj
结束获取
结束属性
我的问题是,当我调试 VB6程序,第一次
InitSomething
被调用,事件将不被处理(VB6事件处理程序从不输入)。随后调用InitSomething
可以正常工作。
一切都正常运行,当我在调试器外部运行程序。在这一点上,我甚至不确定这是我应该担心的事情。
它可能与也可能并不相关,但是VB.NET被转换为一个VB6使用Visual Studio代码转换工具(并随后手动清理)。
解决方案我发现如果你是编写.Net在VB6(或任何其他COM环境)中的消耗组件使用接口是绝对关键的。
与VStudio一起出现的COM模板离开很多都是需要的,特别是当你试图让事件工作时。
这是我使用的。
导入System.Runtime.InteropServices
导入System.ComponentModel
< InterfaceType(ComInterfaceType.InterfaceIsDual),Guid(ClientAction.InterfaceId)> ;公共接口IClientAction
< DispId(1),描述(使系统引发事件)> sub SendMessage(ByVal theMessage As String)
结束接口
< InterfaceType(ComInterfaceType.InterfaceIsIDispatch),Guid(ClientAction.EventsId)>公共接口IClientActionEvents
< DispId(1)> Sub TestEvent(ByVal sender As Object,ByVal e As PacketArrivedEventArgs)
结束接口
< ComSourceInterfaces(GetType(IClientActionEvents)),Guid(ClientAction.ClassId ),ClassInterface(ClassInterfaceType.None)> _
公共类ClientAction
实现IClientAction
公共委托Sub TestEventDelegate(ByVal sender As Object,ByVal e As PacketArrivedEventArgs)
公共事件TestEvent作为TestEventDelegate
public sub New()
// Init etc
end sub
public sub SendMessage(theMessage as string)实现IClientAction.SendMessage
onSendMessage(theMessage)
end sub
受保护的子onSendMessage(消息作为字符串)
如果mRaiseEvents然后
RaiseEvent TestEvent(Me,New PacketArrivedEventArgs(theMessage))
结束If
End Sub
end Class
我已经能够让Assembly / Component的COM和.Net消费者正确地处理事件,并且可以调试进出组件。
希望这有助于。
I have some VB6 code that instantiates a class which handles events that are being raised from a VB.NET component. The VB6 is pretty straightforward:
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
Note that the event handler object has to live beyond the scope of the init method (which is why it is being stored in a Collection). Note also that
m_engine.Start
indicates the point in the program where the VB.NET component would start raising events.The actual event handler (as requested):
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
Note that
m_object
is initialized when an instance ofEventHandler
is created.The VB.NET code which raises the event is even simpler:
Public ReadOnly Property SomeProp() As Object Get Dim obj As Object obj = Nothing RaiseEvent SomeEvent(obj) SomeProp = obj End Get End Property
My problem is that when I debug the VB6 program, the first time
InitSomething
gets called, the event will not be handled (the VB6 event handler is never entered). Subsequent calls toInitSomething
does work.Everything works as I would have expected when I run the program outside the debugger. At this point, I'm not even sure if this is something I should be worried about.
It may or may not be relevant but the VB.NET was converted from a VB6 using the Visual Studio code conversion tool (and subsequently manually cleaned up).
解决方案I've found that if you are writing .Net Components for Consumption in VB6 (or any other COM environment) the utilisation of Interfaces is absolutely criticial.
The COM templates that comes out of the box with VStudio leave a lot to be desired especially when you are trying to get Events to work.
Here's what I've used.
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
I've been able to get COM and .Net consumers of the Assembly/Component to work properly with events and be able to debug in and out of the component.
Hope this helps.
这篇关于在VB6代码中处理VB.NET事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!