明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

VB6中處理自定義窗口消息

[摘要]作者: ZDNET CHINA 特稿在vb程序間進(jìn)行跨進(jìn)程通信不是一件容易的事。我曾經(jīng)見過許多的程序開發(fā)員試圖通過各種各樣的方法來完成這一工作,這些辦法包括從將信息寫入共享的文本文檔或注冊表鍵到使用成熟的activeX程序通信服務(wù)器。每一種辦法都有缺點(diǎn):以前的辦法容易產(chǎn)生錯(cuò)誤,而現(xiàn)在的這些方法又由...
作者: ZDNET CHINA 特稿

在vb程序間進(jìn)行跨進(jìn)程通信不是一件容易的事。我曾經(jīng)見過許多的程序開發(fā)員試圖通過各種各樣的方法來完成這一工作,這些辦法包括從將信息寫入共享的文本文檔或注冊表鍵到使用成熟的activeX程序通信服務(wù)器。每一種辦法都有缺點(diǎn):以前的辦法容易產(chǎn)生錯(cuò)誤,而現(xiàn)在的這些方法又由于在服務(wù)器中呼叫每一個(gè)對象的時(shí)候都會(huì)發(fā)生跨進(jìn)程操作,又使其效率變得非常低。有一個(gè)經(jīng)過實(shí)踐檢驗(yàn)的方法是,將要跨進(jìn)程的通信掛接到你自己的VB程序的消息序列中,同時(shí)傾聽從其它進(jìn)程中傳來的自定義窗口消息,一種被大家稱之為"子類"的技術(shù)。


我曾經(jīng)描述過如何以及為什么在VB編程語言中要運(yùn)用"子類",而且我還展示了如何使用視窗應(yīng)用編程接口來將消息發(fā)送到你的應(yīng)用程序以及解鎖的隱藏控制功能中去。在本篇文章中,我會(huì)向大家解釋如何才能向其他的應(yīng)用程序發(fā)送消息以及如何發(fā)送消息才能解決跨進(jìn)程的通信難題。同時(shí),我還會(huì)給大家提供可再度使用的ActiveX DLL, Messenger.dll,來讓各位在將自定義消息運(yùn)用于自己的程序的時(shí)候盡可能的簡單起來。

傳送信息時(shí)與其它程序之間的相互作用

因?yàn)橄魉褪荳indows和在它上面運(yùn)行的程序之間通信的最基本方式,任何窗口或者控制任何的應(yīng)用程序都可以通過使用SendMessage或者相關(guān)的軟件來發(fā)送消息。此外,那些標(biāo)準(zhǔn)的消息對于所有運(yùn)行于Windows的應(yīng)用程序都有著相同的含義。有了這兩點(diǎn),我們就能得出一個(gè)令人吃驚的結(jié)論:通過發(fā)送消息,人們可以輕而易舉的控制任何的當(dāng)前正在運(yùn)行的應(yīng)用程序,甚至還包括那些并不應(yīng)該被別人操控的應(yīng)用程序。舉個(gè)例子來說:


當(dāng)你使用WM_xBUTTONDOWN 以及 WM_xBUTTONUP來傳送消息的時(shí)候,你可以在別的應(yīng)用程序中模擬鼠標(biāo)的點(diǎn)擊操作。

發(fā)送WM_KEYDOWN 以及 WM_KEYUP消息的時(shí)候,會(huì)模擬出按鍵盤的操作。

有惡意的程序員能夠通過發(fā)送一條WM_CLOSE消息到最高級窗口來迫使其它的應(yīng)用程序關(guān)閉,或者通過使用WM_ENDSESSION來讓其它的應(yīng)用程序誤以為Windows操作系統(tǒng)正在關(guān)閉。

指出你是在和誰談話

發(fā)送消息到另一個(gè)窗口的關(guān)鍵并不取決于你的應(yīng)用程序,而是取決于窗口句柄。Windows操作系統(tǒng)的應(yīng)用編程接口有許多的功能能夠重新得到特定的窗口句柄,其中最經(jīng)常使用的一個(gè)就是FindWindow功能。這個(gè)功能能夠在標(biāo)題說明中找到基于文本的最高級別的窗口(lpWindowName),并且返回到它的窗口句柄。在VB編程語言中關(guān)于FindWindow是如下這么描述的:


Private Declare Function FindWindow Lib "user32" _
Alias "FindWindowA" (ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long


找到子窗體

你能通過使用FindWindowEx來找到子窗體句柄,就象是一個(gè)表格中的特殊控制一樣。



自定義消息提供了一種共通的語言

  
現(xiàn)在讓我們來復(fù)習(xí)一下:發(fā)送消息是一種簡單有效的與其它應(yīng)用程序進(jìn)行交流的方法,而且你能夠輕松的通過發(fā)送標(biāo)準(zhǔn)的Windows消息來模擬出用戶與圖形用戶界面程序之間的相互作用。但是,如果你需要分程傳遞一些非標(biāo)準(zhǔn)的消息到你的另一個(gè)也許已經(jīng)準(zhǔn)備就緒進(jìn)行處理的程序的時(shí)候又該如何去做呢?當(dāng)然,這是完全能夠做到的,重新定義一個(gè)標(biāo)準(zhǔn)消息的含義來表達(dá)"數(shù)據(jù)已經(jīng)準(zhǔn)備就緒,"使其它程序的主窗口子類化,并且對此消息進(jìn)行特殊的處理。


這么做真的有效果嗎?是的,答案是肯定的。但是這遠(yuǎn)遠(yuǎn)不是最佳的解決辦法。首先,你的數(shù)據(jù)處理程序不會(huì)對你決定進(jìn)行重定義的任何消息做出像正常時(shí)一樣的反應(yīng)。如果你能夠定義一條制有你的程序能夠明白的自定義消息的話,會(huì)比較好一些。


令人感到愉快的是,RegisterWindowMessageAPI函數(shù)就是這樣的。你只需要傳遞給它一個(gè)單獨(dú)的文本消息標(biāo)識符,剩下的工作就可以讓這個(gè)功能自己去完成了。其中的工作包括,向Windows注冊此消息,返回一條專門的消息標(biāo)識符,這條專門的消息標(biāo)識符必須被保證是唯一的而且對于當(dāng)前的Windows是有益的。之后,用相同的消息標(biāo)識符呼叫RegisterWindowMessage功能,無論是從相同的還是從不相同的程序中,會(huì)把這個(gè)分配給第一次呼叫的相同的標(biāo)識符返回。VB編程語言對于RegisterWindowMessage有如下聲明:


Private Declare Function RegisterWindowMessage _
Lib "user32" Alias "RegisterWindowMessageA" _
(ByVal lpString As String) As Long


把碎片組合在一起

這是解決跨進(jìn)程通信的最后一塊碎片。任何需要從別的程序接收自定義消息的程序會(huì)子類化它的主窗口,并且提供一個(gè)單獨(dú)的窗口標(biāo)題來讓它的hWnd能被FindWindow輕松的獲得。(第一個(gè)應(yīng)用程序應(yīng)該用另一種方法來定位第二個(gè)程序的hWnd。)兩個(gè)程序都注冊相同的自定義窗口消息,并且懸掛到他們接收到的標(biāo)識符上去。當(dāng)一個(gè)程序需要將自定義消息鎖代表的通知給另一個(gè)程序的時(shí)候,它會(huì)發(fā)現(xiàn)另一個(gè)程序的窗口句柄,并且通過使用SendMessage變量來發(fā)送自定義消息。任何額外的信息都會(huì)由于SendMessage注釋:swParam 以及l(fā)Param參數(shù)或者它的返回碼而相互聯(lián)絡(luò)。


根據(jù)我所說的,我編了一個(gè)在VB6程序中能夠被用來實(shí)現(xiàn)自定義消息特別的Messenger組件。這個(gè)組件的源代碼可以從下邊的列表中找到:


Listing A是這個(gè)組件主要類別的源代碼,cMessenger。

為個(gè)人使用的源代碼被稱之為cMessageInfo,可以在Listing B中被找到。

在Listing C中你能找到的是用來function addresses以及需要功能模塊的時(shí)候的組件源代碼。

Messenger負(fù)責(zé)為用戶子類,注冊,接聽,以及發(fā)送自定義消息。這是相當(dāng)安全的,因此,多個(gè)應(yīng)用程序都能夠使用此組件的同一拷貝。


StartListening方法被看作是一個(gè)窗口對子類的句柄中唯一的參量。它為此窗口嵌入它自己的窗口程序,并且開始等待你用RegisterMessage方法定義的自定義消息。這樣能夠通過提高IncomingMessage事件以及只回應(yīng)你使用RegisterMessage注冊的自定義消息來確定是否收到一條自定義消息。在關(guān)閉窗口之前,通過使用StopListening功能,確保已經(jīng)把cMessenger從窗口消息序列中去掉了。


你可以使用SendMessage來傳送消息到其它的應(yīng)用程序。SendMessage認(rèn)可你希望通報(bào)的窗口標(biāo)題,同時(shí)也認(rèn)可你使用RegisterMessage注冊的消息文本。你能夠通過使用RegisterWindow或者 RegisterWindowByHandle手動(dòng)將新的窗口添加到高速緩存中去。