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