![VB調(diào)用動(dòng)態(tài)鏈接庫(kù)教學(xué)文稿_第1頁(yè)](http://file4.renrendoc.com/view/00d2f1e3bec914f48b955e0ac9d55257/00d2f1e3bec914f48b955e0ac9d552571.gif)
![VB調(diào)用動(dòng)態(tài)鏈接庫(kù)教學(xué)文稿_第2頁(yè)](http://file4.renrendoc.com/view/00d2f1e3bec914f48b955e0ac9d55257/00d2f1e3bec914f48b955e0ac9d552572.gif)
![VB調(diào)用動(dòng)態(tài)鏈接庫(kù)教學(xué)文稿_第3頁(yè)](http://file4.renrendoc.com/view/00d2f1e3bec914f48b955e0ac9d55257/00d2f1e3bec914f48b955e0ac9d552573.gif)
![VB調(diào)用動(dòng)態(tài)鏈接庫(kù)教學(xué)文稿_第4頁(yè)](http://file4.renrendoc.com/view/00d2f1e3bec914f48b955e0ac9d55257/00d2f1e3bec914f48b955e0ac9d552574.gif)
![VB調(diào)用動(dòng)態(tài)鏈接庫(kù)教學(xué)文稿_第5頁(yè)](http://file4.renrendoc.com/view/00d2f1e3bec914f48b955e0ac9d55257/00d2f1e3bec914f48b955e0ac9d552575.gif)
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、Good is good, but better carries it.精益求精,善益求善。VB調(diào)用動(dòng)態(tài)鏈接庫(kù)-VB調(diào)用動(dòng)態(tài)鏈接庫(kù)-Dll編程作為一種簡(jiǎn)單易用的Windows開(kāi)發(fā)環(huán)境,VisualBasic從一推出就受到了廣大編程人員的歡迎。它使程序員不必再直接面對(duì)紛繁復(fù)雜的Windows消息,而可以將精力主要集中在程序功能的實(shí)現(xiàn)上,大大提高了編程效率。但凡事有利必有弊。VB中高度的封裝和模塊化減輕了編程者的負(fù)擔(dān),同時(shí)也使開(kāi)發(fā)人員失去了許多訪問(wèn)低層API函數(shù)和直接與Windows交互的機(jī)會(huì)。因此,相比而言,VB應(yīng)用程序的執(zhí)行效率和功能比C/C+或Delphi生成的程序要差。為了解決這個(gè)問(wèn)題,在
2、一個(gè)大型的VB開(kāi)發(fā)應(yīng)用中,直接調(diào)用WindowsAPI函數(shù)幾乎是不可避免的;同時(shí),還有可能需要程序員自己用C/C+等開(kāi)發(fā)一些動(dòng)態(tài)連接庫(kù),用于在VB中調(diào)用。本文主要討論在32位開(kāi)發(fā)環(huán)境VisualBasic5.0中直接調(diào)用Windows95API函數(shù)或用戶生成的32位動(dòng)態(tài)連接庫(kù)的方法與規(guī)則。Windows動(dòng)態(tài)連接庫(kù)是包含數(shù)據(jù)和函數(shù)的模塊,可以被其它可執(zhí)行文件(EXE、DLL、OCX等)調(diào)用。動(dòng)態(tài)連接庫(kù)包含兩種函數(shù):輸出(exported)函數(shù)和內(nèi)部(internal)函數(shù)。輸出函數(shù)可以被其它模塊調(diào)用,而內(nèi)部函數(shù)則只能在動(dòng)態(tài)連接庫(kù)內(nèi)部使用。盡管動(dòng)態(tài)連接庫(kù)也能輸出數(shù)據(jù),但實(shí)際上它的數(shù)據(jù)通常是只在內(nèi)部
3、使用的。使用動(dòng)態(tài)連接庫(kù)的優(yōu)點(diǎn)是顯而易見(jiàn)的。將應(yīng)用程序的一部分功能提取出來(lái)做成動(dòng)態(tài)連接庫(kù),不但減小了主應(yīng)用程序的大小,提高了程序運(yùn)行效率,還使它更加易于升級(jí)。多個(gè)應(yīng)用程序共享一個(gè)動(dòng)態(tài)連接庫(kù)還能有效地節(jié)省系統(tǒng)資源。正因?yàn)槿绱?,在Windows系統(tǒng)中,動(dòng)態(tài)連接庫(kù)得到了大量的使用。一般來(lái)說(shuō),動(dòng)態(tài)連接庫(kù)都是以DLL為擴(kuò)展名的文件,如Kernel32.dll、commdlg.dll等。但也有例外,如16位Windows的核心部件之一GDI.exe其實(shí)也是一個(gè)動(dòng)態(tài)庫(kù)。編寫(xiě)動(dòng)態(tài)連接庫(kù)的工具很多,如VisualC+、BorlandC+、Delphi等,具體方法可以參見(jiàn)相關(guān)文檔。下面只以VisualC+5.0為例
4、,介紹一下開(kāi)發(fā)應(yīng)用于VisualBasic5.0的動(dòng)態(tài)連接庫(kù)時(shí)應(yīng)注意的問(wèn)題(本文中所有涉及C/C+語(yǔ)言或編譯環(huán)境的地方,都以VC5為例;所有涉及VisualBasic的地方都以VB5為例)。作為一種32位Windows應(yīng)用程序的開(kāi)發(fā)工具,VB5生成的exe文件自然也都是32位的,通常情況下也只能調(diào)用32位的動(dòng)態(tài)連接庫(kù)。但是,并不是所有的32位動(dòng)態(tài)庫(kù)都能被VB生成的exe文件正確地識(shí)別。一般來(lái)說(shuō),自己編寫(xiě)用于VB應(yīng)用程序調(diào)用的動(dòng)態(tài)連接庫(kù)時(shí),應(yīng)注意以下幾個(gè)方面的問(wèn)題:1、生成動(dòng)態(tài)庫(kù)時(shí)要使用_stdcall調(diào)用約定,而不能使用缺省的_cdecl調(diào)用約定;_stdcall約定通常用于32位API函數(shù)的
5、調(diào)用。2、在VC5中的定義文件(.def)中,必須列出輸出函數(shù)的函數(shù)名,以強(qiáng)制VC5系統(tǒng)將輸出函數(shù)的裝飾名(decoratedname)改成普通函數(shù)名;所謂裝飾名是VC的編譯器在編譯過(guò)程中生成的輸出函數(shù)名,它包含了用戶定義的函數(shù)名、函數(shù)參數(shù)及函數(shù)所在的類等多方面的信息。由于在VC5中定義文件不是必需的,因此工程不包含定義文件時(shí)VC5就按自己的約定將用戶定義的輸出函數(shù)名修改成裝飾名后放到輸出函數(shù)列表中,這樣的輸出函數(shù)在VB生成的應(yīng)用程序中是不能正確調(diào)用的(除非聲明時(shí)使用Alias子句)。因此需要增加一個(gè).def文件,其中列出用戶需要的函數(shù)名,以強(qiáng)制VC5不按裝飾名進(jìn)行輸出。3、VC5中的編譯選項(xiàng)
6、結(jié)構(gòu)成員對(duì)齊方式(structurememberalignment)應(yīng)設(shè)成4字節(jié),其原因?qū)⒃诤笪脑敿?xì)介紹。4、由于在C中整型變量是4個(gè)字節(jié),而VB中的整型變量依然只有2個(gè)字節(jié),因此在C中聲明的整型(int)變量在VB中調(diào)用時(shí)要聲明為長(zhǎng)整型(long),而C中的短整型(short)在VB中則要聲明成整型(integer);下表針對(duì)最常用的C語(yǔ)言數(shù)據(jù)類型列出了與之等價(jià)的VisualBasic類型(用于32位版本的Windows)。C語(yǔ)言數(shù)據(jù)類型在VisualBasic中聲明為調(diào)用時(shí)使用的表達(dá)式ATOMByValvariableAsInteger結(jié)果為Integer類型的表達(dá)式BOOLByValva
7、riableAsLong結(jié)果為L(zhǎng)ong類型的表達(dá)式BYTEByValvariableAsByte結(jié)果為Byte類型的表達(dá)式CHARByValvariableAsByte結(jié)果為Byte類型的表達(dá)式COLORREFByValvariableAsLong結(jié)果為L(zhǎng)ong類型的表達(dá)式DWORDByValvariableAsLong結(jié)果為L(zhǎng)ong類型的表達(dá)式HWND,HDC,HMENUByValvariableAsLong結(jié)果為L(zhǎng)ong類型的表達(dá)式等Windows句柄INT,UINTByValvariableAsLong結(jié)果為L(zhǎng)ong類型的表達(dá)式LONGByValvariableAsLong結(jié)果為L(zhǎng)ong
8、類型的表達(dá)式LPARAMByValvariableAsLong結(jié)果為L(zhǎng)ong類型的表達(dá)式LPDWORDvariableAsLong結(jié)果為L(zhǎng)ong類型的表達(dá)式LPINT,LPUINTvariableAsLong結(jié)果為L(zhǎng)ong類型的表達(dá)式LPRECTvariableAstype自定義類型的任意變量LPSTR,LPCSTRByValvariableAsString結(jié)果為String類型的表達(dá)式LPVOIDvariableAsAny任何變量(在傳遞字符串的時(shí)候使用ByVal)LPWORDvariableAsInteger結(jié)果為Integer類型的表達(dá)式LRESULTByValvariableAsLon
9、g結(jié)果為L(zhǎng)ong類型的表達(dá)式NULLAsAny或ByValNothing或ByValvariableAsLongByVal0&或VBNullStringSHORTByValvariableAsInteger結(jié)果為Integer類型的表達(dá)式VOIDSubprocedure不可用WORDByValvariableAsInteger結(jié)果為Integer類型的表達(dá)式WPARAMByValvariableAsLong結(jié)果為L(zhǎng)ong類型的表達(dá)式5、VB中進(jìn)行32位動(dòng)態(tài)庫(kù)的聲明時(shí),函數(shù)名是大小寫(xiě)敏感的。在獲得了需要的動(dòng)態(tài)連接庫(kù)之后,就可以在VB中進(jìn)行調(diào)用了。但是,由于VB不能驗(yàn)證應(yīng)用程序傳遞到動(dòng)態(tài)連接庫(kù)中的
10、參數(shù)值是否正確,因此VB程序中大量的API調(diào)用可能會(huì)降低整個(gè)應(yīng)用程序的穩(wěn)定性,也會(huì)增加以后維護(hù)的難度。所以,決定在VB程序中直接調(diào)用API函數(shù)時(shí)要慎重,但適當(dāng)?shù)氖褂肁PI調(diào)用確實(shí)能夠有效地提高VB程序的性能。這之間的平衡需要編程人員根據(jù)實(shí)際情況來(lái)掌握。下面就具體介紹一下在VB中調(diào)用API函數(shù)時(shí)需要做的工作。要聲明一個(gè)DLL過(guò)程,首先需要在代碼窗口的通用(General)部分增加一個(gè)Declare語(yǔ)句。如果該過(guò)程返回一個(gè)值,應(yīng)將其聲明為Function:DeclareFunctionpublicnameLiblibnameAliasalias(ByValvariableAstype,ByValv
11、ariableAstype.)AsType如果過(guò)程沒(méi)有返回值,可將其聲明為Sub:DeclareSubpublicnameLiblibnameAliasalias(ByValvariableAstype,ByValvariableAstype.)缺省情況下,在標(biāo)準(zhǔn)模塊中聲明的DLL過(guò)程,可以在應(yīng)用程序的任何地方調(diào)用它。在其它類型的模塊中定義的DLL過(guò)程則是模塊私有的,必須在它們前面聲明Private關(guān)鍵字,以示區(qū)分。下面分別介紹聲明語(yǔ)句的各個(gè)組成部分。(一)、指定動(dòng)態(tài)庫(kù):Declare語(yǔ)句中的Lib子句用來(lái)告訴VisualBasic如何找到包含過(guò)程的.dll文件。如果引用的過(guò)程屬于Window
12、s核心庫(kù)(User32、Kernel32或GDI32),則可以不包含文件擴(kuò)展名,如:DeclareFunctionGetTickCountLibkernel32AliasGetTickCount()AsLong對(duì)于其它動(dòng)態(tài)連接庫(kù),可以在Lib子句指定文件的路徑:DeclareFunctionlzCopyLibc:windowslzexpand.dll_(ByValSAsInteger,ByValDAsInteger)AsLong如果未指定libname的路徑,VisualBasic將按照下列順序查找該文件:.exe文件所在的目錄當(dāng)前目錄Windows系統(tǒng)目錄Windows目錄Path環(huán)境變量中
13、的目錄下表中列出了常用的操作系統(tǒng)環(huán)境庫(kù)文件。動(dòng)態(tài)鏈接庫(kù)描述Advapi32.dll高級(jí)API服務(wù),支持大量的API(其中包括許多安全與注冊(cè)方面的調(diào)用)Comdlg32.dll通用對(duì)話框API庫(kù)Gdi32.dll圖形設(shè)備接口API庫(kù)Kernel32.dllWindows32位核心的API支持Lz32.dll32位壓縮例程Mpr.dll多接口路由器庫(kù)Netapi32.dll32位網(wǎng)絡(luò)API庫(kù)Shell32.dll32位ShellAPI庫(kù)User32.dll用戶接口例程庫(kù)Version.dll版本庫(kù)Winmm.dllWindows多媒體庫(kù)Winspool.drv后臺(tái)打印接口,包含后臺(tái)打印API調(diào)用。
14、對(duì)于Windows的系統(tǒng)API函數(shù),可以利用VB提供的工具APIViewer查找某一函數(shù)及其相關(guān)數(shù)據(jù)結(jié)構(gòu)和常數(shù)的聲明,并復(fù)制到自己的程序中。(二)、使用別名:Declare語(yǔ)句中的Alias子句是一個(gè)可選的部分,用戶可以通過(guò)它所標(biāo)識(shí)的別名對(duì)動(dòng)態(tài)庫(kù)中的函數(shù)進(jìn)行引用。例如,在下面的語(yǔ)句中,聲明了一個(gè)在VB中名為MyFunction的函數(shù),而它在動(dòng)態(tài)庫(kù)Mydll.dll中最初的名字是MyFunctionX。PrivateDeclareFunctionMyFunctionLibMydll.dll_AliasMyFunctionX()AsLong需要注意的是,Alias子句中的函數(shù)名是大小寫(xiě)敏感的,也就
15、是說(shuō),必須與函數(shù)在生成時(shí)的聲明(如在C源文件中的聲明)一致。這是因?yàn)?2位動(dòng)態(tài)庫(kù)與16位動(dòng)態(tài)庫(kù)不同,其中的函數(shù)名是區(qū)分大小寫(xiě)的。同樣道理,如果沒(méi)有使用Alias子句,那么在Function(或Sub)后的函數(shù)名也是區(qū)分大小寫(xiě)的。通常在以下幾種情況時(shí)需要使用Alias子句:A.處理使用字符串的系統(tǒng)WindowsAPI過(guò)程如果調(diào)用的系統(tǒng)WindowsAPI過(guò)程要使用字符串,那么聲明語(yǔ)句中必須增加一個(gè)Alias子句,以指定正確的字符集。包含字符串的系統(tǒng)WindowsAPI函數(shù)實(shí)際有兩種格式:ANSI和Unicode(關(guān)于ANSI和Unicode兩種字符集的區(qū)別將在后面詳細(xì)闡述)。因此,在Window
16、s頭文件中,每個(gè)包含字符串的函數(shù)都同時(shí)有ANSI版本和Unicode版本。例如,下面是SetWindowText函數(shù)的兩種C語(yǔ)言描述??梢钥吹剑谝粋€(gè)描述將函數(shù)定義為SetWindowTextA,尾部的A表明它是一個(gè)ANSI函數(shù):WINUSERAPIBOOLWINAPISetWindowTextA(HWNDhWnd,LPCSTRlpString);第二個(gè)描述將它定義為SetWindowTextW,尾部的W表明它是一個(gè)Unicode函數(shù):WINUSERAPIBOOLWINAPISetWindowTextW(HWNDhWnd,LPCWSTRlpString);因?yàn)閮蓚€(gè)函數(shù)實(shí)際的名稱都不是SetWi
17、ndowText,要引用正確的函數(shù)就必須增加一個(gè)Alias子句:PrivateDeclareFunctionSetWindowTextLibuser32_AliasSetWindowTextA(ByValhwndAsLong,ByVal_lpStringAsString)AsLong應(yīng)當(dāng)注意,對(duì)于VB中使用的系統(tǒng)WindowsAPI函數(shù),應(yīng)該指定函數(shù)的ANSI版本,因?yàn)橹挥蠾indowsNT才支持Unicode版本,而Windows95不支持這個(gè)版本。僅當(dāng)應(yīng)用程序只運(yùn)行在WindowsNT平臺(tái)上的時(shí)候才可以使用Unicode版本。B.函數(shù)名是不標(biāo)準(zhǔn)的名稱有時(shí),個(gè)別的DLL過(guò)程的名稱不是有效的標(biāo)
18、識(shí)符。例如,它可能包含了非法的字符(如連字符),或者名稱是VB的關(guān)鍵字(如GetObject)。在這種情況下,可以使用Alias關(guān)鍵字。例如,操作環(huán)境DLLs中的某些過(guò)程名以下劃線開(kāi)始。盡管在VB標(biāo)識(shí)符中允許使用標(biāo)識(shí)符,但是下劃線不能作為標(biāo)識(shí)符的第一個(gè)字符。為了使用這種過(guò)程,必須先聲明一個(gè)名稱合法的過(guò)程,然后用Alias子句引用過(guò)程的真實(shí)名稱:DeclareFunctionlopenLibkernel32Alias_lopen_(ByVallpPathNameAsString,ByValiReadWrite_AsLong)AsLong在上例中,lopen是VB中使用的過(guò)程名稱。而_lopen則
19、是動(dòng)態(tài)連接庫(kù)中可以識(shí)別的名稱。C.使用序號(hào)標(biāo)識(shí)DLL過(guò)程除了使用名稱之外,還可以使用序號(hào)來(lái)標(biāo)識(shí)DLL過(guò)程。某些動(dòng)態(tài)連接庫(kù)中不包含過(guò)程的名稱,在聲明它們包含的過(guò)程時(shí)必須使用序號(hào)。同使用名稱標(biāo)識(shí)的DLL過(guò)程相比,如果使用序號(hào),在最終的應(yīng)用程序中消耗的內(nèi)存將比較少,而且速度會(huì)快些。但是,一個(gè)具體的API的序號(hào)在不同的操作系統(tǒng)中可能是不同的。例如GetWindowsDirectory在Win95下的序號(hào)為432,而在WindowsNT4.0下為338??偠灾绻M麘?yīng)用程序能夠在不同的操作系統(tǒng)下運(yùn)行,那么最好不要使用序號(hào)來(lái)標(biāo)識(shí)API過(guò)程。如果過(guò)程不屬于API,或者應(yīng)用程序使用的范圍很有限,那么使用
20、序號(hào)還是有好處的。要使用序號(hào)來(lái)聲明DLL過(guò)程,Alias子句中的字符串需要包含過(guò)程的序號(hào),并在序號(hào)的前面加一個(gè)數(shù)字標(biāo)記字符(#)。例如,Windowskernel中的GetWindowsDirectory函數(shù)的序號(hào)為432;可以用下面的語(yǔ)句來(lái)聲明該DLL過(guò)程:DeclareFunctionGetWindowsDirectoryLibkernel32_Alias#432(ByVallpBufferAsString,_ByValnSizeAsLong)AsLong在這里,可以使用任意的合法名稱作為過(guò)程的名稱,VB將用序號(hào)在DLL中尋找過(guò)程。為了得到要聲明的過(guò)程的序號(hào),可以使用Dumpbin.exe
21、等實(shí)用工具(Dumpbin.exe是MicrosoftVisualC+提供的一個(gè)實(shí)用工具,它的使用說(shuō)明可以參見(jiàn)VC的文檔)。利用Dumpbin,可以提取出.dll文件中的各種信息,例如DLL中的函數(shù)列表,它們的序號(hào)以及與代碼有關(guān)的其它信息。(三)、使用值或引用傳遞在缺省的情況下,VB以引用方式傳遞所有參數(shù)(ByRef)。這意味著并沒(méi)有傳遞實(shí)際的參數(shù)值,VB只傳遞了數(shù)據(jù)的32位地址。另外有許多DLL過(guò)程要求參數(shù)以值方式傳遞(ByVal)。這意味著它們需要實(shí)際的數(shù)據(jù),而不是數(shù)據(jù)的內(nèi)存地址。如果過(guò)程需要一個(gè)傳值參數(shù),而傳遞給它的參數(shù)是一個(gè)指針,那么由于得到了錯(cuò)誤的數(shù)據(jù),該過(guò)程將不能正確地工作。要使參
22、數(shù)以使用值方式傳遞,在Declare語(yǔ)句中需要在參數(shù)聲明的前面加上ByVal關(guān)鍵字。例如InvertRect過(guò)程要求第一個(gè)參數(shù)用傳值方式傳遞,而第二個(gè)用引用方式傳遞:DeclareFunctionInvertRectLibuser32Alias_InvertRectA(ByValhdcAsLong,lpRectAsRECT)AsLong動(dòng)態(tài)連接庫(kù)的參數(shù)傳遞是一個(gè)復(fù)雜的問(wèn)題,也是VB中調(diào)用動(dòng)態(tài)連接庫(kù)時(shí)最容易出現(xiàn)錯(cuò)誤的地方。參數(shù)類型或傳遞方式的聲明錯(cuò)誤都可能導(dǎo)致應(yīng)用程序出現(xiàn)GPF(通用保護(hù)錯(cuò)誤),甚至使操作系統(tǒng)崩潰,因此我們將在后面專門詳細(xì)地討論這個(gè)問(wèn)題。(四)、靈活的參數(shù)類型某些DLL過(guò)程的同一
23、個(gè)參數(shù)能夠接受多種數(shù)據(jù)類型。如果需要傳遞多種類型的數(shù)據(jù),可以將參數(shù)聲明為AsAny,從而取消類型限制。例如,下面的聲明中的第三個(gè)參數(shù)(lpptAsAny)既可以傳遞一個(gè)POINT結(jié)構(gòu)的數(shù)組,也可以傳遞一個(gè)RECT結(jié)構(gòu):DeclareFunctionMapWindowPointsLibuser32Alias_MapWindowPoints(ByValhwndFromAsLong,_ByValhwndToAsLong,lpptAsAny,_ByValcPointsAsLong)AsLongAsAny子句提供了一定的靈活性,但是,由于它不進(jìn)行任何的類型檢查,風(fēng)險(xiǎn)也隨之增加。因此在使用AsAny子句時(shí)
24、,必須仔細(xì)檢查所有參數(shù)的類型。正確的函數(shù)聲明是在VB中調(diào)用動(dòng)態(tài)連接庫(kù)的前提,但要想在VB中用對(duì)、用好動(dòng)態(tài)庫(kù)中的函數(shù),僅僅有聲明還是遠(yuǎn)遠(yuǎn)不夠的。前面已經(jīng)說(shuō)過(guò),由于VB不能驗(yàn)證應(yīng)用程序傳遞到動(dòng)態(tài)連接庫(kù)中的參數(shù)值是否正確,因此就要求程序員應(yīng)對(duì)參數(shù)類型有非常詳細(xì)的了解,否則很容易引起應(yīng)用程序發(fā)生通用保護(hù)錯(cuò)或?qū)е聺撛诘腂ug,降低軟件的可靠性。下面將參數(shù)類型分為簡(jiǎn)單數(shù)據(jù)類型、字符串、和用戶自定義類型三種分別進(jìn)行討論。(1)、簡(jiǎn)單數(shù)據(jù)類型:簡(jiǎn)單數(shù)據(jù)類型是指Numeric數(shù)據(jù)類型(包括Integer、Long、Single、Double、Currency類型)、Byte數(shù)據(jù)類型和Boolean數(shù)據(jù)類型。它們
25、的共同的特點(diǎn)是結(jié)構(gòu)簡(jiǎn)單,操作系統(tǒng)在處理時(shí)不必進(jìn)行特殊的轉(zhuǎn)換。簡(jiǎn)單數(shù)據(jù)類型參數(shù)的傳遞比較簡(jiǎn)單。我們知道,在VB中傳遞參數(shù)的方式有兩種:傳值(Byval)和傳址(ByRef),缺省的方式是傳址。所謂傳值,就是對(duì)一個(gè)變量的具體值進(jìn)行傳遞;而傳址則是傳遞變量的地址。例如,在VB程序中需要將一個(gè)整型變量m=10的值傳進(jìn)動(dòng)態(tài)庫(kù),如果用傳值方式,那么傳進(jìn)動(dòng)態(tài)庫(kù)的值就是10,而在傳址方式下,傳入的則是變量m的地址,相當(dāng)于C/C+中&m的值。需要注意的是,以傳值方式傳進(jìn)動(dòng)態(tài)連接庫(kù)的變量,其值在動(dòng)態(tài)庫(kù)中是不能被改變的;如果需要在動(dòng)態(tài)連接庫(kù)中修改傳入?yún)?shù)的值,則必須使用傳址方式。一般來(lái)說(shuō),在VB和動(dòng)態(tài)連接庫(kù)之間傳遞
26、單個(gè)的簡(jiǎn)單數(shù)據(jù)類型,只要注意了以上幾個(gè)方面就可以了。當(dāng)需要將一個(gè)簡(jiǎn)單數(shù)據(jù)類型的整個(gè)數(shù)組傳進(jìn)動(dòng)態(tài)庫(kù)時(shí),必須將相應(yīng)參數(shù)聲明為傳址方式,然后把數(shù)組的第一個(gè)元素作為參數(shù)傳入,這樣在動(dòng)態(tài)連接庫(kù)中就得到了數(shù)組的首地址,從而可以對(duì)整個(gè)數(shù)組進(jìn)行訪問(wèn)。例如,聲明了一個(gè)名為ReadArray的DLL過(guò)程,要求傳入一個(gè)整型數(shù)組aArray:DeclareFunctionReadArrayLibmydll.dll_(aArrayAsInteger)AsInteger在調(diào)用時(shí)可以采用如下方式:Dimret,I(5)asIntegerret=ReadArray(I(0)注釋:將整個(gè)數(shù)組傳入動(dòng)態(tài)連接庫(kù)(2)、字符串參數(shù)的傳
27、遞:與簡(jiǎn)單數(shù)據(jù)類型相比,字符串類型(String、String*n)的參數(shù)傳遞要復(fù)雜得多,這主要是Windows98API和VB使用的字符串類型不同的緣故。VB使用被稱為BSTR的String數(shù)據(jù)類型,它是由自動(dòng)化(以前被稱為OLEAutomation)定義的數(shù)據(jù)類型。一個(gè)BSTR由頭部和字符串組成,頭部包含了字符串的長(zhǎng)度信息,字符串中可以包含嵌入的null值。大部分的BSTR是Unicode的,即每個(gè)字符需要兩個(gè)字節(jié)。BSTR通常以兩字節(jié)的兩個(gè)null字符結(jié)束。下圖表示了一個(gè)BSTR類型的字符串。FunctionGetCharByte(ByValOneCharAsInteger,ByValI
28、sHighByteAsBoolean)AsByte注釋:該函數(shù)獲得一個(gè)字符的高字節(jié)或低字節(jié)IfIsHighByteThenIfOneChar=0ThenGetCharByte=CByte(OneChar256)注釋:右移8位,得到高字節(jié)ElseGetCharByte=CByte(OneCharAnd&H7FFF)256)Or&H80EndIfExitFunctionElseGetCharByte=CByte(OneCharAnd&HFF)注釋:屏蔽掉高字節(jié),得到低字節(jié)ExitFunctionEndIfEndFunctionSubStrToByte(StrToChangeAsString,Byt
29、eArray()AsByte)注釋:該函數(shù)將一個(gè)字符串轉(zhuǎn)換成字節(jié)數(shù)組DimLowBound,UpBoundAsIntegerDimi,count,lengthAsIntegerDimOneCharAsIntegercount=0length=Len(StrToChange)LowBound=LBound(ByteArray)UpBound=UBound(ByteArray)Fori=LowBoundToUpBoundByteArray(i)=0注釋:初始化字節(jié)數(shù)組NextFori=LowBoundToUpBoundcount=count+1Ifcount255)Or(OneChar0)Then
30、注釋:該字符是非ASCII字符ByteArray(i)=GetCharByte(OneChar,True)注釋:得到高字節(jié)i=i+1Ifi=0ThenGetCharByte=CByte(OneChar256)注釋:右移8位,得到高字節(jié)ElseGetCharByte=CByte(OneCharAnd&H7FFF)256)Or&H80EndIfExitFunctionElseGetCharByte=CByte(OneCharAnd&HFF)注釋:屏蔽掉高字節(jié),得到低字節(jié)ExitFunctionEndIfEndFunctionSubStrToByte(StrToChangeAsString,Byte
31、Array()AsByte)注釋:該函數(shù)將一個(gè)字符串轉(zhuǎn)換成字節(jié)數(shù)組DimLowBound,UpBoundAsIntegerDimi,count,lengthAsIntegerDimOneCharAsIntegercount=0length=Len(StrToChange)LowBound=LBound(ByteArray)UpBound=UBound(ByteArray)Fori=LowBoundToUpBoundByteArray(i)=0注釋:初始化字節(jié)數(shù)組NextFori=LowBoundToUpBoundcount=count+1Ifcount255)Or(OneChar0)Then注
32、釋:該字符是非ASCII字符ByteArray(i)=GetCharByte(OneChar,True)注釋:得到高字節(jié)i=i+1Ifi=UpBoundThenByteArray(i)=GetCharByte(OneChar,False)注釋:得到低字節(jié)Else注釋:該字符是ASCII字符ByteArray(i)=OneCharEndIfElseExitForEndIfNextEndSubSubChangeStrAryToByte(StrAry()AsString,ByteAry()AsByte)注釋:將字符串?dāng)?shù)組轉(zhuǎn)換成字節(jié)數(shù)組DimLowBound,UpBoundAsIntegerDimi,
33、count,StartPos,MaxLenAsIntegerDimTmpByte()AsByteLowBound=LBound(StrAry)UpBound=UBound(StrAry)count=0ReDimByteAry(0)Fori=LowBoundToUpBoundMaxLen=LenB(StrAry(i)ReDimTmpByte(MaxLen+1)ReDimPreserveByteAry(count+MaxLen+1)CallStrToByte(StrAry(i),TmpByte)注釋:轉(zhuǎn)換一個(gè)字符串StartPos=countDoByteAry(count)=TmpByte(cou
34、nt-StartPos)count=count+1IfByteAry(count-1)=0ThenExitDoLoop注釋:將每一個(gè)字符串對(duì)應(yīng)的字節(jié)數(shù)組按順序填入結(jié)果數(shù)組中ReDimPreserveByteAry(count-1)NextiEndSub下面看一個(gè)轉(zhuǎn)換的例子:DimResultAry()asByteDimSomeStr(2)asStringSomeStr(0)=測(cè)試1SomeStr(1)=測(cè)試222SomeStr(2)=測(cè)試33CallChangeStrAryToByte(SomeStr,ResultAry)注釋:轉(zhuǎn)換字符串?dāng)?shù)組當(dāng)轉(zhuǎn)換完成以后,查看字節(jié)數(shù)組ResultAry,其中
35、包含了21個(gè)元素,依次是:178,226,202,212,49,0,178,226,202,212,50,50,50,0,178,226,202,212,51,51,0。其中,178,226是測(cè)的字節(jié)碼,202,112是試的字節(jié)碼,49,50,51分別為字符1、2、3的ASCII碼。可見(jiàn),經(jīng)過(guò)轉(zhuǎn)換后,字符串?dāng)?shù)組中的各個(gè)元素按順序放在了字節(jié)數(shù)組中,相互間以終止符0分隔。這樣,字符串?dāng)?shù)組就全部轉(zhuǎn)換成了字節(jié)數(shù)組,然后只要將字節(jié)數(shù)組的第一個(gè)元素以傳址的方式傳入動(dòng)態(tài)連接庫(kù),DLL過(guò)程就可以正確地訪問(wèn)數(shù)組中的所有字符串了。但是,使用這種方法,當(dāng)DLL過(guò)程處理結(jié)束返回VB時(shí),VB得到的仍然是字節(jié)數(shù)組。如果需
36、要在VB中再次得到該字節(jié)數(shù)組表示的字符串,還要把整個(gè)字節(jié)數(shù)組重新以0為分割符分成多個(gè)子數(shù)組(每個(gè)子數(shù)組都對(duì)應(yīng)原來(lái)字符串?dāng)?shù)組中的一個(gè)元素),然后使用VB函數(shù)StrConv將每個(gè)子數(shù)組轉(zhuǎn)換成字符串(轉(zhuǎn)換時(shí)第二個(gè)參數(shù)選vbUnicode),就可以顯示或進(jìn)行其它操作了。例如,其中一個(gè)子數(shù)組的名字是SubAry,則函數(shù)StrConv(SubAry,vbUnicode)就返回了它所對(duì)應(yīng)的字符串??傊?,VB應(yīng)用程序和動(dòng)態(tài)庫(kù)間字符串參數(shù)的傳遞是一個(gè)比較復(fù)雜的過(guò)程,使用時(shí)要非常謹(jǐn)慎。同時(shí)應(yīng)盡可能避免傳遞字符串?dāng)?shù)組類型的參數(shù),因?yàn)檫@很容易引起下標(biāo)越界、堆棧溢出等嚴(yán)重錯(cuò)誤。(3)、用戶自定義類型(User-defi
37、nedType)參數(shù)的傳遞用戶自定義類型在VB中是一種重要的數(shù)據(jù)類型,它為編程者提供了很大的靈活性,使開(kāi)發(fā)人員可以根據(jù)需要構(gòu)造自己的數(shù)據(jù)結(jié)構(gòu)。它相當(dāng)于C/C+中的結(jié)構(gòu)類型(structure)。在VB中,允許程序員以傳址的方式將自定義數(shù)據(jù)類型參數(shù)傳入動(dòng)態(tài)庫(kù),DLL過(guò)程也可以將修改后的參數(shù)返回VB程序。但是,在VB中仍然不支持以傳值的方式傳遞用戶自定義類型參數(shù)。傳遞用戶自定義類型參數(shù)時(shí),必須確保VB中的數(shù)據(jù)類型的成員與動(dòng)態(tài)庫(kù)中的結(jié)構(gòu)成員是一一對(duì)應(yīng)的,所占空間也必須嚴(yán)格一致。這里所說(shuō)的一一對(duì)應(yīng),不僅是指VB中的所有結(jié)構(gòu)成員在動(dòng)態(tài)庫(kù)的結(jié)構(gòu)中都必須有對(duì)應(yīng)的元素,而且它們?cè)跀?shù)據(jù)結(jié)構(gòu)中定義的順序也必須嚴(yán)格一致,這是VB中使用的數(shù)據(jù)結(jié)構(gòu)成員對(duì)齊方式?jīng)Q定的
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- SMARCA2-ligand-13-生命科學(xué)試劑-MCE-7252
- Nonanoylcarnitine-C9-carnitine-生命科學(xué)試劑-MCE-3656
- CP-LC-1254-生命科學(xué)試劑-MCE-4991
- 3-Hydroxy-desalkylflurazepam-生命科學(xué)試劑-MCE-8942
- 二零二五年度瓷磚產(chǎn)品出口退稅代理服務(wù)合同
- 二零二五年度泳池水上運(yùn)動(dòng)項(xiàng)目推廣合作合同
- 二零二五年度環(huán)境污染責(zé)任賠償調(diào)解協(xié)議
- 質(zhì)量控制在提高實(shí)驗(yàn)室效率中的作用
- DB3702T 46.1-2024地理標(biāo)志產(chǎn)品 平度大花生 第1部分:生產(chǎn)技術(shù)規(guī)程
- 2024年湖南省公務(wù)員錄用考試《行測(cè)》真題及答案解析
- 心尖球形綜合征
- DBJT 13-460-2024 既有多層住宅建筑增設(shè)電梯工程技術(shù)標(biāo)準(zhǔn)
- 中國(guó)證監(jiān)會(huì)證券市場(chǎng)交易結(jié)算資金監(jiān)控系統(tǒng)證券公司接口規(guī)范
- 2025屆天津市部分學(xué)校高三年級(jí)八校聯(lián)考英語(yǔ)試題含解析
- 微項(xiàng)目 探討如何利用工業(yè)廢氣中的二氧化碳合成甲醇-2025年高考化學(xué)選擇性必修第一冊(cè)(魯科版)
- 廣東省廣州市黃埔區(qū)2024-2025學(xué)年八年級(jí)物理上學(xué)期教學(xué)質(zhì)量監(jiān)測(cè)試題
- 水產(chǎn)品冷凍加工原料處理與加工技術(shù)考核試卷
- 全新保密協(xié)議模板公安下載(2024版)
- 財(cái)務(wù)管理學(xué)(第10版)課件 第1章 總論
- GB/T 4008-2024錳硅合金
評(píng)論
0/150
提交評(píng)論