編寫VB程序時(shí),經(jīng)常遇到的問(wèn)題就是VB給我們準(zhǔn)備的東西我們會(huì)用,控件組裝就是一個(gè)程序,然而一旦想要實(shí)現(xiàn)VB沒有直接提供的功能,就會(huì)不知所措。其實(shí)Windows操作系統(tǒng)本身就給我們準(zhǔn)備了許多東西,VB沒有的,或許Windows有。我們當(dāng)然希望少花力氣,多得效果。這里要講的內(nèi)容就是——學(xué)會(huì)利用Windows給我們的東西:API。
然而,學(xué)會(huì)一種東西是需要付出相當(dāng)?shù)呐Φ模珹PI也一樣,它可以給我們帶來(lái)很大的方便,但想要掌握它,就不是使用幾個(gè)控件那么輕松的事了。所以在看這篇文章時(shí),希望讀者可以抱一個(gè)正確的態(tài)度,就是學(xué)習(xí)編程不是為好玩,而是為使用; 不要以自己對(duì)這方面是否有興趣而看,而要為API是否能為你的程序帶來(lái)效果而看。我并不是說(shuō)一切都是那么嚴(yán)肅和困難,只是API對(duì)VB來(lái)說(shuō),已經(jīng)可以算高級(jí)方面的應(yīng)用了,所以“認(rèn)真”和“仔細(xì)”是需要的。好了,放松一點(diǎn),讓我們從現(xiàn)在起一步步領(lǐng)略API的好處吧。 前言 1.API API全稱為Application Programming Interface,直譯的話可叫它“應(yīng)用程序接口”。從意義上來(lái)說(shuō),API是一個(gè)操作系統(tǒng)或某個(gè)程序本身提供給其他程序使用的函數(shù)。在Windows操作系統(tǒng)中,有成千個(gè)Windows的函數(shù)提供給應(yīng)用程序使用,本文所說(shuō)的API,就是指這些函數(shù)。 2.VB與API 之所以寫這篇文章(而不寫VC或其他語(yǔ)言),是因?yàn)閂B對(duì)API的支持不是直接的,而且是不完全的; 在使用上,Windows的API編寫時(shí)是假設(shè)調(diào)用者是C或C++語(yǔ)言,因此VB調(diào)用API不是很方便,也經(jīng)常有不必要的錯(cuò)誤或不明白如何使用的情況出現(xiàn)。本文的對(duì)象主要還是對(duì)API沒有很深研究的讀者,如果你不想了解太多細(xì)節(jié),你可以把一個(gè)合適的函數(shù)用法搬過(guò)去,或者你完全不知道API,或者只知道少數(shù),對(duì)許多函數(shù)還不清楚如何使用,或者你希望可以從本文學(xué)到更多使用API的技巧甚至VB的技巧(但愿我可以讓你學(xué)到),我想你都應(yīng)該看這篇文章。但還是有個(gè)大前提,你必須是已經(jīng)會(huì)使用VB的讀者,因?yàn)橐院笾v到的內(nèi)容不會(huì)有一個(gè)完整工程從頭到尾教你做,有可能是一段簡(jiǎn)短的聲明與調(diào)用代碼,也可能是幾個(gè)函數(shù)的組合,如果必要的話,也會(huì)講述相關(guān)內(nèi)容的VB技巧,但一定不會(huì)有完整的實(shí)例示范。 3.本文原則和約定 由于API中有的用法簡(jiǎn)單有的復(fù)雜,有的可單獨(dú)使用有的卻不行,加上各個(gè)API的主要用途不同,很難判斷先說(shuō)哪個(gè)再說(shuō)哪個(gè)可以讓人更容易理解,因此本文盡量從比較常用的說(shuō)起,從可以對(duì)程序產(chǎn)生較大作用的說(shuō)起。為了能讓多數(shù)人理解,如果需要涉及到其他方面的知識(shí),也將盡量講述,讓讀者可以學(xué)到使用API的知識(shí),并能夠利用本文中的知識(shí)應(yīng)付新的API。如果你對(duì)某個(gè)API有什么疑問(wèn),歡迎來(lái)信(webmaster@neocactus.com),但由于時(shí)間有限,不能對(duì)來(lái)信一一回復(fù),如果有需要,將會(huì)在文中講述。 基礎(chǔ)知識(shí) 在講API之前,讓我先講解一些與API相關(guān)的VB基礎(chǔ)知識(shí),后文如有涉及將不再詳述。此處未提及的,將在本文中第一次接觸時(shí)再做解釋。 1.自定義類型 VB中可以使用Type關(guān)鍵字將已有的數(shù)據(jù)類型進(jìn)行組合,成為一個(gè)新的類型,該類型就稱為用戶自定義類型。如: Type NewType 定義了一個(gè)名為NewType的自定義類型。以后可以用Dim MyType As NewType來(lái)定義一個(gè)NewType類型的變量。 sName As String類型的變量有兩種,一種是變長(zhǎng),即運(yùn)行時(shí)的字符串長(zhǎng)度是可變的,另一種是定長(zhǎng),運(yùn)行時(shí)字符串的長(zhǎng)度是固定的。平常我們定義一個(gè)字符串變量: Dim strA As String 即定義了一個(gè)變長(zhǎng)的字符串,但在使用API時(shí)經(jīng)常要用到定長(zhǎng)的字符串,應(yīng)該這樣定義: Dim strB As String * 30,即定義了一個(gè)可容納30個(gè)字節(jié)字符的變量。 2.聲明 VB中使用API之前,需要先對(duì)API進(jìn)行聲明,聲明的方法是使用Declare關(guān)鍵字,如: 3.句柄 API中使用得最多的一個(gè)詞大概就是“句柄”了。如果要說(shuō)得復(fù)雜些,句柄的確可以說(shuō)上一大堆,不過(guò)作為VB的應(yīng)用,我們可以更簡(jiǎn)單地去理解它??梢赃@么說(shuō),句柄是Windows系統(tǒng)賦予內(nèi)存中每一個(gè)對(duì)象,包括窗口、按鈕(其實(shí)也是一種窗口)或者文件、圖標(biāo)、菜單等等所有東西的標(biāo)識(shí)。所謂標(biāo)識(shí)就如身份證一樣,是不會(huì)重復(fù)并且和實(shí)際對(duì)象是一一對(duì)應(yīng)的。它的作用是讓W(xué)indows知道將被操作的對(duì)象是誰(shuí)。許多VB控件都提供了一個(gè)長(zhǎng)型的hWnd屬性,一般情況下,這個(gè)屬性就是這個(gè)控件的句柄,用API控制這個(gè)控件時(shí)就需要用到這個(gè)屬性了。 4.設(shè)備上下文 其實(shí)我覺得“設(shè)備上下文”這個(gè)詞讀起來(lái)很奇怪,不過(guò)就其字面來(lái)看,Device Context(DC,可不是直流電或DreamCast哦)就是這個(gè)意思,許多人也這么稱它。不過(guò)我想翻譯為“設(shè)備中介”大家應(yīng)該更容易理解吧。它的作用是作為計(jì)算機(jī)設(shè)備和程序之間的中介,比如顯示器和程序之間,或者打印機(jī)和程序之間。在對(duì)這些設(shè)備操作的時(shí)候,是需要通過(guò)這個(gè)中介操作的(與句柄相似),一些控件,如 Picture,想在上面畫圖時(shí),就要用到hDC屬性了。
5.顯式聲明與自動(dòng)保存 在默認(rèn)情況下,Visual Basic會(huì)把未聲明的變量認(rèn)為是新變量(即使是你不小心打錯(cuò)字了),這樣很容易出現(xiàn)錯(cuò)誤,而且要找出這樣的錯(cuò)誤往往很不容易。加上API的操作基本上都會(huì)涉及到系統(tǒng)本身,一旦出錯(cuò)就有可能出現(xiàn)Visual Basic崩潰甚至系統(tǒng)崩潰。所以到Visual Basic的選項(xiàng)設(shè)置中選上Require Variable Declaration(需要變量聲明)。在 Enviroment(環(huán)境)頁(yè)中的When a program starts(當(dāng)程序啟動(dòng)時(shí))處選上Prompt To Save Changes(提示保存)或 Save Changes(自動(dòng)保存)。這樣Visual Basic會(huì)檢查變量是否已經(jīng)聲明,不再允許沒有聲明的變量出現(xiàn)了。 6.API瀏覽器 前面講“聲明”的時(shí)候提到了API瀏覽器,這里也說(shuō)一說(shuō)它。在安裝完VB時(shí),安裝程序會(huì)把API瀏覽器復(fù)制到你的計(jì)算機(jī)里。啟動(dòng)后界面如圖1(以VB6為準(zhǔn))。可以看到,從API瀏覽器里我們可以得到API的聲明、常量值以及與API相關(guān)的自定義類型的定義。其中Declare Scope(聲明范圍)是指該聲明是公有的還是私有的。對(duì)于在標(biāo)準(zhǔn)模塊中的聲明,如果聲明為私有,則只對(duì)該模塊有效,如果為公有,則對(duì)整個(gè)程序都有效。在窗體模塊中只能聲明為私有。 7.MSDN MSDN是微軟發(fā)布的一套完整的Windows開發(fā)者技術(shù)文檔(如圖2)。里面不僅有VB、VC++、VFP、MSDEV、VSS等開發(fā)工具的完整幫助,而且包含了Windows平臺(tái)開發(fā)的幾乎所有的技術(shù)資料,并不斷地更新。我們需要的API資料這里都有很詳細(xì)的說(shuō)明,包括使用平臺(tái)、參數(shù)類型、參數(shù)作用等(當(dāng)然它并非完全正確,錯(cuò)誤的地方也時(shí)有出現(xiàn))。不過(guò)作為以C為基礎(chǔ)的API,這里的資料是英文的,而且格式也是C語(yǔ)言格式。想要讀懂,那你的英文水平和C語(yǔ)言就要有兩把刷子了。不過(guò)不必?fù)?dān)心,它只是我建議一定要有的參考文檔,最重要的還是我接下來(lái)要講的內(nèi)容,它不僅是中文的,還是VB的,又有使用示例,還有相關(guān)知識(shí)講解。記住MSDN只是參考文檔,作用就好像字典,可千萬(wàn)不要買了一套MSDN就跑去跟別人說(shuō)你已經(jīng)變得多厲害了,不然…… 順便說(shuō)一說(shuō),以前的MSDN是雙CD的,現(xiàn)在已經(jīng)變成3CD了。如果買的話應(yīng)盡量買最新的(但沒有必要每次更新都換一套),因?yàn)楦碌陌姹景岩恍╁e(cuò)誤改正了,并增加了新的內(nèi)容,比如最新的MSDN已經(jīng)增加了許多Windows XP的內(nèi)容。你可以從微軟的中國(guó)網(wǎng)站訂到這套文檔,不過(guò)一年的價(jià)錢從一萬(wàn)幾到三萬(wàn)幾,買不起的話……自己想辦法吧。 好了,開篇寫了這么多,無(wú)非也是想讓讀者在以后可以更容易理解所講的內(nèi)容。這些是基礎(chǔ),是一定要記住的。下面我們就先介紹一個(gè)比較簡(jiǎn)單的API,開始我們的API之旅吧! 第一話 從消息說(shuō)起 由于這是《細(xì)水長(zhǎng)流話API》的第一話,我必須注意到所講的內(nèi)容要簡(jiǎn)單,并且讓你有耐心可以看到往后的文章,所以我希望可以通過(guò)一個(gè)比較特別的例子來(lái)引起你的注意(這樣的情況不會(huì)總是有的)。讓我們想想,VB里的CommandButton控件讓我們可以做什么?按下、彈起,還有呢?請(qǐng)看看圖3,這樣的情況在你的程序運(yùn)行時(shí)出現(xiàn)過(guò)嗎? Windows是以消息來(lái)傳遞信息的。當(dāng)出現(xiàn)某個(gè)操作,比如按鈕被按下,就產(chǎn)生按鈕被按下的消息。消息被傳送到被操作對(duì)象(按鈕),事件就產(chǎn)生了。應(yīng)注意不是按鈕產(chǎn)生消息,而是Windows知道這個(gè)操作的發(fā)生,向按鈕發(fā)送這個(gè)消息,按鈕收到后再做相應(yīng)的處理——如改變外觀成為按下的狀態(tài)。 Windows允許第三者向某個(gè)對(duì)象發(fā)送消息,因此當(dāng)某個(gè)操作沒有發(fā)生時(shí),我們是可以讓對(duì)象如同收到消息一樣產(chǎn)生效果的,這就需要用到API函數(shù)——SendMessage了。 SendMessage的聲明前面已經(jīng)說(shuō)過(guò)(注意以Public開頭應(yīng)放在標(biāo)準(zhǔn)模塊中,否則用Private開頭),它的各個(gè)參數(shù)中,hwnd是對(duì)象的句柄,wMsg是消息的值(具體什么消息),另外兩個(gè)參數(shù)根據(jù)不同消息和不同應(yīng)用有不同的值。 你看到的圖3的情況,是由于我的程序向Command Button控件發(fā)送了WM_NCLBUTTONDOWN消息。這個(gè)消息發(fā)生在鼠標(biāo)在窗口的非客戶區(qū)域上按下時(shí)。所謂非客戶區(qū)域,你可以理解成一個(gè)窗口的邊緣和標(biāo)題欄(當(dāng)然是指一般情況,這種情況是可以被程序改變的)。 在我這個(gè)按鈕的MouseDown事件中,只寫了短短的幾句: Private Sub cmdResize_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) With cmdResize
可以看到,我讓鼠標(biāo)拉動(dòng)按鈕時(shí),拉按鈕左邊是用 HTLEFT做參數(shù),拉右邊是用HTRIGHT做參數(shù)。這兩個(gè)都是常量,可以從API瀏覽器中得到值。同樣的,若想拉按鈕的上面和下面,可用HTTOP和HTBOTTOM做參數(shù),而 HTTOPLEFT和HTBOTTOMRIGHT則分別是左上角和右下角。 在發(fā)送消息之前有一個(gè)ReleaseCapture的API。這個(gè)API是讓W(xué)indows釋放對(duì)鼠標(biāo)的捕捉以便使鼠標(biāo)位置的信息不能被收到,CommandButton不知道鼠標(biāo)在哪里,也就不會(huì)發(fā)生按鈕在這時(shí)被按下的情況。當(dāng)然,可以放心,Windows釋放對(duì)鼠標(biāo)的捕捉只是暫時(shí)的,當(dāng)你放開鼠標(biāo)再次發(fā)生移動(dòng)時(shí),Windows又會(huì)捕捉鼠標(biāo)了——它是時(shí)時(shí)都在發(fā)生的。 你可能希望如同我的程序一樣在按鈕邊緣光標(biāo)會(huì)變化,下面是我寫的程序段: Private Sub cmdResize_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) With cmdResize End Sub 作用很明顯,而且很簡(jiǎn)單,所以我就不對(duì)這段代碼作解釋了。 這個(gè)例子很簡(jiǎn)單,但相信起的作用是不小的。SendMessage可以發(fā)送很多消息,當(dāng)然我不會(huì)對(duì)這些消息一一作解釋,但以后還是會(huì)經(jīng)常接觸到的,所以更多的知識(shí)就等慢慢再學(xué)吧。 文中程序在Windows2000+VB6環(huán)境下調(diào)試通過(guò)。 |
|