对于以上问题,笔者早期的实现方法是,自定义一个消息结构(VbMsg),并在程序的主窗体内建立一个消息广播引擎,主要由一个消息队列和一个定时消息广播器所组成。消息广播器每隔一固定时间检查一次消息队列,如果有消息存在,就将其发送给所有打开的窗口,并将该消息从队列中删除。如此再定义一个全局的消息发送过程(SendMsg),将要发送的消息(VbMsg)送入消息队列。这样当需要广播消息时,只需填充好消息结构,调用SendMsg过程即可。
这里较为复杂的是消息广播器如何将消息发送到各窗口。这需要作个硬性规定,即每一个窗体都必须定义一个形式完全相同的消息接收函数(RecMsg),在这个函数中对接收到的消息进行处理,当然也可以什么都不做。有了这样的规定之后,消息广播器在进行广播时,就可以利用VB系统定义的全局变量Forms,遍历所有的窗体,并调用一遍每个窗体的消息接收函数。其主要代码如下:
Public Sub SendMsgToForms(msg as VbMsg)
Dim frm as Form
For Each frm In Forms
frm.RecMsg msg
Next frm
End Sub
通过上面的这些过程,就可以实现在独立的程序中,对随机事件进行异步处理。这一方法的效果基本令人满意。但是它有几个较大的局限性:
? 定时检查消息队列需要利用Timer控件进行触发,这在程序运行时,就必然要牺牲一部分效率;
? 消息广播的范围限定在一个程序模块内,如果整个系统分成多个大的模块,那么存在于动态链接模块(.DLL)中的窗体将不能直接接收到广播消息,更无法实现进程间的消息传递;
? 消息的接收者只能是窗体,而作为真正的基础单元“类”却无法直接接收消息。
VB 5.0 企业版增添了 嗲坑辛Φ奶匦裕梢越饩鲆陨夏烟狻!?
1、 用户自定义事件
在类模块中,可以使用Event关键字来定义用户自定义事件,使用 RaiseEvent 语句来产生该事件,这一机制给处理随机事件带来了很大方便。本文中的消息广播引擎,就可以不再使用Timer控件做支持,而是当收到需要广播的消息时,产生一个预定义的事件;而需要处理消息的客体对象,只需截获该事件。
2、 ActiveX EXE组件
利用VB,可以方便地将共享代码封装在ActiveX组件之中,从而可以实现跨进程间的消息传递。因为ActiveX组件有内部(DLL)、外部(EXE)两种,外部组件可以对模块内的全局数据实现共享。
3、 远程自动化连接
ActiveX组件是一种标准的客户机/服务器结构,利用Windows平台的COM模型,VB能够方便地将这种结构扩展到整个网络的范围。所以,消息广播设计既可实现进程间的消息传递,也可实现网络上的消息传递。
根据以上思想,笔者通过四个模块之间的相互协作,完成了消息的发送、广播及接收,并将这四个模块封装在一个ActiveX EXE组件之中。下面就是这四个类模块的简单介绍及源代码。
类模块之一:Msg.cls
该模块定义了消息数据结构VbMsg类,它是消息传递中的载体。这里只是一个简单的例子,如果想实现更多的功能,如建立两点间的数据通道,而不是单纯的广播消息,则要对该结构进行一些扩充。
BEGIN
MultiUse = -1 True
END
Attribute VB_Name = “VbMsg"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
Option Explicit
消息类:定义全局的消息结构
Public iType As Long 消息类型编号
Public iName As String 消息名
Public iSource As String 消息源说明
Public iDescription As String 消息说明
Dim iT As Date 消息发生时间
返回日期型时间
Public Property Get iTime() As Date
iTime = iT
End Property
返回字符型时间
Public Property Get iTimeStr() As String
iTimeStr = Format(iT, “yyyy.mm.dd hh:mm:ss")
End Property
在对象被建立时,设置消息发生时间
Private Sub Class_Initialize()
iT = Now()
End Sub
类模块之二:MsgCli.cls
本模块是对客户接收端MsgClient类的定义,这相当于一个消息接收器。在这个类中定义的一个RecMsg事件,当接收器收到消息时(过程SetMsg被调用),就产生这一事件;接收器的建立者截获这一事件,并处理消息。为了避免接收不必要的消息,声明了minMsg、maxMsg两个变量,以便对VbMsg中的iType属性进行过滤。
BEGIN
MultiUse = -1 True
END
Attribute VB_Name = “MsgClient
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
Option Explicit
客户消息接收类
定义接收消息事件,该对象的宿主类应截获该事件,并处
理接收到的消息
Public Event RecMsg(ByVal msg As VbMsg)
通过设置消息的接收范围,过滤掉不需要的消息
Public minMsg As Long
Public maxMsg As Long
该对象的标志编号,使用时不应修改该值
Public ID As Long
事件产生过程,只应由消息服务器(MsgServer)调用文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!



