VB的API編程精粹(1)
發(fā)布時(shí)間:2008-08-06 閱讀數(shù): 次 來(lái)源:網(wǎng)樂原科技
Visual Basic以友好易學(xué)的可視化開發(fā)環(huán)境聞名于 世,成為人們學(xué)習(xí)計(jì)算機(jī)編程的首選語(yǔ)言。目前,全世界 大概有300多萬(wàn)人使用著Visual Basic語(yǔ)言。如果您想在 這茫茫眾生中出類拔萃,那么您就不得不學(xué)習(xí)API (Application Program lnterface,即Windows的應(yīng)用程 序編程接口)編程。不懂API,那可成不了高手。
第一節(jié):API基礎(chǔ)
API說(shuō)到底就是一系列的底層函數(shù),是系統(tǒng)提供給 用戶用于進(jìn)入操作系統(tǒng)核心,進(jìn)行高級(jí)編程的途徑。通 過在Visual Basic應(yīng)用程序中聲明外部過程就能夠 訪問Windows API(以及其它的外部DLLs)。在聲明 了過程之后,調(diào)用它的方法與調(diào)用Visual Basic自 己的過程相同。要聲明一個(gè)DLL過程,需要在代碼窗 口的"聲明"部分增加一個(gè)Declare語(yǔ)句,如果該過 程返回一個(gè)值,應(yīng)將其聲明為Function。例如:
Declare Function publicname Lib "libname" [Alias "alias"] [([[ByVal] variable [As type] [,[ByVal] variable [As type]]...])] As Type
如果過程沒有返回值,可將其聲明為Sub。
缺省情況下,在標(biāo)準(zhǔn)模塊中聲明的DLL過程,可 以在應(yīng)用程序的任何地方調(diào)用它。在其他類型的模塊 中定義的DLL過程是模塊私有的,必須在它們前面 加上Private關(guān)鍵字,以示區(qū)分。特別提請(qǐng)注意的 是,在32位的Visual Basic中過程名是區(qū)分大小 寫的。而在以前的16位版本中并不區(qū)分大小寫,這 是初學(xué)者容易出錯(cuò)的地方。
Declare語(yǔ)句中的Lib子句用來(lái)告訴Visual Basic如何找到包含該過程的dll文件。如果引用的過 程屬于Windows核心庫(kù)(User32、Kernel32或 GDI32),則可以不包含文件擴(kuò)展名。例如:
Declare Function GetTickCount Lib "kernel32" Alias "GetTickCount"() As Long。對(duì)于其它DLL, Lib子句須指定文件的路徑及擴(kuò)展名。
如果調(diào)用的Windows API過程要使用字符串,那 么在聲明語(yǔ)句中必須增加一個(gè)Alias子句,以指定 正確的字符集。包含字符串的Windows API函數(shù)實(shí) 際有兩種格武ANSI格式Unicode格式。因此,在 Windows頭文件中,每個(gè)包含字符串的函數(shù)都同時(shí)有 ANSI版本和Unicode版本。
例如,下面是SetWindowText函數(shù)的兩種C語(yǔ)言描 述??梢钥吹?,第一個(gè)描述將函數(shù)定義為SetWindowTextA, 尾部的"A"表明它是一個(gè)ANSI函數(shù):
SetWindowTextA(HWND hWnd,LPCSTR lpString);
第二個(gè)描述將它定義為SetWindowTextW,尾部的 "w"表明它是一個(gè)Unicode函數(shù):
SetWindowTextW(HWND Hwnd,LPCWSTR lpString);
因?yàn)閮蓚€(gè)函數(shù)實(shí)際的名稱都不是"SetWindow Text",要引用正確的函數(shù)就必須增加一個(gè)Alias子句:
Private Declare Function SetwindowText Lib "user32" Alias "SetWindowTextA"(ByVal hwnd As Longg,ByVal lpString As String) As Long
請(qǐng)注意, Alias子句后面的字符串必須是過程的 真正名稱,必須是區(qū)分大小寫的。事實(shí)上,您只需要 記住,只有Windows NT才支持Unicode格式,而 Windows 95只支持ANSI格式就行了。至于兩者的區(qū) 別,作一般的應(yīng)用程序開發(fā)是不需要了解的。
VB5專業(yè)版在VB目錄的\Winapi子目錄下,用幾 個(gè)文件提供了關(guān)于API的信息。 Win32api.txt文件中 包含了32位Windows API函數(shù)中用到的函數(shù)和類型的 結(jié)構(gòu)聲明以及全局常量的值。用戶可以用VB本身帶的外 接程序"API瀏覽器"來(lái)方便地使用Win32api.Txt,如下 所示:
點(diǎn)擊菜單文件項(xiàng)的"加載文本文件…"從VB目 錄下的WINAPI目錄中選擇"WIN32API.TXT",就可以 查看WINDOWS 95系統(tǒng)的API函數(shù)的聲明、常數(shù)定義和 數(shù)據(jù)類型了。例如,我們打算查看函數(shù)InverRect() 的聲明。首先,點(diǎn)擊"搜索"按鈕,輸入字符串 "InverRect"。在"可選項(xiàng)"欄中,蘭色的亮度條將移 動(dòng)到"InverRect"項(xiàng)上。再點(diǎn)按"添加"按鈕,在"選 定項(xiàng)"中就出現(xiàn)"InverRect"在Visual Basic中的 聲明了。接下來(lái)自然是點(diǎn)按"復(fù)制"按鈕,然后將窗 口切換到Visual Basic開發(fā)環(huán)境中,在需要聲明API 函數(shù)的地方Ctrl+V(粘貼)即可。
上面所講的聲明方法雖然簡(jiǎn)單,但只有使用WIN DOWS本身的API函數(shù)才能這樣。對(duì)于第三方提供的動(dòng) 態(tài)鏈接庫(kù)(DLL)您只有用鍵盤老老實(shí)實(shí)地敲了。
第二節(jié):牛刀小試
現(xiàn)在讀者一定很想自己親自試一下,下面舉兩個(gè) 實(shí)際應(yīng)用的例子讓大家體會(huì)一下API的妙用吧!
1.使一個(gè)窗體始終保持在屏幕的最上面
我們知道VB本身自帶的函數(shù)是難以完成此功能 的,我們可以通過調(diào)用Windows的API函數(shù): SetWindowPos達(dá)到我們的要求。操作步驟如下:
(1)啟動(dòng)VB5建立一個(gè)新工程,在該工程中添加一 個(gè)模塊(Moudel),在該模塊中用上述的"API例覽器" 添加如下的該API函數(shù)的函數(shù)聲明和常量聲明部分:
'API函數(shù)聲明
Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
'常量聲明
Global Const SWP_HIDEWINDOW = &H80
Global Const SWP_NOACTIVATE = &H10
Global Const SWP_NOCOPYBITS = &H100
Global Const SWP_NOMOVE = &H2
Global Const SWP_NOOWNERZORDER = &H200
Global Const SWP_NOREDRAW = &H8
Global Const SWP_NOREPOSITION = SWP_NOOWNERZORDER
Global Const SWP_NOSIZE = &H1
Global Const SWP_NOZORDER = &H4
Global Const SWP_SHOWWINDOW = &H40
Global Const HWND_BOTTOM = 1
Global Const HWND_BROADCAST = &HFFFF&
Global Const HWND_DESKTOP = 0
Global Const HWND_NOTOPMOST = -2
Global Const HWND_TOPMOST = -1
Global Const HWND_TOP = 0
Global Const Flags=SWP_NOMOVE Or SWP_NOSIZE
這里以"SWP_"開頭的常量是表示窗體所具有的 風(fēng)格,這些常量可以通過VB中的"OR"操作符組合在 一起。而以"HWND_"開頭的常量表示窗體在桌面上的 位置。從這些常量的英文單詞的意義上讀者應(yīng)該很容 易理解他們所具有的風(fēng)格了。所以筆者就不一一去說(shuō) 明了。至于為什么要添加這些常量而不是別的這就要 您去查看Windows SDK關(guān)于該函數(shù)的幫助文檔了。當(dāng) 然這對(duì)于初學(xué)者來(lái)說(shuō)有一定的難度,但不要畏懼,只 要您仔細(xì)看幫助就會(huì)慢慢搞懂的。因?yàn)檫@些API函數(shù) 是為C和C++的編程人員編寫的,所以如果您懂一點(diǎn) C++的話會(huì)很容易理解的。
(2)現(xiàn)在只要在您想要此功能的地方調(diào)用該函數(shù) 就可以了,調(diào)用的方法如:
Dim Success as Long
SuccesS=SetwindowPos(me.HWnd. HWND_TOPMOST,0,0,0,0,FLAGS)
若Success返回的值不等于零則表示調(diào)用成功。
比如在某個(gè)窗體的Load事件中加入上述的兩行代 碼,就可以達(dá)到使該窗體始終位于屏幕最上面的目的。
細(xì)心的讀者可能已經(jīng)發(fā)現(xiàn)上面的例子中的模塊聲 明中聲明了好幾個(gè)常量,可為什么只用到三個(gè)呢?現(xiàn) 在您可以試著改變一下API函數(shù)"SetWindowPos"中 的第二個(gè)參數(shù)或常量FLAGS中的項(xiàng),看看您的窗體會(huì) 出現(xiàn)什么樣的效果?
2.VB5中如何屏蔽掉win95中的CTRL_ALT_DEL, CTRL_ESC, ALT_TAB三組熱鍵通過調(diào)用API函數(shù)"SystemParametersInfo"來(lái)實(shí) 現(xiàn)。
首先創(chuàng)建一新工程;在此工程中添加一個(gè)窗體和 一個(gè)模塊;在窗體上拖放兩個(gè)按鈕分別命名為 "cmdDisable","cmdEnable";Copy如下代碼入模塊中:
Public Declare Function SystemParametersInfo Lib "user32" Ahias "SystemParametersInfoA" (ByVal uAction As Long,ByVal uParam As Long, lpvParam As Any,ByVal fuWinIni As Long)AS Long
Public Const SPI_SCREENSAVERRUNNING=97
在窗體的代碼編輯區(qū)Copy如下代碼:
'使三組熱鍵失效
Private Sub cmdDisable_click()
SystemParametersInfo
SPI_SCREENSAVERRUNNING,True,byVal 1&,0
End Sub
Private Sub Form_Unload(Cancel As Integer)
'程序退出前是熱鍵有效
CndEnable_Click
End Sub
若將此功能和屏幕保護(hù)程序結(jié)合到一起,那您的屏幕 保護(hù)程序一定增色許多。
API函數(shù)的簡(jiǎn)單調(diào)用例子就是這么容易,相信現(xiàn)在您 對(duì)API的調(diào)用已不再感到神秘了,接下來(lái)我們就看看一個(gè) 比較復(fù)雜的應(yīng)用。
第三節(jié):高手進(jìn)階
上面的關(guān)于API的調(diào)用的例子只是為了帶您去Win dows API世界中去探索一下。相信您已探索到了一點(diǎn)眉 目并想去實(shí)現(xiàn)一些更"好玩"的東西了。好!下面就向您 介紹一個(gè)很"好玩"同時(shí)又會(huì)使您的程序看起來(lái)更專業(yè)化 的一個(gè)API調(diào)用。
相信您的機(jī)器上一定裝有"金山詞霸",試著啟動(dòng)它 您發(fā)現(xiàn)了什么?啟動(dòng)畫面過后它"不見了"。把鼠標(biāo)移到 桌面的右下角,原來(lái)它以圖標(biāo)的形式"藏在" Windows 的托盤中。用鼠標(biāo)右擊它還會(huì)彈出一個(gè)菜單功能項(xiàng)供您 選擇?,F(xiàn)在您一定想把自己的程序也放到托盤,這樣您的 程序多具有專業(yè)水準(zhǔn)!
下面是此功能的實(shí)現(xiàn)步驟:
1.這里我們調(diào)用的API函數(shù)是: "Shell_NotifyIcon",在您的模塊中添加如下的函數(shù)聲明 和常量聲明:
'以下常量告訴系統(tǒng)在托盤中您的圖標(biāo)上發(fā)生了什么 操作
'常量聲明
Public Const WM_MOUSEMOVE = &H200 '在圖標(biāo)上移動(dòng)鼠標(biāo)
Public Const WM_LBUTTONDOWN = &H201 '鼠標(biāo)左鍵按下
Public Const WM_LBUTTONUP = &H202 '鼠標(biāo)左鍵釋放
Public Const WM_LBUTTONDBLCLK = &H203 '雙擊鼠標(biāo)左鍵
Public Const WM_RBUTTONDOWN = &H204 '鼠標(biāo)右鍵按下
Public Const WM_RBUTTONUP = &H205 '鼠標(biāo)右鍵釋放
Public Const WM_RBUTTONDBLCLK = &H206 '雙擊鼠標(biāo)右鍵
Public Const WM_SETHOTKEY = &H32 '響應(yīng)您定義的熱鍵
'API函數(shù)聲明
Public Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias " Shell_NotifyIconA" (ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As Long
'自定義一個(gè)調(diào)用API Shell_NotifyIcon要用到的類 型"NOTIFYICONDATA"
Public Type NOTIFYICONDATA
cdSize As Long 'NOTIFYICONDATA類型的大小
hwnd As Long '你的應(yīng)用程序窗體的名柄
uId As Long '應(yīng)用程序圖標(biāo)資源的ID號(hào)
uFlags As Long '使那些參數(shù)有效它是以下枚舉類型中的
'NIF_MESSAGE、NIF_ICON、NIF_TIP三組的組合
uCallbackMessage As Long '鼠標(biāo)移動(dòng)時(shí)把此消息發(fā)給該圖標(biāo)的窗體
hIcon As Long '圖標(biāo)名柄
szTip As String*64 '當(dāng)鼠標(biāo)在圖標(biāo)上時(shí)顯示的Tip文本
End Type
'這是一個(gè)枚舉類型它告訴API Shell_NotifyIcon去做什么操作
Public Enum enm_NIM_Shell
NIM_ADD=&H40 '在“金碟”中加一圖標(biāo)
NIM_MODIFY=&H1 '修改“金碟”中的圖標(biāo)
NIM_DELETE=&H2 '刪除“金碟”中的圖標(biāo)
NIF_MESSAGE=&H1 '使類型"NOTIFYICONDATA"中的uCallbackMessage有效
NIF_ICON=&H2 '使類型"NOTIFYICONDATA"中的hIcon有效
NIF_TIP=&H4 '使類型"NOTIFYICONDATA"中的szTip有效
WM_MOUSEMOVE=&H200 '使鼠標(biāo)移動(dòng)消息有效
End Enum
'定義一個(gè)"NOTIFYICONDATA"類型的變量
Public nidProgramData As NOTIFYICONDATA
以上是函數(shù)及常量聲明和自定義的一個(gè)類型變量,下 面是此API函數(shù)的調(diào)用方法:
2. 在窗體上用菜單編輯一個(gè)具有如下信息的菜單項(xiàng):
主菜單:無(wú)標(biāo)題、名稱(mainMenu)
子菜單:標(biāo)題(API編程)、名稱(submnul);
標(biāo)題(退出)、名稱(submnu2).
這里只是舉個(gè)例子,具體的功能你可以根據(jù)你的具體需要來(lái)編輯此菜單項(xiàng)
3. 在窗體的Load事件中添加如下代碼:
Private Sub Form_Load()
'隱藏窗體
With Me
.Top =-10000
.Left = -10000
.WindowState = vbMinimized
End With
'設(shè)置類型NOTIFYICONDATA所具有的特征
With nidprogramData
.cbSize = Len(nidProgramData)
.hwnd = Me.hwnd .uld = vbNull
.uFlags = NIF_ICON Or NIF_TIP Or NIF_MESSAGE
'觸發(fā)鼠標(biāo)移動(dòng)消息
.uCallbackMessage = WM_MOUSEMOVE
.hIcon = Me.Icon '“托盤”中放入窗體圖標(biāo),你可以把窗體的圖標(biāo)換成你所喜歡的圖標(biāo)
.szTip ="VB 的 Win32 API 編程" & vbNullChar
End With
'調(diào)用該函數(shù)
Shell_NotifyIcon NIM_ADD,nidprogramData
End Sub
'根據(jù)不同的鼠標(biāo)消息做不同的操作
Private Sub Form_MouseMove(Button As inte ger, Shift As lnteger, x As Single, Y As Single)
On Error GoTo Form_MouseMove_err:
Dim Result As Long
Dim msg As Long
'X的值依賴與顯示模式的設(shè)置
If Me.ScaleMode = vbpixels Then
msg = x
Else
msg = x/Screen.TwipsPerPixe1X
End If
Select Case msg
Case WM_LBUTTONUP
'在這里加入鼠標(biāo)左鍵釋放時(shí)你想做的操作
Case WM_LBUTTONDBLCLK
'在這里加入雙擊鼠標(biāo)左鍵時(shí)你想做的操作
Case WM_RBUTTONUP
'通常這里彈出你的功能菜單
PopupMenu mainMenu
Case WM_MOUSEISMOVING
'在這里加入鼠標(biāo)正在移動(dòng)時(shí)你想做的操作
End Select
Exit Sub
Form_MouseMove_err:
'在這里加入你的處理異常錯(cuò)誤的代碼
End Sub
4.Run你的程序,您是不是看到了象“金山詞霸”一樣的功能?相信你此時(shí)的感覺一定特別“爽”!
API的世界j是豐富多彩的,只要你肯細(xì)心地去探索它你一定會(huì)獲得許多意想不到的好東西。所以筆者覺得定值得每一個(gè)具有“好奇”精神的人去探索它。后續(xù)的期刊筆者會(huì)向讀者詳細(xì)介紹一些更好更“?!钡腁PI調(diào)用。