在Visual Basic(以下簡稱VB)程序設計過程中,如何輕松地處理眾多的隨機事件,往往是制作大型系統首先要考慮的問題之一。例如,多個窗口同時打開同一個表(Table),一個窗口中對數據進行了修改,而其它窗口也能夠隨之進行數據更新,這時就需要有一條說明數據改變了的消息在所有窗口間進行廣播。在C中,只需要定義一條用戶消息即可實現這一點;而用VB編程就不那麼簡單。
對於以上問題,筆者早期的實現方法是,自定義一個消息結構(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 企業版增添了 嗲坑辛Φ奶匦裕可以解決以上難題。?/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
Attribute VB_Exposed = True
Option Explicit
消息類:定義全局的消息結構
Public iType As Long 消息類型編號
Public iName As String 消息名
Public iSource As String 消息源說明