带有自定义事件的类,如何声明数组
Private WithEvents Objects(UBound) As ClassVB不能直接支持.看过好些老外的方法,都不怎么理想.

解决方案 »

  1.   

    关注.....,怎么在API版............
      

  2.   

    处理多个对象的事件?如果不是控件的话,你可以试试用集合类来处理。举个简单的例子。
    在类模块IEventHandler(事件接口)中Option ExplicitPublic Sub FireEvent()
        
    End Sub在类模块MyObjects(集合类)中Option ExplicitImplements IEventHandlerPublic Event ObjectEvent()Private m_Col       As New CollectionPublic Sub Add(objItem As ObjectItem, Optional ByVal Key As String)
        
        objItem.EventHandler = Me
        
        If Len(Key) Then
            m_Col.Add objItem, Key
        Else
            m_Col.Add objItem
        End If
        
    End SubPrivate Sub IEventHandler_FireEvent()
        RaiseEvent ObjectEvent
    End Sub'其他的代码略...在类模块ObjectItem(要处理的对象)Option ExplicitPrivate m_EventHandler          As IEventHandlerFriend Property Let EventHandler(ByVal Value As IEventHandler)
        Set m_EventHandler = Value
    End Property'Test方法通知实现这个接口的对象
    Public Sub Test()
        m_EventHandler.FireEvent
    End Sub使用时Option ExplicitPrivate WithEvents mObjects     As MyObjectsPrivate Sub Command1_Click()
        
        Dim o       As ObjectItem
        
        If mObjects Is Nothing Then Set mObjects = New MyObjects
        
        Set o = New ObjectItem
        
        mObjects.Add o
        
        o.TestEnd SubPrivate Sub mObjects_ObjectEvent()
        MsgBox "OK"
    End Sub
      

  3.   

    Private WithEvents Objects(UBound) As Class不支持定义数组的。
      

  4.   

    不知道你都看过哪些了,如果类是你自己写的话,可以绕过event(即将event也封装成一般的过程),这样就可以不用使用WithEvents了
      

  5.   

    这是一个简单的例子:
    新建一个普通工程,添加一个窗体,3个类模块:类模块IEvents:
    Option Explicit'interface IEventsPublic Sub Event1()
    End SubPublic Sub Event2(ByVal Param As Integer)
    End Sub类模块IYourObject:
    Option Explicit
    'interface IYourObjectPublic Property Get YourProp() As String
    End PropertyPublic Sub YourSub(ByVal i As Integer)
    End SubPublic Sub SetEventHandler(EH As IEvents)
    End Sub类模块CYourObject:
    'CYourObject - implements the IYourObject interface
    Option Explicit
    Implements IYourObject
    Dim m_Events As IEvents
    Private mYourProp As StringPublic Property Get YourProp() As String
        YourProp = IYourObject.YourProp
    End Property
    Public Sub YourSub(ByVal i As Integer)
        IYourObject_YourSub i
    End SubPublic Sub SetEventHandler(EH As IEvents)
        IYourObject.SetEventHandler EH
    End SubPrivate Sub Class_Initialize()
        mYourProp = "this is test"
    End SubPrivate Sub IYourObject_SetEventHandler(EH As IEvents)
        Set m_Events = EH
    End SubPrivate Property Get IYourObject_YourProp() As String
       'raise an event
       IYourObject_YourProp = mYourProp
       m_Events.Event1
    End PropertyPrivate Sub IYourObject_YourSub(ByVal i As Integer)
        ' raise an event
        m_Events.Event2 i
    End Sub窗体:
    Option Explicit
    Implements IEventsDim MyClassObj As IYourObjectPrivate Sub Command1_Click()
        MsgBox MyClassObj.YourProp
    End Sub' IEvents implementation
    Public Sub IEvents_Event1()
        MsgBox "Raised Event1 !!"
    End SubPublic Sub IEvents_Event2(ByVal Param As Integer)
        MsgBox "Raised Event2 !!"
    End Sub' form code
    Private Sub Form_Load()
    ' create the object
        Set MyClassObj = New CYourObject
        MyClassObj.SetEventHandler Me
    End Sub
      

  6.   

    看看我的做法,用一个通用数组类来管理索引及访问类
    只是,事件没有办法传回.那位达人帮我想想办法Option Explicit
    'in Form
    Private WithEvents CExample As Class_Example
    Private CArray As New Class_ObjectArrayPrivate Sub Form_Load()
            Dim i As Long
            For i = 1 To 3
                    Set CExample = New Class_Example
                    CArray.CNew CExample
            Next i
    End SubPrivate Sub Form_Unload(Cancel As Integer)
            Set CExample = Nothing
    End SubPrivate Sub Form_DblClick()
            CArray.CItem(2).Raise
    End SubPrivate Sub CExample_CEvent(ByVal index As Long)
            Debug.Print index
    End Sub
    Option Explicit'Class_Example.cls
    Public index As LongPublic Event CEvent(ByVal index As Long)Public Function Raise()
            RaiseEvent CEvent(index)
    End FunctionOption Explicit
    'Class_ObjectArray.cls
    Private Class_Objects() As ObjectPrivate Sub Class_Initialize()
            ReDim Class_Objects(0)
    End SubPrivate Sub Class_Terminate()
            Erase Class_Objects
    End SubPublic Function CNew(ByRef CItem As Object) As Long
            CNew = UBound(Class_Objects) + 1
            ReDim Preserve Class_Objects(CNew)
            Set Class_Objects(CNew) = CItem
            Class_Objects(CNew).index = CNew
    End FunctionPublic Function CItem(ByVal index As Long) As Object
            Set CItem = Class_Objects(index)
    End Function
      

  7.   

    to:rainstormmaster(暴风雨 v2.0) 
    '--------------------------------------------------------
    老大,帮我看看我的方法能不能把事件想办法传回去呀?我写了十几个类,不想一个一个改接口呀,现在用我自己的方法已经可以实现类数组和事件回调了,只是类数组的事件回调有点问题.
      

  8.   

    处理这种需求一般都是类集合加Implements接口。
    fj182(阿花)的方法比较标准,建议楼主认真看看,他就是事件中少传了一个Index参数,这只需为对象加个属性,就可解决。
    类集合比类数组更便于组织与维护,是MS推荐的方法。稍加改动就可实现与VB控件数组几乎完全一样的用法。rainstormmaster的办法同样使用了接口类,应该也行,只是没采用事件封装而已。
    LZ的方法,本质上有问题,可以产生事件,但不能识别对象的Index,而且事件的发生是在基对象之外,你应该加个接口类。
      

  9.   

    看看是否符合你的要求:
    Option Explicit
    'in Form
    Private WithEvents CExample As Class_Example
    Private CArray As New Class_ObjectArrayPrivate Sub Form_Load()
            Dim i As Long
            Set CExample = New Class_Example
            For i = 1 To 3
                    CArray.CNew CExample
            Next i
    End SubPrivate Sub Form_Unload(Cancel As Integer)
            Set CExample = Nothing
    End SubPrivate Sub Form_DblClick()
            CArray.CItem(2).Raise 2
    End SubPrivate Sub CExample_CEvent(ByVal index As Long)
            MsgBox index
    End Sub
    Option Explicit'Class_Example.cls
    'Public index As LongPublic Event CEvent(ByVal index As Long)Public Function Raise(ByVal mindex As Long)
            RaiseEvent CEvent(mindex)
    End Function
    Option Explicit'Class_ObjectArray.cls
    Private Class_Objects() As Object
    Private Sub Class_Initialize()
            ReDim Class_Objects(0)
    End SubPrivate Sub Class_Terminate()
            Erase Class_Objects
    End SubPublic Function CNew(ByRef CItem As Object) As Long
            CNew = UBound(Class_Objects) + 1
            ReDim Preserve Class_Objects(CNew)
            Set Class_Objects(CNew) = CItem
            'Class_Objects(CNew).index = CNew
    End FunctionPublic Function CItem(ByVal index As Long) As Object
            Set CItem = Class_Objects(index)
    End Function对比一下:
    Private Sub Form_Load()
            Dim i As Long
            For i = 1 To 3
                    Set CExample = New Class_Example
                    CArray.CNew CExample
            Next i
    End Sub
    和:
    Private Sub Form_Load()
            Dim i As Long
            Set CExample = New Class_Example
            For i = 1 To 3
                    CArray.CNew CExample
            Next i
    End Sub
    看看有什么不同
      

  10.   

    to:homezj(小吉)你说对了,果然是高手,我的那个方法是有问题,后来我又改了一下,在Example类里加了一个拷贝构造函数,还改了一下Array里的接口部分,事件是实现了,可是和你说的一样,不能由类自身触发事件,只能从外部方法触发.其它的几种方法还没仔细看,我再研究一下,问题解决了马上就结帐.'-------------------------------------------------
    谢谢各位了.
      

  11.   

    晕,地址没写:http://vb.mvps.org/samples/code/ObjArrays.zip