VBA中自定义类和事件的(伪)注册

想了解一下VBA中自定义类和事件,以及注册事件处理程序的方法。

折腾了大半天,觉得这样的方式实在称不上“注册”,所以加一个“伪”字。纯粹是瞎试,原理也还没有摸透。先留着,有时间再接着摸。

做以下尝试:

1、建一个自定义类(类模块),类名:Qiqiu

    该类提供一个Daqi的方法,每执行一次,x(记录气球的体积)的值+i,如果x的值大于max,则触发自定义的Change事件。

    为节省细节不使用属性过程,变量直接用public

 1 Public Event Change(q As qiqiu)   'Event关键字声明事件,事件参数是Qiqiu类型。 
'推模式还是拉模式?一直感觉有参数的都该是推模式,傻傻分不清楚啊。 2 Public x As Integer '记录实际体积 3 Public max As Integer '记录最大体积 4 Function Daqi(i As Integer) '模拟给Qiqiu打气的情形 5 x = x + i 6 If x > max Then 7 RaiseEvent Change(Me) 'RaiseEvent关键字触发事件。在事件触发时,把自已的实例引用传给订阅者。 8 x = 0 9 End If 10 End Function

2、建三个简单窗体MainFrm,UserFrm1,UserFrm2

    MainFrm启动后,点击“弹出窗体按钮”,UserFrm1和UserFrm2显示出来

   

3、UserFrm1、UserFrm2需要关联Qiqiu的Change事件(观察气球状态的变化对事件做出响应),需要做一些准备

    下面是UserFrm1中的代码(为简化案例,UserFrm2的代码和UserFrm1完全相同,实际上可以完全是不同的响应)

    注意第一行的WithEvents关键字的变量声明,后面需要使用这个变量将方法(事件处理程序)关联到事件。

1 Public WithEvents qiu As Qiqiu          '关联Qiqiu的事件的关键,维护一个Qiqiu的引用,既然有引用,本案的Change事件的参数就显得很多余。
2 
3 Private Sub qiu_Change(q As Qiqiu)      '事件的响应程序
4 Me.TextBox1 = "气球爆炸了,爆炸时体积是:" + CStr(q.x) 5 End Sub

4、MainFrm主窗体代码:

 1 Public q As Qiqiu 
 3 Private Sub UserForm_Initialize()
 4     Set q = New Qiqiu                      '窗体初始化,初始化Qiqiu类的实例
 5     q.max = 10                             '将q的最大体积设定为10
 6 End Sub
 8 
 9 Private Sub btn_Click()              '点击按钮“弹出窗体”执行的代码,实例化UserFrm1和UserFrm2并显示 
11 Dim f1 As UserFrm1, f2 As UserFrm2
13   Set f1 = New UserFrm1
14   Set f2 = New UserFrm2
16   Set f1.qiu = q        '第3中的WithEvents关键字声名的变量在此处使用
17   Set f2.qiu = q        '使f1.qiu,f2.qiu分别指向Qiqiu类的实例q(即:注册)
19     f1.Show False
20     f2.Show False
22 End Sub
23 
24 Private Sub btndq_Click()          '点击按钮“打气”执行的代码   
26      q.daqi (5)                    '调用q的打气方法给Qiqiu打气,每次打入气体体积为5。当q.x大于q.max时触发事件  
28 End Sub

 5、程序执行效果:(虽然实现了效果,但理解上感觉模模糊糊)

      打气三次时触发事件(此时气球的体积是15,超过了气球的max体积10),事件关联的处理程序提示,气球爆炸,并获取爆炸时的体积

    

6、小结:

     VBA中,类的事件可能是很封闭的。不像C#事件开放了注册和移除的接口,只要方法签名相同,就可以很方便的指向事件的响应方法,根本不需要在订阅者类的内部再声明和发布者直接相关东西(变量引用),减小耦合度。

     其实摸索了VBA的对象浏览器后,也可以找到类中事件的冰山一角,可以看到它的签名。比如Worksheet的Change事件。

    

7、补充一点转来的总结(我自己按想法修改了一些用词):

    主题对象(被观察者、事件发布者)对客户端(观察者、订阅者)一无所知

  1. 观察者引用一个主题对象,对这个观察者,它可将引用放置在 WithEvents 变量中来处理那些主题对象。发布者没有订阅者的信息。它向未知数目的听众进行广播, 剧院中可能一个观众都没有。
  2. 主题对象不会控制接收事件的观察者的次序。(好像这点和C#有很大不同,C#事件注册的顺序可以决定事件的执行顺序)
  3. 当对象引发事件时,其所有订阅者都在引发事件的对象再次获得控制之前处理该事件。
  4. 如果事件包含 ByRef 参数,则该参数可被任何处理事件的客户程序改变。只有最后的客户端进行的改变才对引发事件的对象可见,因为(如上所述),直到所有客户端都处理该事件之前,引发事件的对象不会再度获得控制。

    为了将某个事件添加到一个类中,然后使用该事件,可以这样做:

  1. 在定义类的类模块声明部分,用 Event 语句来声明事件—该事件带有希望它带有的任何参数。事件总是 Public。 注意 事件不能有命名的参数、Optional可选的参数、或 ParamArray可变参数。事件没有返回值。
  2. 在类模块代码中的合适地方,用 RaiseEvent 语句来引发事件,并提供所需要的参数。
  3. 在将要处理事件的模块声明部分,使用 WithEvents 关键字,添加该类类型的变量。它必须是一个模块级的变量。
  4. 在代码窗口左边的下拉菜单上,选择声明为 WithEvents 的变量。
  5. 在代码窗口右边的下拉菜单上,选择希望处理的事件。(可以为类声明多个事件。)
  6. 使用所提供的参数,将代码添加到事件过程中。

转载于:https://www.cnblogs.com/zzstone/p/5521296.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值