在VB程序中处理随机事件

2016-02-19 14:54 15 1 收藏

下面是个简单易学的在VB程序中处理随机事件教程,图老师小编详细图解介绍包你轻松学会,喜欢的朋友赶紧get起来吧!

【 tulaoshi.com - 编程语言 】

  在Visual Basic(以下简称VB)程序设计过程中,如何轻松地处理众多的随机事件,往往是制作大型系统首先要考虑的问题之一。例如,多个窗口同时打开同一个表(Table),一个窗口中对数据进行了修改,而其它窗口也能够随之进行数据更新,这时就需要有一条说明数据改变了的消息在所有窗口间进行广播。在C中,只需要定义一条用户消息即可实现这一点;而用VB编程就不那么简单。 早期实现方法及局限性

  对于以上问题,笔者早期的实现方法是,自定义一个消息结构(VbMsg),并在程序的主窗体内建立一个消息广播引擎,主要由一个消息队列和一个定时消息广播器所组成。消息广播器每隔一固定时间检查一次消息队列,如果有消息存在,就将其发送给所有打开的窗口,并将该消息从队列中删除。如此再定义一个全局的消息发送过程(SendMsg),将要发送的消息(VbMsg)送入消息队列。这样当需要广播消息时,只需填充好消息结构,调用SendMsg过程即可。 

  这里较为复杂的是消息广播器如何将消息发送到各窗口。这需要作个硬性规定,即每一个窗体都必须定义一个形式完全相同的消息接收函数(RecMsg),在这个函数中对接收到的消息进行处理,当然也可以什么都不做。有了这样的规定之后,消息广播器在进行广播时,就可以利用VB系统定义的全局变量Forms,遍历所有的窗体,并调用一遍每个窗体的消息接收函数。其主要代码如下:

  

Public Sub SendMsgToForms(msg as VbMsg)Dim frm as FormFor Each frm In Formsfrm.RecMsg msgNext frmEnd Sub  

  通过上面的这些过程,就可以实现在独立的程序中,对随机事件进行异步处理。这一方法的效果基本令人满意。但是它有几个较大的局限性:

  ? 定时检查消息队列需要利用Timer控件进行触发,这在程序运行时,就必然要牺牲一部分效率;

  ? 消息广播的范围限定在一个程序模块内,如果整个系统分成多个大的模块,那么存在于动态链接模块(.DLL)中的窗体将不能直接接收到广播消息,更无法实现进程间的消息传递;

  ? 消息的接收者只能是窗体,而作为真正的基础单元类却无法直接接收消息。 

VB5.0的新特性及实现方法

  VB 5.0 企业版增添了 嗲坑辛Φ奶匦裕可以解决以上难题。?/p

  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

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  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

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  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)调用

  Public Sub SetMsg(msg As VbMsg)

  If msg.iType >= minMsg And msg.iType <= maxMsg Then

  RaiseEvent RecMsg(msg)

  nd If

  nd Sub

  根据ID返回对象的关键字,只应由消息服务器调用

  Public Property Get Key() As String

  Key = ID:& ID

  End Property

  类模块之三:Global.bas

  本模块声明了两个全局变量,一个是接收器(MsgClient)列表(Clients),一个是接收器计数器,为每个接收器分配一个唯一的ID标志。把变量放在单独的模块中,是为了实现数据在进程间的共享,是跨进程间消息传递的关键所在(应保证在编译时工程是单线程的,否则不能实现数据共享)。

  Attribute VB_Name = modGlobal

  Option Explicit

  消息服务器全局变量,消息接收客户列表

  Public Clients As New Collection

  消息接收客户ID计数器

  Public CliCount As Long

  类模块之四:MsgSrv.cls

  本模块定义了消息服务器类MsgServer,该类是消息广播引擎的主体,它主要管理维护消息接收器列表(Clients),将发送来的消息(调用SendMsg过程)依次发送给列表中的所有接收器。请注意:为了方便使用,该类被声明为公共全局类。

  

BEGINMultiUse = -1 TrueENDAttribute VB_Name = MsgServerAttribute VB_GlobalNameSpace = TrueAttribute VB_Creatable = TrueAttribute VB_PredeclaredId = FalseAttribute VB_Exposed = TrueOption Explicit

  消息服务器类,发送消息

  

Public Sub SendMsg(msg As VbMsg)Dim c As MsgClientFor Each c In Clientsc.SetMsg msgDoEventsNext cEnd Sub

  增删消息接收客户

  

Public Sub AddMsgClient(c As MsgClient)CliCount = CliCount + 1c.Id = CliCountClients.Add c, c.KeyEnd SubPublic Sub DelMsgClient(c As MsgClient)Clients.Remove c.KeyIf Clients.Count = 0 Then CliCount = 0End Sub 

  应用举例

  至此,一个小巧灵活的消息广播引擎就完成了,它的使用范围很广,用起来也很方便,只需在工程中引入编译过的ActiveX组件,就可以直接调用SendMsg发送消息。但可能在安装消息接收器(MsgClient)时会稍许有点麻烦,下面举例说明其应用。

  在设计Windows程序时,往往希望调试时能看到程序运行时后台的一些情况。利用VB的单步执行或Debug命令,会受到一些限制。利用消息广播引擎,制作一个通用的实时消息事件查看程序,就可以很好地解决这一问题。查看程序的主要工作是捕捉一组事先定义好的消息事件,并将消息的内容显示在列表框内。本应用可以只用一个窗体完成,主要代码如下。

  

Const MsgInfoID=101Private WithEvents mClient As MsgClientPrivate Sub Form_Load()Set mClient = New MsgClientMClient.minMsg= MsgInfoIDMClient.maxMsg= MsgInfoIDAddMsgClient mClientEnd SubPrivate Sub Form_Unload(Cancel As Integer)DelMsgClient mClientEnd SubPrivate Sub mClient _RecMsg(ByVal msg As VbMsgSrv.VbMsg)List1.AddItem msg.iTimeStr & Chr(9) & msg.iName & Chr(9) &sg.iDescriptionEnd Sub

  在被调试的程序中,为了调用方便,可以编写一个全局过程:

  

Const MsgInfoID=101Public Sub MsgInfo(iName As String,iDes As String)Dim msg As New MsgClientWith msg.iName = iName. iDescription = iDesEnd WithSendMsg msgEnd Sub 

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  在程序的重点环节插入MsgInfo过程,运行时有关信息就会在事件查看程序的窗口中显示出来。这种方法尤其适合调试多程序协作的软件系统。当软件系统正式交给用户时,插入的MsgInfo过程也不一定要全部删掉,只要将实时查看改为写入日志文件,作为日后软件维护的资料。

来源:http://www.tulaoshi.com/n/20160219/1608274.html

延伸阅读
在标准工程中添加一个公共对话框和两个按钮即可尝试本例: OptionExplicit '删除文件的API PrivateDeclareFunctionSHFileOperationLib"shell32.dll"Alias"SHFileOperationA"(lpFileOpAsToBin)AsLong '清空回收站的API PrivateDeclareFunctionSHEmptyRecycleBinLib"shell32.dll"Alias"SHEmptyRecycleBinA"...
OLE自动化是不同应用程序之间进行通讯的一个标准。OLE自动化的工作方式是:通讯被动方(OLE服务器)应用程序向通讯主动方(OLE客户机)应用程序提供一个以上可供其调用的OLE自动化对象类型,OLE客户机通过引用这些对象实现对OLE服务器的调用,然后通过设置对象的属性和使用对象的方法操纵OLE服务器应用程序,完成两者之间的通讯。 Visu...
    经常用Authorware制作练习型课件,最近发现了一个问题:学生在多媒体网络教室使用这些课件进行练习时,由于大家的题目都是一样的,所以难免会有学生互相“借鉴”。     因此笔者考虑能否制作随机出题的效果,即随机抽取题库中的题目,并且随机出现,现将本人在Authorware中研究出来的随机出题的制作方法...
由于API过程存在于VisualBasic应用程序之外的文件中,在使用时必须指定过程的位置和调用参数。可以用Declare语句提供这类信息。在声明了API过程之后,可以把它当做VisualBasic自己的过程使用。 如果在VisualBasic中直接调用API,那么VisualBasic环境下固有的安全机制将受到不利影响。这意味着在测试和调试程序时可能会遇到更多的系统故障...
尽管Windows的API函数在当今Visual成风的时代正渐渐被人们忘却,但是正如当年开发高技巧的DOS软件离不开汇编语言和DOS系统功能调用一样,无论开发平台高级到什么地步,只要Windows还在最底层运作,就要用到API函数。无论VB的开发手段多么高明,功能多么强大,但是在现实应用中,总有一些功能的实现是VB无能为力的。微软也早意识到这一点,...

经验教程

521

收藏

28
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部