主题:[讨论]vb6仿委托实现多个类共享同一个事件处理过程的问题
最近在做一个DLL时遇到一个问题,希望在使用这个DLL中的类时,能够像控件数组一样地,共享同一个事件处理过程,但用WithEvent不能声明对象数组。于是想到了类似于C#中的委托(或事件)的实现方式。
具体代码如下:
[code=c]
'//类TestDllArray.Tester
Option Explicit
'//最开始时直接在Tester里定义事件,但由于不能用WithEvent声明对象数组,所以废弃
'Public Event DataChanged(ByVal TestID As Long, ByVal curData As Long)
Private mData As Long
Private mTestID As Long '//测试时以区分不同的对象
'//委托,目前只能实现一级委托,没有委托链
'//不能实现像 myTest.EventHandler +=new myDelegate()
Private mDelegate As delegate
Private Sub Class_Initialize()
mData = 0
mTestID = Rnd() * 65535
End Sub
Public Property Let MyData(ByVal value As Long)
mData = value
'//由委托来产生事件
Call mDelegate.EventHandler(Me, MyData)
'RaiseEvent DataChanged(mTestID, value)
End Property
Public Property Get MyData() As Long
MyData = mData
End Property
Public Property Set EventHandler(ByRef dlg As delegate)
Set mDelegate = dlg
End Property
Public Property Get TestID() As Long
TestID = mTestID
End Property
’类TestDllArray.Delegate
Option Explicit
Public Event MyEvent(ByVal thisTester As Tester, ByVal param1 As String)
'//注意是Friend的,在同一工程中的Tester可用,但对于Form1不可用
Friend Sub EventHandler(ByVal thisTester As Tester, ByVal param1 As String)
'//不希望在事件中更改属性,或者作出的更改不影响源对象
'public void EventHandler(const Tester *thisTest,CString param1)
Debug.Print thisTester.TestID, param1
'//为便于用户自定义处理过程
RaiseEvent MyEvent(thisTester, param1)
End Sub
'//在窗体中
Option Explicit
Private myTest() As TestDllArray.Tester
Private myTest2 As TestDllArray.Tester
Private WithEvents myDelegate As TestDllArray.delegate
Private WithEvents myDelegate2 As TestDllArray.delegate
Private Sub cmdTest_Click()
myTest(0).MyData = Rnd() * 200
myTest(1).MyData = Rnd() * 200
myTest2.MyData = Rnd() * 200
End Sub
Private Sub Command1_Click()
'//改变myTest(0)的事件处理委托对象
Set myTest(0).EventHandler = myDelegate2
myTest(0).MyData = 200 + Rnd() * 200
Debug.Print "after event,"; myTest(0).MyData
End Sub
Private Sub Form_Load()
Set myDelegate = New delegate
Set myDelegate2 = New delegate
ReDim myTest(1) As TestDllArray.Tester
Set myTest(0) = New TestDllArray.Tester
Debug.Print myTest(0).TestID
Set myTest(0).EventHandler = myDelegate
Set myTest(1) = New TestDllArray.Tester
Debug.Print myTest(1).TestID
Set myTest(1).EventHandler = myDelegate
Set myTest2 = New TestDllArray.Tester
Debug.Print myTest2.TestID
Set myTest2.EventHandler = myDelegate
'Set myTest2 = myTest
'Debug.Print myTest2.TestID
End Sub
'//最初想到的是回调函数的形式,addressOf 但无从下手。
'Private Function FARPROC(ByVal pfn As Long) As Long
' FARPROC = pfn
'End Function
Private Sub myDelegate_MyEvent(ByVal thisTester As TestDllArray.Tester, ByVal param1 As String)
Debug.Print "user defined procedure,"; thisTester.TestID, param1
End Sub
Private Sub myDelegate2_MyEvent(ByVal thisTester As TestDllArray.Tester, ByVal param1 As String)
'in this event procedure,try to change byval object instance
Debug.Print "in event,"; thisTester.MyData
[color=red]'//在此处再修改myData时会导至触发多次事件,不知道怎么解决[/color]
thisTester.MyData = 23
End Sub
[/code]
问题:
1、如何实现多级委托(叫委托链?)
2、在事件中再修改myData时导致触发多次事件,如何解决?
[color=red][size=4]PS.其实做成OCX控件形式的就可以实现控件数组了?!真是多此一举[/size][/color]
具体代码如下:
[code=c]
'//类TestDllArray.Tester
Option Explicit
'//最开始时直接在Tester里定义事件,但由于不能用WithEvent声明对象数组,所以废弃
'Public Event DataChanged(ByVal TestID As Long, ByVal curData As Long)
Private mData As Long
Private mTestID As Long '//测试时以区分不同的对象
'//委托,目前只能实现一级委托,没有委托链
'//不能实现像 myTest.EventHandler +=new myDelegate()
Private mDelegate As delegate
Private Sub Class_Initialize()
mData = 0
mTestID = Rnd() * 65535
End Sub
Public Property Let MyData(ByVal value As Long)
mData = value
'//由委托来产生事件
Call mDelegate.EventHandler(Me, MyData)
'RaiseEvent DataChanged(mTestID, value)
End Property
Public Property Get MyData() As Long
MyData = mData
End Property
Public Property Set EventHandler(ByRef dlg As delegate)
Set mDelegate = dlg
End Property
Public Property Get TestID() As Long
TestID = mTestID
End Property
’类TestDllArray.Delegate
Option Explicit
Public Event MyEvent(ByVal thisTester As Tester, ByVal param1 As String)
'//注意是Friend的,在同一工程中的Tester可用,但对于Form1不可用
Friend Sub EventHandler(ByVal thisTester As Tester, ByVal param1 As String)
'//不希望在事件中更改属性,或者作出的更改不影响源对象
'public void EventHandler(const Tester *thisTest,CString param1)
Debug.Print thisTester.TestID, param1
'//为便于用户自定义处理过程
RaiseEvent MyEvent(thisTester, param1)
End Sub
'//在窗体中
Option Explicit
Private myTest() As TestDllArray.Tester
Private myTest2 As TestDllArray.Tester
Private WithEvents myDelegate As TestDllArray.delegate
Private WithEvents myDelegate2 As TestDllArray.delegate
Private Sub cmdTest_Click()
myTest(0).MyData = Rnd() * 200
myTest(1).MyData = Rnd() * 200
myTest2.MyData = Rnd() * 200
End Sub
Private Sub Command1_Click()
'//改变myTest(0)的事件处理委托对象
Set myTest(0).EventHandler = myDelegate2
myTest(0).MyData = 200 + Rnd() * 200
Debug.Print "after event,"; myTest(0).MyData
End Sub
Private Sub Form_Load()
Set myDelegate = New delegate
Set myDelegate2 = New delegate
ReDim myTest(1) As TestDllArray.Tester
Set myTest(0) = New TestDllArray.Tester
Debug.Print myTest(0).TestID
Set myTest(0).EventHandler = myDelegate
Set myTest(1) = New TestDllArray.Tester
Debug.Print myTest(1).TestID
Set myTest(1).EventHandler = myDelegate
Set myTest2 = New TestDllArray.Tester
Debug.Print myTest2.TestID
Set myTest2.EventHandler = myDelegate
'Set myTest2 = myTest
'Debug.Print myTest2.TestID
End Sub
'//最初想到的是回调函数的形式,addressOf 但无从下手。
'Private Function FARPROC(ByVal pfn As Long) As Long
' FARPROC = pfn
'End Function
Private Sub myDelegate_MyEvent(ByVal thisTester As TestDllArray.Tester, ByVal param1 As String)
Debug.Print "user defined procedure,"; thisTester.TestID, param1
End Sub
Private Sub myDelegate2_MyEvent(ByVal thisTester As TestDllArray.Tester, ByVal param1 As String)
'in this event procedure,try to change byval object instance
Debug.Print "in event,"; thisTester.MyData
[color=red]'//在此处再修改myData时会导至触发多次事件,不知道怎么解决[/color]
thisTester.MyData = 23
End Sub
[/code]
问题:
1、如何实现多级委托(叫委托链?)
2、在事件中再修改myData时导致触发多次事件,如何解决?
[color=red][size=4]PS.其实做成OCX控件形式的就可以实现控件数组了?!真是多此一举[/size][/color]