回 帖 发 新 帖 刷新版面

主题:[讨论]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]

回复列表 (共6个回复)

沙发

又看了一下,c#中的委托是由delegate去寻找业务,而不是用户找上门 (MyDelegate myDlg = new MyDelegate(custom.DoSomething);)。而java中的更像是用户去找委托(addEventListener)。不知理解对了没有。[em1]

板凳

大家多多少少地给点评论意见噻。。

3 楼

看不懂啊从来都没有想过这些所以就没有办法说话了

4 楼

实在不知道LZ要做什么 !~

5 楼

[quote]实在不知道LZ要做什么 !~[/quote]

[quote]希望在使用这个DLL中的类时,能够像控件数组一样地,共享同一个事件处理过程,但用WithEvent不能声明对象数组[/quote]

[quote][color=red]问题:
1、如何实现多级委托(叫委托链?)[/color][color=green]PS.就像CallNextHook一样,继续对一个事件(消息)进行处理[/color][color=red]
2、在事件中再修改myData时导致触发多次事件,如何解决?

PS.其实做成OCX控件形式的就可以实现控件数组了?!真是多此一举[/color][/quote]

6 楼

今天又遇到这个问题了。在原来写的代码中又找不到了。突然想到好像在这里发这样的帖子,就google了一下"vb6 天天学习 事件 类",居然就找到了。[em1][em1]
PS:学习两个字居然被GFW认为是敏感词。faint

我来回复

您尚未登录,请登录后再回复。点此登录或注册