VBA 类模块系列之十三——给类对象安装心脏起搏器

原计划本篇应该谈谈如何定义自己的事件的,比如给我们创建的第一个类Person定义一个生日提醒事件。然而,我发现,我们的Person类对象从一出生(Set objperson = New Person)到最后死亡(Set objperson = Nothing),中间是没有呼吸和脉搏的。

你在说什么?什么是呼吸和脉搏?

上面的3句代码不是类对象的呼吸和脉搏吗?

呃,你说的没错,这3句是类对象的呼吸和脉搏,但它的心脏就只跳动了3下而已。因为外界就只刺激了它3下,这3句代码执行完,我们的类对象的心脏就停止了跳动。

一个人,虽然活着,却需要外界刺激才能反应,这个人其实跟植物人没什么两样。一个植物人,你怎么能期望她主动告诉你:“下周我过生日”呢?

所以,在给我们创建的第一个类Person定义事件之前,我们得先给她安装一个心脏起搏器,要让她有一定的主观能动性才行。

心脏起搏器是个什么东西?它具体长什么样,我也不知道,但是你可以捂住你的胸口感受一下自己的心跳,你就会知道,它是一个非常有规律的脉冲,比如0.7秒跳动一下。我们从哪里去给我们的类Person找一个每0.7秒跳动一下的东西?

作为一个有一定经验的Access VBA开发人员,不知道你使用过窗体的Timer事件没有?没有没关系,我们一起来创建一个窗体3,在窗体3的属性表的事件选项卡中,将“计时器间隔”设置为一个大于0的数(比如说2000),然后为“计时器触发事件”编写一段响应程序,那么,每隔2000毫秒(2秒)时间,这段响应程序就会自动执行一次。如下图所示:

你保存一下窗体3,然后打开它,进到IDE界面,你会看到立即窗口中,每隔2秒,就会有一行文字“每隔2秒,这里就自动执行一次”。

如果将2000改为700,就是心脏跳动的频率了。这就是我们要给Person类安装的心脏起搏器。

那怎么安装到我们的Person类中呢?我们先来分析一下我们的需求。我们的Person类需要每隔0.7秒获得一个脉冲,而窗体3,它每隔0.7秒就能发起一个Timer事件,所以,如果我们在Person类中能够监听窗体3的Timer事件的话,我们的目的就达到了。

所以,我们在Person类的头部,定义一个与窗体3一样类型的窗体变量mfrm,因为Person类还要监听窗体变量mfrm所指向的窗体3的Timer事件,所以要添加WithEvents修饰符:

到目前位置,只是定义好了窗体变量mfrm,它还需要指向窗体3。套用上一篇的方法,在Person类的实例化事件Class_Initialize()中(对应着上一篇的窗体2的Form_Load()事件),将mfrm指向窗体3(Set mfrm = Forms(“窗体3”))。

当然这样做是没有问题的,需要注意的一点是,代码执行前,先要打开窗体3,否则Forms(“窗体3”)就报错。

窗体3是Person类的心脏起搏器,现在你把它打开了,呃,人人都看得到Person类的心脏起搏器,一个人,她的心脏长在外面,吓人就算了,你发现她的心脏右上角还有一个关闭按钮,那就真的有点说不过去了。一不小心人把她的心脏给关闭了可咋整?(当然,应该是关不掉的,原因暂按不表)

所以我们这里,换一种方法,如下:

第5行代码,有没有让你惊掉下巴^_^?其实很好理解,Form_窗体3是一个类的名字,所以 New Form_窗体3 就是创建一个Form_窗体3的类的对象,让mfrm这个窗体变量指向这个类对象。于是窗体3就在内存中被创建,但是,它不会显示出来,除非你设置它的Visible属性等于True。使用这种方式打开的窗体3,不会出现在Forms()中,所以你引用Forms(“窗体3”)是会报错的。

如果你问我,我们在定义mfrm的时候,指定的类型是Access.Form,为什么我们不给mfrm指定“Form_窗体3”类型?如果你能有这种疑问,说明你是带着脑子在看我的文章^_^。这里也先按下不表。因为涉及到面向对象的多态的概念,以后再谈。

好了,内存中创建了窗体3对象,mfrm也指向了窗体3。现在我们可以用指向窗体3的mfrm对象变量,任意的调用窗体3的属性和方法了。又由于mfrm前面加了关键字WithEvents,Person类对象可以监听窗体3的任何事件了!为什么任意任何被我加粗了?我想强调的是一种自由,一种想干嘛就可以干嘛的自由。通过mfrm,窗体3现在是你的提线木偶,一切听你的指示,做上帝的感觉又来了,有木有?^_^

现在可以监听窗体3的Timer事件了吗?呃,要看情况。要看什么情况?我们知道窗体的Timer事件的触发,是需要条件的,什么条件?窗体的“计时器触发”属性和“计时器间隔”属性必须要设置正确,Timer事件才能正常被触发。我们的第一个图中,“计时器触发”属性的值是“[事件过程]”,“计时器间隔”属性的值是“2000”,都已经设置好了呀?

是的,你没有看错,上面的截图确实是这样设置好了的。但是,心脏这么重要的事情,你能交给别人去帮你设置这2个重要属性的值吗?如果万一某个人打开窗体3,把这2个属性值给改了,怎么办?所以要确保万无一失,我们使用木偶的线mfrm来设置窗体3的这2个属性:

这里,直接将计时器间隔(TimerInterval)2000的原始值,覆盖为700。

好了,现在可以为mfrm监听到的窗体3的Timer事件写事件响应代码了:

现在窗体3的Timer事件,有了2个监听者,一个是Person类对象,通过mfrm监听,另一个是窗体3本身,还记得窗体3中的 Form_Timer()代码吧?窗体3的Timer事件,只需要Person类对象来监听就好了,我们将窗体3中的Form_Timer()代码注释掉。

最后,在Person类的销毁事件中,将mfrm对象变量的指针释放掉:

好了,Person类对象的心脏起搏器安装完毕。我们在模块1中写如下测试代码:

第14到16行代码,写了一个无限循环的语句。目的是为了让Test中定义的objPerson对象一直存活下去。DoEvents是释放线程控制权的意思。运行Test代码,你会在立即窗口中看到如下的消息:

这段测试代码,你不干预,它会永远运行下去,所以,当你听厌了赵冰冰的呼喊声后,可以点停止按钮强行停止执行。

对代码有洁癖的人,是不会就此罢休的。所以,再创建一个窗体4,在窗体4的代码窗口写如下测试代码:

使用窗体4做类的代码测试的好处是,只要窗体4打开后不关闭,objPerson对象就一直存活在内存中,你就可以一直听到赵冰冰的心跳和呼喊声,直到关闭窗体4。^_^

这回的出生入死的记录就完整了^_^

最后,就不按惯例贴出所有代码了。因为有点长,窗体也比较多。直接将我的Access文件贴在这里,供大家下载。VBA 类模块系列之十三——给类对象安装心脏起搏器

下一篇应该不会跳票了,开讲自定义事件和触发自定义事件。敬请期待^_^

发表评论

电子邮件地址不会被公开。