我已经研究过,并且阅读了我能找到的所有内容。我很可能已经看到了我的问题的解决方案,但没有认识到它。看来森林对我来说太厚了。
我在vb.net上写了一个dll - VS2010。它在vb.net项目中使用时非常有效。我已启用COM等,以允许它与VB6一起使用。
直到我需要这些事件,它才能按照VB6中的计划运行。但是现在试图让WithEvents部分工作是我完全迷失的地方!
一旦时间比较函数变为真(或相等),我的VB.Net dll就会引发一个事件。它还返回事件的实际时间。
在我的VB6项目中,使用WithEvents函数需要声明在类模块中。我无法理解这将如何/应该如何工作。 正如我之前所说,很多帖子我已经阅读了它必须在类模块中的事实,但没有一个确切地说明如何在一个干净的直接方法中实现这一点。好吧,无论如何,至少对我来说是直截了当的。
以下代码是我在添加事件之前如何使用dll。所有属性和操作等都能正常工作。它位于.bas模块中。
Public PT As New PrecisionTimer.PrecisionTimer
这是如何在表单上使用它的示例:
Private Sub Command3_Click()
Dim aa As Integer
aa = PT.SetTimerEvent(Val(Text6.Text))
Select Case aa
Case -1
OkToInitiate = True
Case False
OkToInitiate = False
End Select
End Sub
但是现在我需要对dll中的事件作出反应。 这是VB.Net dll中引发事件的行:
RaiseEvent OTE(ActualTriggeredTime.ToString())
所以,有人可以帮助我,我在确定如何实现这一目标时遇到了很多麻烦。
谢谢!
更多信息:
@TnTinMn,对你来说,CM从未成为我的强项。以下是MyClass中的代码:
Option Explicit
Public WithEvents PTM As PrecisionTimer.PrecisionTimer
Private Sub PTM_OTE(ByVal ActualTriggeredTime As Variant)
Dim aa As Integer
aa = 1
End Sub
现在可以删除PTM_OTE子,并且会自动显示一个新的PTM_OTE子,当然没有aa = 1代码。
在我的Module1.bas中:
Option Explicit
Public PT As New MyClass.PTM
Public OkToInitiate As Boolean
您是否在我的代码中看到错误?
在对象浏览器中,我确实看到了OTE事件。在这一点上,我想我应该能够在左上角的代码编辑器中看到PT,但我没有?!?!
更多信息:
我在VB.Net dll中添加了一个附加函数到事件例程 - 一个TriggeredFlag。
Public Sub OnTimedEvent(source As Object, e As ElapsedEventArgs)
'Other code including basic error handling
RaiseEvent OTE(ActualTriggeredTime.ToString())
TriggeredFlag = True
End Sub
现在当我在我的vb6项目中使用dll时,我可以监视TriggeredFlag。它确实按预期变化。然而事件似乎没有收到。我相信问题出在VB6代码中 - 类模块中的WithEvents语句(可能)。这是我的整个课程模块:
Option Explicit
Public WithEvents PTM As PrecisionTimer.PrecisionTimer
Public Sub Class_Initialize()
Set PTM = New PrecisionTimer.PrecisionTimer
End Sub
Private Sub PTM_OTE(ByVal ActualTriggeredTime As String)
Dim aa As Integer
aa = 1
End Sub
最后的附加信息:
感谢所有帮助解决这个问题的人! 这是我的Module1.Bas最终:
Option Explicit
Public PT As New PrecisionTimer.PrecisionTimer
Public DT As New DTParams
Public OkToInitiate As Boolean
在表格的“常规”部分中:
Option Explicit
Public WithEvents TimerEvents As PrecisionTimer.PrecisionTimer
Form_load例程包括:
Set TimerEvents = PT
这是TimerEvents_OTE例程:
Private Sub TimerEvents_OTE(ByVal ActualTriggeredTime As String)
'Fires when the "Timer Done" event fires
Call SetTimerText(ActualTriggeredTime)
End Sub
最后,没有使用类模块。
再次感谢所有人!
答案 0 :(得分:2)
您似乎不愿意分享您的.Net代码。为了给您一个工作示例,请尝试实现以下示例,该示例将详细说明创建公开给COM的工作类库的步骤。我没有安装VB6,但已使用MS Office VBA进行了测试。据我所知,VBA是语言,VB6是该语言的主机。有关详细信息,请参阅:Difference between Visual Basic 6.0 and VBA。
第1步:创建COM类库。 以管理员身份启动Visual Studio。这样VS就可以在注册表中注册COM组件。 从"空项目(.Net Framework)创建一个新项目 - Visual Basic"模板。我将该项目命名为#34; Demo COM Exposed Event"。转到项目属性 - 应用程序选项卡并设置"应用程序类型"到"班级图书馆"。您还可以清除"根命名空间"框以强制所有内容都在全局命名空间中,但这不是必需的,因为COM无法识别名称空间。
接下来打开Build Configuration Manager,为项目定义并激活X86(32位)配置。
接下来,将项目配置为注册COM类。这是在"编译选项卡"在项目属性中。
下面的VB.Net代码定义了COMDemoClass
。此类公开一个事件(Event1
),一个方法(SingleFireEvent1
)来引发事件,一个布尔属性(AutoFireEvent1
)启动/停止一个可以触发的计时器{{ 1}}。
Event1
此时,构建项目以生成Dll和类型库。这些应该可以在Solution Explorer中查看。
第2步:在VBA代码中使用库。
在VB IDE中,将项目引用添加到在步骤1中创建的类型库。
添加"类模块"并命名为" ExposeVBNetLib"并将此代码添加到模块中。请注意,您可以向Form或其他类类型模块添加类似的代码;您无法在标准模块中定义Imports System.Runtime.InteropServices
Imports System.Timers
<ComClass(COMDemoClass.ClassId, COMDemoClass.InterfaceId, COMDemoClass.EventsId)>
Public Class COMDemoClass
#Region "COM GUIDs"
' These GUIDs provide the COM identity for this class
' and its COM interfaces. If you change them, existing
' clients will no longer be able to access the class.
Public Const ClassId As String = "db10634a-91fe-4cde-a2da-5421578e6142"
Public Const InterfaceId As String = "22d6da07-b40c-4a04-9551-9c375bf99c06"
Public Const EventsId As String = "2096fe58-d50c-4d19-9039-a6ad4193385c"
#End Region
<ComVisible(False)>
Delegate Sub _Event1(arg As String)
Public Event Event1 As _Event1
Private tmr As New System.Timers.Timer With {.AutoReset = True, .Interval = 500, .Enabled = False}
Private _AutoFireEvent1 As Boolean
' A creatable COM class must have a Public Sub New()
' with no parameters, otherwise, the class will not be
' registered in the COM registry and cannot be created
' via CreateObject.
Public Sub New()
MyBase.New()
AddHandler tmr.Elapsed, AddressOf tmr_Elapsed
End Sub
Private Sub tmr_Elapsed(sender As Object, e As ElapsedEventArgs)
SingleFireEvent1(DateTime.Now.ToLongTimeString())
End Sub
Public Sub SingleFireEvent1(Optional arg As String = "Hello")
RaiseEvent Event1(arg)
End Sub
Public Property AutoFireEvent1 As Boolean
Get
Return _AutoFireEvent1
End Get
Set(value As Boolean)
If value <> _AutoFireEvent1 Then
_AutoFireEvent1 = value
tmr.Enabled = value
End If
End Set
End Property
End Class
变量。
WithEvents
此类订阅COM类 Option Explicit
Private WithEvents vbNetCOMClass As Demo_COM_Exposed_Event.COMDemoClass
Private Sub Class_Initialize()
Set vbNetCOMClass = New Demo_COM_Exposed_Event.COMDemoClass
End Sub
Private Sub Class_Terminate()
Set vbNetCOMClass = Nothing
End Sub
To test the VBA class, add the following code to a standard Module.
Option Explicit
Private instance As ExposeVBNetLib ' a variable to keep the class reference alive between methods
Sub CreateAndLaunch()
Set instance = New ExposeVBNetLib
instance.SingleFireEvent1 "It works"
instance.AutoFireEvent1 = True
End Sub
Sub ShutDown_instance()
If Not (instance Is Nothing) Then
instance.AutoFireEvent1 = False
Set instance = Nothing
End If
End Sub
Private Sub vbNetCOMClass_Event1(ByVal arg As String)
Debug.Print arg
End Sub
Public Property Get AutoFireEvent1() As Boolean
AutoFireEvent1 = vbNetCOMClass.AutoFireEvent1
End Property
Public Property Let AutoFireEvent1(arg As Boolean)
vbNetCOMClass.AutoFireEvent1 = arg
End Property
Public Sub SingleFireEvent1(arg As String)
vbNetCOMClass.SingleFireEvent1 arg
End Sub
的{{1}}并处理方法Event1
中的事件。此方法将接收的参数打印到&#34;立即窗口&#34;。
第3步 - 测试
在标准VBA模块中,放置以下代码:
COMDemoClass
运行方法vbNetCOMClass_Event1
以启动代码。运行方法Option Explicit
Private instance As ExposeVBNetLib ' a variable to keep the class reference alive between methods
Sub CreateAndLaunch()
Set instance = New ExposeVBNetLib
instance.SingleFireEvent1 "It works"
instance.AutoFireEvent1 = True
End Sub
Sub ShutDown_instance()
If Not (instance Is Nothing) Then
instance.AutoFireEvent1 = False
Set instance = Nothing
End If
End Sub
以停止代码。
最后,您应该能够通过配置项目来启动VBA主机,在Visual Studio中调试.Net代码。就我而言,这是Excel和你的VB6。这是通过&#34; Debug选项卡&#34;在项目属性下,通过设置&#34;启动外部程序&#34;在&#34;开始选项&#34;。
下答案 1 :(得分:1)
WithEvents不必在类模块中。它可以在
但它不能在模块中。
您的命令处理程序(Command3_Click)位于表单中。您可以使用相同的格式声明计时器 。
Public WithEvents TimerEvents As New PrecisionTimer.PrecisionTimer
由于您已在模块中将其命名为PT,因此我会在表单中使用其他名称,例如TimerEvents。
声明此变量后,您可以在编辑器窗口左上角的列表中选择它...
然后在编辑器窗口右上角的列表中选择事件...
此VB6将自动插入事件处理程序,您可以在屏幕截图的底部看到。
在命令处理程序中,必须在新变量
中存储对计时器对象的引用Set TimerEvents = PT
所以完整的函数看起来像这样
Private Sub Command3_Click()
Dim aa As Integer
Set TimerEvents = PT
aa = PT.SetTimerEvent(Val(Text6.Text))
Select Case aa
Case -1
OkToInitiate = True
Case False
OkToInitiate = False
End Select
End Sub
但是,我猜它有一个更好的地方来初始化TimerEvents变量。
如果要停止处理事件,请将变量设置为Nothing。
Set TimerEvents = Nothing
答案 2 :(得分:-1)
尝试使用WithEvents声明PrecisionTimer:
Public WithEvents PT As New PrecisionTimer.PrecisionTimer
然后为OTE添加一个事件处理程序:
Public Sub PrecisionTimer_OTE(ByVal ActualTriggeredTime As String) Handles PT.OTE
...
End Sub