API說到底就是一系列的底層函數(shù),是系統(tǒng)提供給 用戶用于進(jìn)入操作系統(tǒng)核心,進(jìn)行高級(jí)編程的途徑。通過在Visual Basic應(yīng)用程序中聲明外部過程就能夠 訪問Windows API(以及其它的外部DLLs)。在聲明了過程之后,調(diào)用它的方法與調(diào)用Visual Basic自己的過程相同。
Visual Basic (VB)作為一種高效編程環(huán)境,它封裝了部分Windows API函數(shù),但也犧牲了一些API的功能。調(diào)用API時(shí)稍有不慎就可能導(dǎo)致API編程錯(cuò)誤,出現(xiàn)難于捕獲或間歇性錯(cuò)誤,甚至出現(xiàn)程序崩潰。要減少API編程錯(cuò)誤,提高VB調(diào)用API時(shí)的安全性,應(yīng)重點(diǎn)注意下列八個(gè)問題:
(1)指定“Option Explicit”
編程前最好將VB編程環(huán)境中的“Require Variable Declaration(要求變量申明)項(xiàng)選中。如果該項(xiàng)未被指定,任何簡(jiǎn)單的錄入錯(cuò)誤都可能會(huì)產(chǎn)生一個(gè)“Variant”變量,在調(diào)用API時(shí),VB對(duì)該變量進(jìn)行強(qiáng)制轉(zhuǎn)換以避免沖突,這樣一來,VB就會(huì)為字符串、長(zhǎng)整數(shù)、整數(shù)、浮點(diǎn)數(shù)等各種類型傳遞NULL值,導(dǎo)致程序無法正常運(yùn)行。
(2)注意VB整數(shù)和Win32整數(shù)的區(qū)別
在VB環(huán)境下,涉及到的所有integer(整型數(shù)),都是16位,而一旦涉及C/C++Win32文檔時(shí),則是32位,閱讀與Windows API函數(shù)或與32位動(dòng)態(tài)鏈接庫有關(guān)的資料或應(yīng)用程序時(shí),尤其要注意分析理解環(huán)境背景,以利于分清數(shù)據(jù)類型和數(shù)據(jù)結(jié)構(gòu),正確地聲明API函數(shù)。
(3)減少和避免使用As Any
雖然用As Any的方法聲明庫,可使Windows API函數(shù)能接受多種類型的參數(shù),但更嚴(yán)重的是,即使是一個(gè)很小的錯(cuò)誤,比如遺漏類型標(biāo)識(shí)符或錯(cuò)誤地使用了ByVal關(guān)鍵字,都可能導(dǎo)致系統(tǒng)崩潰或很難發(fā)現(xiàn)的其他數(shù)據(jù)錯(cuò)誤。
(4)注意檢查參數(shù)類型
API錯(cuò)誤中,除了因遺漏ByVal關(guān)鍵字導(dǎo)致的錯(cuò)誤外,大約有50%是因?yàn)槁暶髦杏胁徽_的參數(shù)類型。在Win32環(huán)境下,無論是8位、16位,還是32位數(shù)值變量都是以32位傳遞,如果同時(shí)使用,則很難發(fā)現(xiàn)其中錯(cuò)誤。如果聲明的參數(shù)類型不同,被VB視為Variant傳遞給API函數(shù),會(huì)出現(xiàn)“錯(cuò)誤的DLL調(diào)用規(guī)范”的消息。
(5)勿忘ByVal,確保函數(shù)聲明的完整性
ByVal是“按值”調(diào)用,參數(shù)傳遞時(shí),不將指向DLL的指針傳遞給參數(shù)變量本身,而是將傳遞參數(shù)值的一份拷貝傳遞給DLL。比如傳遞字符串參數(shù)時(shí),VB與DLL之間的接口支持兩種類型的字符串,如未使用ByVal關(guān)鍵字,VB將指向DLL的函數(shù)指針傳遞給一個(gè)OLE2.0字符串(即BSTR數(shù)據(jù)類型),而Windows API函數(shù)往往不支持這種數(shù)據(jù)類型,導(dǎo)致錯(cuò)誤。而使用ByVal關(guān)鍵字后VB將字符串轉(zhuǎn)變換成C語言格式的“空終止”串,被API正確使用。
(6)重新檢查函數(shù)名
在Win16環(huán)境下,API函數(shù)的名字不要求區(qū)分大小寫,而在Win32環(huán)境下,則有此要求。在一個(gè)DLL函數(shù)里找不到聲明的函數(shù)時(shí),有必要檢查一下函數(shù)名,對(duì)于管理字符串的函數(shù),是否遺漏了A和W前綴。
(7)預(yù)先初始化字符串,以免造成沖突
如果API函數(shù)要求一個(gè)指向緩沖區(qū)的指針,以便從中載入數(shù)據(jù),而此時(shí)傳遞的是字符串變量,應(yīng)該先初始化字符串長(zhǎng)度。因?yàn)锳PI無法知道字符串的長(zhǎng)度——API默認(rèn)已為其分配有足夠的長(zhǎng)度。沒有初始化字符串,分配給字符串的緩沖區(qū)有可能會(huì)不足,API函數(shù)將有可能在緩沖區(qū)末尾反復(fù)改寫,內(nèi)存里字符串后面的內(nèi)容將會(huì)改寫得一塌糊涂。程序表現(xiàn)為突然終止或間歇性錯(cuò)誤。
(8)跟蹤檢查參數(shù)、返回類型和返回值
VB具有立即模式和單步調(diào)試功能,利用這個(gè)優(yōu)勢(shì),確保函數(shù)聲明的類型明確(API不返回Variant類型),通過跟蹤和檢查參數(shù)的來源及類型,可以排除參數(shù)的錯(cuò)誤傳遞。許多API函數(shù)都有返回結(jié)果,指出自己是否執(zhí)行成功。你若要對(duì)返回結(jié)果進(jìn)行測(cè)試,用VB的Err對(duì)象的LastDllError方法可查閱這些信息,對(duì)錯(cuò)誤可針對(duì)API函數(shù)調(diào)用,取回API函數(shù)GetlastError的結(jié)果,以修改聲明,達(dá)到正確調(diào)用API函數(shù)之目的。