談談WindowsAPI在VB中的應用
[摘 要] 本文首先講述在VB中運用Windows API的一般方法,然后結合本人編程經驗從界面編程、多媒體編程、系統編程等方面舉例講述API的實際應用,最后講述VB中API應用應注意的問題以及解決辦法。
Windows API(應用程序接口)是Windows 視窗系統提供給用戶進行系統編程和外設控制的強大的應用程序接口,靈活運用好Windows API將使用戶的程序更專業,功能更強大。本文將從VB中API運用的一般方法、編程應用和應注意的問題及解決辦法等三個方面講述在VB中API的應用問題。
一、 VB中運用Windows API 的一般方法
Windows API提供給用戶成千上萬個系統功能調用的函數,功能十分強大,靈活有效運用它,能使用戶實際中遇到的許多棘手問題迎刃而解。VB中沒有提供直接調用API的功能,但VB中能通過聲明API函數,從而有效使用API。下面是關于VB中使用API的一般方法:
1. 首先利用VB提供的API 瀏覽器查找到所需聲明的API函數和常量定義,并復制該函數。(注:若用戶無API瀏覽器,也可以從VBWINAPIWinapi32.txt中直接復制所需API函數。)
2. 然后在VB中新增一個模塊,并將前面復制的API函數和常量定義復制到模塊中。
3. 最后在VB程序中就可以象VB自身的函數一樣運用API函數。
二、VB中Windows API的編程應用
1.界面編程
1)示例一:創建不規則窗體
Win32 API 有很多讓你意想不到的功能。要創建特殊的不規則窗口看上去似乎很難。 但我們運用API,則幾行代碼就可以實現,這似乎不可思議。但事實就是如此,不信看看吧!實現步驟:
(1 ) 建立一個新項目文件DEMO1.PRJ;
(2 ) 建立模塊文件DEMO1.BAS.并在模塊的聲明部分加入以下代碼:
| Private Declare Function CreatePolygonRgn Lib "gdi32" (lpPoint As POINTAPI, ByVal nCount As Long, ByVal nPolyFillMode As Long) As Long Private Declare Function SetWindowRgn Lib "user32" (ByVal hWnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long '定義頂點結構 Public Type POINTAPI X As Long Y As Long End Type Public Dim XYPOINT() As POINTAPI |
(3)在窗體Form1的Command1_Click處理程序中加入以下代碼:
| Private Sub Command1_Click() '定義區域句柄 Dim hRgn As Long Dim lRes As Long '定義T型頂點坐標數組 ReDim XYPOINT(7) As POINTAPI 'T shape has 8 points '確定T型頂點坐標的值 With Me XYPOINT(0).X = 0 XYPOINT(0).Y = 0 XYPOINT(1).X = .ScaleWidth XYPOINT(1).Y = 0 XYPOINT(2).X = .ScaleWidth XYPOINT(2).Y = .ScaleHeight / 2 XYPOINT(3).X = .ScaleWidth - (.ScaleWidth / 3) XYPOINT(3).Y = .ScaleHeight / 2 XYPOINT(4).X = .ScaleWidth - (.ScaleWidth / 3) XYPOINT(4).Y = .ScaleHeight XYPOINT(5).X = .ScaleWidth / 3 XYPOINT(5).Y = .ScaleHeight XYPOINT(6).X = .ScaleWidth / 3 XYPOINT(6).Y = .ScaleHeight / 2 XYPOINT(7).X = 0 XYPOINT(7).Y = .ScaleHeight / 2 End With hRgn = CreatePolygonRgn(XYPOINT(0), 8, 1) lRes = SetWindowRgn(Me.hWnd, hRgn, True) Me.BackColor = vbBlue End Sub |
(4)在窗體的Form_Unload處理程序中加入代碼:
| Private Sub Form1_DbClick() Unload Me End Sub |
運行效果如下圖:

2)示例二:游動的窗體
朋友,您使用過Linux嗎?如果您使用過的話,那么Linux中那只游動的可愛小企鵝,一定忘不了。其實,該功能實現很簡單,下面,筆者將帶您一起來實現它。
實現步驟:
1. 建立新項目文件DEMO2.PRJ;
2. 建立模塊文件DEMO2.BAS.并在模塊中加入如下代碼:
| Public Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long Public Type POINTAPI X As Long Y As Long End Type Public Oldx As Long Public Oldy As Long Public Newx As Long Public Newy As Long Public Pnt As POINTAPI |
3.在窗體上加入一個時間控件Timer1_Timer處理程序中加入如下代碼:
| Private Sub Timer1_Timer() Me.SetFocus GetCursorPos Pnt Oldx = Form1.Left Oldy = Form1.Top Newx = Pnt.X * 13.5 Newy = Pnt.Y * 13.5 incx = (Newx - Oldx) / 80 * 13.5 incy = (Newy - Oldy) / 80 * 13.5 Form1.Move Oldx + incx, Oldy + incy End Sub |
4.在Image1_DblClick處理程序中加入如下代碼:
| Private Sub Image1_DblClick() Unload Me End Sub |
2.系統編程
1)示例一:屏蔽CTRL+ALT+DEL鍵
我們在編程中,為了達到特殊的要求,有時需要屏蔽功能CTRL+ALT+DLE,本示例程序將教你如何實現它。
實現步驟:
1.建立一個新項目,將其命名為DEMO3.vbp。
2.在Form1窗體的聲明中加入以下代碼:
| Private Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Long, ByVal uParam As Long, ByRef lpvParam As Any, ByVal fuWinIni As Long) As Long Const SPI_SCREENSAVERRUNNING = 97 |
3. 在Form1窗口的Command1_Click中加入以下代碼:
| Private Sub Command1_Click() Dim r As Integer Dim p As Boolean If Command1.Caption = "屏蔽" Then r = SystemParametersInfo(SPI_SCREENSAVERRUNNING, True, p, 0) Command1.Caption = "有效" Else r = SystemParametersInfo(SPI_SCREENSAVERRUNNING, False, p, 0) Command1.Caption = "屏蔽" End If End Sub |
4. 在Form1窗體的Form_Unload中加入以下代碼:
| Form1_Unload() Dim r As Integer Dim p As Boolean r = SystemParametersInfo(SPI_SCREENSAVERRUNNING, False, p, 0) |
運行效果如下圖:
2) 示例二:抓屏演示
本示例程序將演示如何拷貝屏幕圖象。
實現步驟:
1. 建立一個新項目,將其命名為Demo4.vbp。
2. 增加模塊Demo4.bas,在Demo4.bas中加入如下代碼:
| Public Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long Public Declare Function StretchBlt Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long Public Const SRCCOPY = &HCC0020 |
3. 在窗體Form1的Command1_Click處理程序中加入以下代碼:
| Private Sub Command1_Click() Dim i As Long Dim wScreen As Long Dim hscreen As Long Dim w As Long Dim h As Long Picture1.Cls wScreen = Screen.Width Screen.TwipsPerPixelX hscreen = Screen.Height Screen.TwipsPerPixelY w = Picture1.ScaleWidth h = Picture1.ScaleHeight hdcScreen = GetDC(0) i = StretchBlt(Picture1.hdc, 0, 0, w, h, hdcScreen, 0, 0, wScreen, hscreen, vbSrcCopy) Picture1.Refresh End Sub |
運行效果如下圖:

3.多媒體編程:
1) 示例一:百葉窗效果
實現步驟:
1.建立一個新項目,將其命名為Demo5.vbp。
2.增加模塊Demo5.bas,在Demo5.bas中加入如下代碼:
| Public Const SRCCOPY = &HCC0020 Public Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long |
3.在窗體的聲明部分加入代碼:
Dim h, w As Integer
4.在窗體的Form_Load處理程序中加入代碼:
| Private Sub Form_Load() Picture1.Move 0, 0 Picture2.Move 0, 0 h = Picture1.ScaleHeight w = Picture1.ScaleWidth Picture2.Width = Picture1.Width Picture2.Height = Picture1.Height End Sub |
5.在窗體的Command1_Click處理代碼中:
| Private Sub Command1_Click() Dim i, j, g As Integer Picture2.Cls For i = 0 To 50 For j = i To w Step 50 BitBlt Picture2.hDC, j, 0, 1, h, Picture1.hDC, j, 0, SRCCOPY For g = 0 To 500 Next g Next j Next i End Sub |
6.在窗體的Command2_Click的處理程序中:
| Private Sub Command2_Click() Dim i, j, g As Integer Picture2.Cls For i = 0 To 50 For j = i To w Step 50 BitBlt Picture2.hDC, 0, j, w, 1, Picture1.hDC, 0, j, SRCCOPY For g = 0 To 500 Next g Next j Next i End Sub |
7.在窗體的Picture1_Resize的處理程序中加入代碼:
| Private Sub Picture1_Resize() Picture2.Width = Picture1.Width Picture2.Height = Picture1.Height End Sub |
2)示例二:播放背景音樂
實現步驟:
1.建立一個新項目,將其命名為Demo6.vbp。
2.增加模塊Demo6.bas,在Demo6.bas中加入如下代碼:
| Public Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long |
3.在窗體的Form_load的處理程序中加入如下代碼:
| Private Sub Form_Load() Dim back back = mciSendString&("OPEN " + App.Path + "TEST.MID" + " TYPE SEQUENCER ALIAS NN", 0&, 0, 0) back = mciSendString&("PLAY NN FROM 0", 0&, 0, 0) R% = mciSendString&("CLOSE ANIMATION", 0&, 0, 0) End Sub |
4.在窗體的Command1_Click的處理程序中加入代碼:
| Private Sub Command1_Click() Dim back back = mciSendString&("CLOSE NN", 0, 0, 0) End Sub |
5.在窗體的Command2_Click的處理程序中加入代碼:
| Private Sub Command2_Click() Dim back back = mciSendString&("OPEN " + App.Path + "TEST.MID" + " TYPE SEQUENCER ALIAS NN", 0&, 0, 0) back = mciSendString&("PLAY NN FROM 0", 0&, 0, 0) R% = mciSendString&("CLOSE ANIMATION", 0&, 0, 0) End Sub |
運行效果如下圖:
三、VB中API應用應注意的問題及其對策
使用API函數的VB程序員也許都遇到這樣的現象。在VB集成環境下,程序運行后,出 現一錯誤信息對話框,按確定鍵后系統自動退出VB集成環境,此時如果你的程序尚未存盤,那末很遺憾挽回損失已回天乏力。這是你對API函數使用不當引起的一般保護故障(GPF)。
當一個GPF錯發生時,你應允許Windows關閉你的應用。有些情況下你可能需要退出Windows或者重新引導系統,出錯程度視內存被破壞程度而定。DLL(動態鏈接庫)函數中的類型不一致等錯誤是引起GPF錯誤的主要原因。下面談談避免GPF的一些技巧:
用別名來提供強類型檢查是避免GPF的有效措施之一。有些情況下,DLL函數可以接受多種類型,LoadCursor函數就是這樣一個例子,其定義如下:HCursor LoadCursor(hInstance,lpCursorName)。這里HCursor是一個指向光標對象的16位句柄,hInstance是一個16位實例句柄,lpCursorName是光標的名字或者是光標資源的32位整數ID。為了支持兩種類型的lpCursorName參數。VB有必要包含如下兩個聲明:
| DeclareFunction LoadCursor Lib"USER"(ByVal hInstance As Integer,ByVal lpCursorName As String)As Integer DeclareFunction LoadCursor Lib"USER"(ByVal hInstance As Integer,ByVallpCursorName As Long)As Integer |
但是,這兩個聲明不能在一個程序中同時存在,因為Visual Basic會報重復聲明錯。我們知道,As Any聲明可使得任何參數都可以傳遞給DLL函數,因此可以如下聲明:
DeclareFunction LoadCursor Lib"USER"(ByVal hInstance As Integer ,ByVal lpCursorName As Any )As Integer
上述聲明意味著Visual Basic能支持一個參數可接受多種類型的DLL函數,然而這就可能帶來各種災難性的后果,每當偶然情況下用不正確的參數調用該函數時,都可以引發一個GPF,我們可以這樣進行嚴格的類型檢查并且幫助防止這類問題。這種方法就是在函數的聲明中使用Alias技巧,看看下面的兩個聲明:
| DeclareFunction LoadCursorByName Lib"USER"Alias "LoadCursor"(ByVal hInstance As Integer,ByVal lpCursorName As String)As Integer DeclareFunction LoadCursorByID Lib"USER"Alias "LoadCursor"(ByVal hInstance As Integer ,ByVallpCursorName As Long)As Integer |
LoadCursorByName用字符串做lpCursorName參數訪問DLL函數LoadCursor,而函數LoadCursorByID訪問同樣的DLL函數LoadCursor,但是用長整型做lpCursorName參數,這兩個函數都對lpCursorName參數進行嚴格的類型檢查,使Visual Basic能在調用DLL函數之前識別出不正確的變量類型,最大限度地減少引起GPF或者導致系統崩潰的機會。除此之外,使用API函數時運行之前最好先存盤,仔細檢查調用API函數的參數與聲明的類型是否一致,以及嚴格檢查參數是否有效都能減少引發GPF或者系統崩潰。