Crazy City 公會根據地 伺服器 : 海怒斯 ID: Ya小多

10/10 妄想世界論壇 建設完成
欲使用 數據 . 外掛等 區域 請先加入會員即可
本論壇一律"禁止討論付費外掛"只討論BUG或WZ

您沒有登錄。 請登錄註冊

VB Api相關資訊 大量資料

上一篇主題 下一篇主題 向下  內容 [第1頁(共1頁)]

1 VB Api相關資訊 大量資料 于 周六 10月 10, 2009 8:50 pm

guage6110

avatar
管理者之章
管理者之章
一、API是什麼?

  這個我本來不想說的,不過也許你知道其它人不知道,這裡為了照顧一下新手,不得不說些廢話,請大家諒解。

  Win32 API即為Microsoft 32位平台的應用程序編程接口(Application Programming Interface)。所有在Win32平台上運行的應用程序都可以調用這些函數。

  使用Win32 API,應用程序可以充分挖掘Windows的32位操作系統的潛力。Mircrosoft的所有32位平台都支持統一的API,包括函數、結構、消息、宏及接口。使用 Win32 API不但可以開發出在各種平台上都能成功運行的應用程序,而且也可以充分利用每個平台特有的功能和屬性。

  
  以上為API的相關介紹,不過有些新手看了以後可能還是不怎麼明白API到底有什麼用?這裡請不要著急,如果你有足夠耐心的話,請慢慢往下看。

二、如何使用API?

  估計這才是大家真正關心的,那麼如何使用API呢?在了解API之前,先打開你的VB書,翻到過程函數這章來,在搞清楚API之前應該先搞懂過程函數是怎麼一回事!如果你還不知道過程的工作方式,那麼請先不要急著往下看,那樣容易走很多彎路。

  好了,當你理解了過程函數時,也就是你可以使用API的時候了,別把API看得太難,你就像使用過程函數一樣使用API就可以了。首先,讓我們看看一個簡單的API,以下:

  Private Declare Sub Sleep Lib \"kernel32\" Alias \"Sleep\" (ByVal dwMilliseconds As Long)

  以上這個API的呢是起一個延時作用。你如果是剛接觸API的話可能會感到API的書寫及其復雜,而且會感到很不適應。其實這沒什麼的,慢慢習慣就好了。至于API這些復雜的書寫你就不用操心了,在你安裝VB的時候微軟已經幫我們帶上了API瀏覽器,這些全部都可以利用API瀏覽器幫我們自動生成。API瀏覽器的位置位于[開始菜單-程序-Microsoft Visual Basic 6.0 中文版-Microsoft Visual Basic 6.0 中文版工具-API 文本瀏覽器]。打開API瀏覽器,在最上面的一個文本框中輸入Sleep,這時下面列表框中就會自動顯示相應的API函數,然後點右邊添加按鈕即可,接著點擊復制按鈕,這時你就可以用Ctrl+V把聲明的API添加到VB代碼窗口中了。

  這裡我要說一下,有些新手可能還弄不明白。API的聲明範圍一般有兩種模式,一種是Private(私有的),一種是Public(公用的)。一般Private是聲明在類模塊或窗體類中,Public聲明在模塊中。你在添加API的時候,添加按鈕下面就有API的聲明範圍,可以根據自己的需要進行添加。這裡我們一般選擇私有的(Private)就可以了。

  經過上面,我們知道如何添加API,接著我們分析一下API聲明,這是你了解API必備的。首先看第一個單詞Private,很顯然,我上面剛剛講過,這是申明一個私有的API變量。再看第二個Declare,這個單詞幫我們告訴VB是在申明API函數,一般申明外在的API函數時都必須帶上這個單詞。第三個Sub,別告訴我你不知道什麼意思?這就是我叫你先學習VB中過程函數的意思,這個說白了就是沒有反回值,一般如果不是Sub而是Function都帶有反回值的。第四個Lib,這個是告訴VB我們要聲明哪一個DLL中的API函數,也就是告訴VB我們要申明第五個單詞kernel32.dLL中的API,一般寫DLL名稱時都要用雙引號括起來,如\"user32\"、\"shell32.dll\"等,至于後面的.dll這個可以帶可不帶。再來看第六個Alias,這個也是需要同後面一個一起用的,我們應該把第六個和第七個連起來一起看Alias \"Sleep\",這個意思表示將被調用的過程在DLL中還有另外的名稱,這個是可選的。最後括號裡面的,也就是和過程函數一樣,你傳入相應的值就可以了。

  上面我們分析完API函數聲明以後,接著我們就要自己動手寫代碼了。先把這個API復制到Form1代碼窗口中,然後寫如下代碼:

Private Declare Sub Sleep Lib \"kernel32\" (ByVal dwMilliseconds As Long)
Private Sub Form_Load()
Sleep 2000
End Sub

  解釋一下,也就是在窗體啟動時使用Sleep API進行延時2秒,後面的參數dwMilliseconds是表示你要延時的秒數,基本上和設置Timer中的秒數一樣。你再看一下Sleep 2000的使用方式,是不是和使用VB過程函數一樣呢?好了,我們的第一個VB API程序寫完了,可以看到使用API並不是一件很難的事。

三、如何才能提升你對API的學習興趣?

  API,我常把它看做成過程函數,不過每人都有每人的見解和理解方式,自己的理解方式只要可以幫助自己更好的學習和掌握API,也沒必要一定要學習他人的。

  1,自己做MsgBox

  了解API參數的使用方法是很重要的,這裡我們不用VB的MsgBox,直接使用API彈出MsgBox消息框。首先,打開API瀏覽器,選擇MessageBox,大家可以用這個API和VB內置的MsgBox比較一下,其實MsgBox也就是MessageBox的縮寫,只不過一個是API,一個是VB內置的,但兩者都是通過API進行工作的。好了,選擇私有聲明方式,粘貼到VB代碼編輯窗口中,然後新建一個CommandButton,寫入以下代碼:

Private Declare Function MessageBox Lib \"user32\" Alias \"MessageBoxA\"
(ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String,
ByVal wType As Long) As Long
Private Sub Command1_Click()
MessageBox Me.hwnd, \"這裡是內容\", \"標題\", 0
End Sub

  先讓我們來分析一下,首先看第一個參數Byval hWnd As Long,很顯然這是一個長整形變量,所以我們這裡需要傳遞的是數字,你可能會發現我們傳遞的並不是數字啊,而是 Me.hwnd??很奇怪是嗎?如果你真的有此疑問說明你是真心想要學習好API的,現在就讓我們來看看Me.hwnd到底是什麼東西?以下摘自VB幫助文檔:
  hWnd 屬性:返回窗體或控件的句柄。
  句 柄:是由操作環境定義的一個唯一的整數值,它被程序用來標識或者切換到對象,如窗體或控件等。

  現在估計你差不多就已經明白了,我們調用的hwnd其實是一個句柄整數值,你可以用 Msgbox Me.hwnd 看一下就知道了。至于Me這是一個關鍵字,代表當前Form窗體對象。如:Me.Caption=\"標題\"、Me.BackColor=vbRed等。

  接上面的,首先我們傳入了Me.hwnd,表示是當前窗口調用MessageBox,這裡告訴大家一個技巧,也就是以後凡是看到Byval hwnd As Long,一般都是需要傳入句柄的,至于傳入哪個對象句柄,那就要看你是怎麼實現的了。
  ByVal lpText As String,這個是字符串變量,標識著叫我們需要傳入字符串進去,可以看裡面的變量字符lpText,屬于文本的意思,也就是說是用來顯示MsgBox中的消息文本的。ByVal lpCaption As String,也是字符串變量,還是傳入字符串進去。在看裡面的變量字符lpCaption,其實就是顯示MsgBox標題的。
  ByVal wType As Long,這是一個整形變量,需要傳遞整形數字,還是看裡面的變量字符wType,標識著顯示MsgBox類型,這裡可以像VB的MsgBox一樣使用,如這裡可以傳入:vbYesNo,vbOkCancel等,如果忽略那就傳入0即可。

  好了,按F5啟動程序,點擊Command1,接著就會彈出一個消息框,這裡我們制作以及分析MsgBox已經完成了。希望你能在這段學習到一些知識。

  2,來點實用的吧

  就拿隱藏Windows任務管理器來說吧,這裡只能隱藏任務管理器中的窗口,不能隱藏進程。(問:有沒有隱藏進程的?答:你想幹什麼?),當程序運行後你無法從任務管理器的窗口中關閉程序,只能從進程中進行終止。好了,還是老規矩,打開API瀏覽器,輸入GetWindow和ShowWindow兩個API,聲明範圍還是私有的,復制粘貼到Form代碼窗口中,嗯,好了?別急,還是API瀏覽器,選擇Combox中的常數,輸入GW_OWNER和SW_HIDE這兩個API常數,然後粘貼到代碼窗口中,問我這兩個是幹什麼的?那就接著往下看吧。寫入以下代碼:

Private Declare Function GetWindow Lib \"user32\" (ByVal hwnd As Long,
ByVal wCmd As Long) As Long
Private Declare Function ShowWindow Lib \"user32\" (ByVal hwnd As Long,
ByVal nCmdShow As Long) As Long
Private Const GW_OWNER = 4
Private Const SW_HIDE = 0
Private Sub Form_Load()
Dim lphWnd As Long
lphWnd = GetWindow(Me.hwnd, GW_OWNER)
ShowWindow lphWnd, SW_HIDE
End Sub

  又到了分析的時候了,這對剛入門的新手可謂是最激動的時候了。好了,還是老子,看看兩個API的表面意思和傳遞值變量。

  先看GetWindow,表面意思:獲取窗口。傳遞值變量:hWnd整形句柄,wCmd整形命令值。
  再看ShowWindow,表面意思:顯示窗口。傳遞值變量:hWnd整形句柄,nCmdShow整形命令值。

  然後是使用代碼,先看lphWnd = GetWindow(Me.hwnd, GW_OWNER)這句,這句意思是獲取當前窗口的所有者窗口句柄,可以看到GetWindow是Function過程函數,執行以後會返回相應的窗口句柄值,這個值為Long整形(同句柄)。接著調用ShowWindow lphWnd, SW_HIDE,這句意思是顯示lphwnd這個句柄的窗口,關鍵一句是最後的SW_HIDE,這是API函數的常量。通過設置常量能讓系統知道API到底應該怎麼執行顯示窗口,是顯示?還是隱藏?Hide當然是隱藏的意思。好了,編譯成Exe,運行後打開任務管理器,查看程序窗口,還有嗎?

  我又要說一下了,有些人可能不懂為什麼要用GW_OWNER這些常量,這些到底有什麼用?還有就是我怎麼知道哪些API對應哪些的常量?其實這些常量你只要稍微注意一下就知道它們是怎麼回事了,如在GetWindow中我使用GW_OWNER,在ShowWindow中我使用SW_HIDE這些常量都有一個共同的特點,就是他們都是以API的單詞第一個字母為標準。如GetWindow相對應的常量就是Get(G)Window(W)=GW,ShowWindow相對應的常就是Show(S)Window(W)=SW,這些常量可以自己在VB的API瀏覽器中找找看。

  3,繼續往下學吧。。

上面兩個我們講到了一般API的使用方法,和一些API常量的使用方法,接著我們來看看API類型的使用方法,在了解這一小節前請先搞懂VB中的自定義類型(Type)這章,否則你可能會稀裡糊塗的,到時別怪我沒提醒你哦!

這次讓我們來獲取一下鼠標指針的位置。這裡教大家一個技巧,當你想用API去實現某一特定的功能時,卻又不知道該用哪個API,這時你可以就表面的意思到API瀏覽器找找,有70%以上的機率可以找到哦!現在就拿這個API開刀,那我們應該如何找?別著急,往下看:

如我們現在要獲取鼠標指針位置,可以這樣翻譯一下:Get(獲取)Cursor(指針)Pos(位置),組合起來:GetCursorPos,呵呵,一條API就這樣出來了,到API瀏覽器輸入這個組合單詞,呵,有吧?見以下:

Private Declare Function GetCursorPos Lib \"user32\" Alias \"GetCursorPos\" (lpPoint As POINTAPI) As Long

好了好了,高興一下就算了,現在讓我們分析一下這個API,看其它的沒啥不同的,其中只有一個參數,就是最後一個變量有些不懂?在VB中好像沒有見過這個變量?不明白麼?那就再繼續往下看。

lpPoint As POINTAPI,POINTAPI?很顯然,在VB中並沒有此類型,一般都是String、Integer、Long、Byte等變量類型,那麼這個也就理所當然的是自定義類型(問:什麼是自定義類型?答:不知道,自已不會看書啊)。既然是自定義類型,那麼我們如何才能知道它是如何定義的呢?這裡也就不用你操心啦,還是API瀏覽器,在最上面的Combox中選擇類型,這時下面List中也就自然的把API的相關類型顯示出來了,現在我們開始在Text文本框中輸入我們需要的自定義類型,POINTAPI,點擊添加,出來了吧?如下:

Private Type POINTAPI
x As Long
y As Long
End Type

好了,現在開始寫代碼,添加一個Timer控件,設置屬性見以下:

Interval = 100
Enabled = True

雙擊Timer控件,轉到代碼環境中寫入以下代碼:

Private Declare Function GetCursorPos Lib \"user32\" (lpPoint As POINTAPI) As Long
Private Type POINTAPI
x As Long
y As Long
End Type
Private Sub Timer1_Timer()
Dim lpPoint As POINTAPI

GetCursorPos lpPoint

Me.Caption = \"X = \" & lpPoint.x & \" Y = \" & lpPoint.y
End Sub

好了,分析開始,緊張不?別緊張,沒啥值得緊張的!見以下:

Dim lpPoint As POINTAPI,申明一個POINTAPI類型變量,我們學過自定義類型的朋友都知道,一般使用自定義類型時都需要先申明一個相關的類型變量方可使用。

GetCursorPos lpPoint,這一步我不說你都知道,調用API唄。通過這個API獲取鼠標指針的相關信息。這裡我們使用了自己聲明的lpPoint變量,那為啥要使用這個變量呢?這裡我們回過頭來就前兩節我們所分析的那樣進行分析,可以看到GetCursorPos所需要傳遞的值,如果是Long,我們就傳入整形數字,如果是String,我們就傳入字符串,這裡是POINTAPI,所以理所當然是要傳入POINTAPI類型,但是!VB中的自定義類型不可以直接使用,所以我們需要先聲明一個相同類型的變量。不知道說了這麼多你懂了沒?


Me.Caption = \"X = \" & lpPoint.x & \" Y = \" & lpPoint.y,最後一句,也就是用來顯示當前鼠標的坐標值的,我們通過聲明的lpPoint變量來獲取相應的鼠標坐標值,如果你不懂,那就請你先把VB自定義類型這章學完再說。

這裡關于API的一些使用方法及範例就先介紹到這裡,如果你還有耐心往下看下去的話,那我們就接著往下聊!

四、如何慢慢提升自己的API功力?

何為API功力?其實沒必要搞那麼清楚,首先需要搞明白的就是,你應該知道在什麼環境下使用什麼API,實現哪些功能應該使用哪些API!這才是我們需要的。

1,試著自己從小程序開始寫起。

寫小程序?對!在你寫小程序時應該揀你最感興趣的程序寫,否則有可能你寫到一半以後會覺得自己這個程序寫得毫無價值,簡直是在浪費時間,最後到頭來還是功虧一簣。這裡我拿什麼當題材呢?我在這裡也想了很久,最後還是決定選擇一個注銷Windows程序來做題材(其實這是我當初學API最想實現的功能)。

注銷Windows也就是退出Windows(重啟,關機等都一樣,不都是退出的意思嗎?),根據表面意思在API瀏覽器中輸入Exit(退出)Windows,看看有沒有這個API?這裡提醒一下,你在查找這個API的時候還會看到ExitWindowsEX這個API,其實這兩個API實現的功能一樣,前者是用在16位操作系統上,只不過在Win32位操作系統上一般都使用ExitWindowsEX。所以這裡就使用後者。API見以下:


Private Declare Function ExitWindowsEx Lib \"user32\" Alias \"ExitWindowsEx\" (ByVal uFlags As Long, ByVal dwReserved As Long) As Long

看看裡面的兩個參數,ByVal uFlags As Long?這裡我們需要傳入一個整形數字,可是應該傳入什麼數字呢?這裡說下,API中的參數可以傳入不同的值,不同的值從而導致產生不同的結果。分析API中參數應該傳遞哪些值其實是有技巧的,以後大家只要是看到參數字符中包函Flags字符的話那就說明該參數可以被傳入一個或多個標志,並且大部分都是傳入API常數(什麼是API常數就不用我說了吧)。說白話點,就是我們可以傳入多個API常量,並且可以在API瀏覽器中找到,當然,不一定所有的API常數都可以在API瀏覽器中找到,不過大部分都可以。在API瀏覽器查API常量時我前面就教過大家技巧,現在該是我們實踐的時候了,分析如下:


Exit :頭一個大寫字符 E
Windows:頭一個大寫字符 W
Ex :頭一個大寫字符 E
組合 :EWE_


好了,現在在API瀏覽器的中常數中找找,咦?發現好像沒有以EWE開頭的常數??只發現以EWX開頭的?現在先別著急,咱們回過頭來再分析下,咱們是失敗在最後一步Ex上,這裡我不得不否決我前面教過大家的技巧,但是又不能完全否決,出現這種情況時就需要大家靈活運用API常數的分析法,可以看到EWX最後一個X是以Ex的X作結尾的,以這種方法做API常數開頭的不止這一個,所以這裡我特意留了一個陷阱,希望給大家帶來一些經驗將來能夠靈活運用。現在我把關機uFlags所能用到的相關常數發上來,如下:


Private Const EWX_FORCE = 4
Private Const EWX_LOGOFF = 0
Private Const EWX_REBOOT = 2
Private Const EWX_SHUTDOWN = 1

怎麼樣?看得懂吧?英語稍微好一點基本上沒問題。不過這裡我還是要解釋一番,照顧新手嘛!


EWX_FORCE 前面的 EWX_ 我就不說了,關鍵是看 _ 符號後面的,Force 單詞翻譯:強制,強迫。人工在翻譯一下(我英文不好,翻譯錯了請別見怪,呵呵 ^_^ ),意思是說:強制執行ExitWindowsEx API關機函數。不知道這樣解釋你能不能明白。那到底這個常數有什麼用呢?這裡我們先回憶一下以前關機的時候,當Windows無法關閉某些窗口的時候就停止繼續關機了,最後還得把無法關閉的窗口手動關閉方可,現在,如果我們使用這個常數進行關機,那Windows不管你窗口能不能關閉,直接強制關閉。希望你懂了。

EWX_LOGOFF 這個嘛,貌似組合單詞,不可直接翻譯,那樣就不是那個意思了。Logout Off,是這樣寫嗎?注銷的意思。

EWX_REBOOT 不浪費時間了,直接說明意思:重新啟動。

EWX_SHUTDOWN 關機。


至于第二個ByVal dwReserved As Long,為保留整形,一般為0即可。至于為什麼為0,大家可以到網上下載一些專門講解API函數的電子書看看,裡面有大部分API函數的詳細講解。或者下載VS.MSDN看看,在MSDN中說Windows 2000/95/98/Me中此參數忽略,XP中是指定關機消息說明。


最後看看這個API為Function聲明,說明該函數有返回值,返回值為Long,MSDN中說:如果執行成功,則返回非零,否則為零。


現在上面已經把這個關機API和相關參數常量都給你分析透了,你可別告訴我你還不知道怎麼寫?好了,這裡我們做一個定時注銷程序,呵呵,雖然很簡單,不過很多時候用得上哦!在Form窗口上添加Timer控件,Interval 設置為1000,Enabled 設置為 True。好了,代碼如下:


Private Declare Function ExitWindowsEx Lib \"user32\" (ByVal uFlags As Long, ByVal dwReserved As Long) As Long
Private Const EWX_LOGOFF = 0
Private Sub Timer1_Timer()
Static i As Integer

i = i + 1

Me.Caption = i \'這一步純粹是想看看當前已經執行到幾秒了?可不要

If i = 10 Then \'秒數判斷,可以根據自己的需要進行運算
ExitWindowsEx EWX_LOGOFF, 0
End If
End Sub


其實我都有點不想分析了,不過為了照顧大眾,不得不說下,Static i As Integer 靜態變量(問:啥叫靜態變量?答:我暈!),i = i + 1是每執行Timer一次i就加1,Timer的interval設置為1000,1000為一秒,2000為二秒。。。。後面一個If i = 10 Then是判斷當i=10以後,也就是10秒,就執行注銷,這個時候你可別忘了保存好你的其它沒有保存的文件哦,如果沒保存資料丟失的話偶不承擔任何法律責任的。其實這裡我們可以自己做一個,如可以寫成這樣:ExitWindowsEx EWX_LOGOFF Or EWX_FORCE, 0,其中用了Or運算,整體的意思是強制Windows注銷。這樣理解就夠了,只要能讓你明白。


現在我又要說一下了,不說不行的!就是在API中使用 Or 運算,關于Or運算符VB書中都有詳細解釋的,別告訴我你沒看?沒看馬上去看!上面EWX_LOGOFF Or EWX_FORCE 的使用是把 注銷 和 強制 進行Or位運算,對兩個數值執行按位析取,這裡涉及到二進制運算,說多了你可能不明白(如果你還是想追根到底的想知道到底是怎麼一回事的話,我也沒辦法,給個網址你慢慢看http://book.csdn.net/bookfiles/110/1001103366.shtml),我就說簡單點的吧,以後如果你想組合兩個API常數的功能,一般都是用 Or 進行運行的。如上面寫的。


好了,保存其它文件,然後F5運行之,看著Form標題的數字慢慢添加,當為10時,Windows開始注銷。。。


小提示:在使用EWX_SHUTDOWN的時候你可能會感覺沒有作用,主要是NT系統的安全性提高,需要用其它API進行提升自己的權限才可以。關于如何提升應用程序權限請百度一下。


2,先從一些最簡單的API開始


無疑自己試著寫程序是最好的提升方法,學完一些知識以後自己試著寫寫,這樣能讓你理解的更快更好,好了不說廢話了,接著往下看。


最簡單的API,呵呵,哪些最簡單呢?這個我也說不好,這樣吧,咱們就從Get(獲取)開始,那Get什麼呢?Window(窗口),還是從窗口下手吧,這樣更接近我們日常的編程,誰叫這是一個Windows操作系統呢?先列幾個常用的API:


GetWindow、GetWindowDC、GetWindowLong、GetWindowRect、GetWindowRgn、GetWindowsDirectory、GetWindowText、GetWindowThreadProcessId


還有很多,我就先列舉幾個簡單點的,咱們就從這幾個中間隨便抽幾個來講講吧。


先從GetWindowText下手,大家就表面的意思進行理解下,Get(獲取)Window(窗口)Text(文本),Very Good!這個API以前不錯的,可以獲取密碼框中的密碼,呵呵,說到這裡,我估計有些人開始興奮起來了!那好,Follow Me!


新建一個Form窗口,然後添加一個CommandButton,Caption設置為:顯示密碼。接著添加兩個TextBox,Text1屬性設置:PasswordChar=*;Text=123456789,Text2的屬性基本上沒有什麼需要設置的,只需要把Text屬性為空就可以了,它主要是用來幫助咱們顯示出密碼的。好了,在Form1代碼框中填入以下代碼:


Private Declare Function GetWindowText Lib \"user32\" Alias \"GetWindowTextA\" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Sub Command1_Click()
Dim sBuffer As String

sBuffer = Space(255)
GetWindowText Text1.hwnd, sBuffer, 255

Text2.Text = sBuffer
End Sub


OK,F5運行,點擊Command1,怎麼樣?Text1中的密碼字符顯示在Text2中了吧?你可以再更改下Text1中的密碼,然後再點擊Command1試試。也許你覺得會多此一舉,為何不Text2.Text=Text1.Text這樣?如果真的這樣的話看似簡單,那你就學不到API了。


又到了開始分析的時候了,打起精神來,先看第一句:Dim sBuffer As String,不用說,聲明一個字符串變量唄!接著看第二句:sBuffer = Space(255) 那這一句呢?有些人可能不知道了,沒事,我會仔細講的。Space是VB內置的字符串處理函數,VB中的幫助文件中有說明:


開始{

本示例使用 Space 函數來生成一個字符串,字符串的內容為空格,長度為指定的長度。
Dim MyString
\' 返回 10 個空格的字符串。
MyString = Space(10)
\' 將 10 個空格插入兩個字符串中間。
MyString = \"Hello\" & Space(10) & \"World\"

}結束

很顯然,我這一句是要分配255個空格字符串內存,為啥要用分配?這都是為後面所要用到打定的基礎。接著往下:


GetWindowText Text1.hwnd, sBuffer, 255 這一步是關鍵,通過它來獲取咱們想要的窗口文本,看第一個參數,我前面講過hwnd一般都是需要傳入句柄的,這時咱們傳入了Text1.hwnd(Text1控件的句柄),第二個參數,lpSting為字符串變量,所以這裡咱們傳入sBuffer字符串變量。最後一個cch為Long整形,所以理應傳入數字,這裡我們傳入了255。現在又有人想問了,為什麼需要這麼傳入值?貌似和以前的傳入不一樣?確實!一剛開始你可能搞不懂,這時候我先講講大概的意思,我們用GetWindowText來獲取窗口中的文本,當獲取成功以後,理所當然會返回窗口中的字符串,但是當我們用這個API進行獲取時,必須需要一個緩衝來保存我們所獲取的字符串,你如果不信去試試把sBuffer = Space(255)去掉,後面的255其實就是告訴這個API我們緩衝字符串的大小,這裡再告訴大家一個技巧,以後只要是看見包函有cch字符時,大部分都是輸入相關類型的大小。


再附加一點,就裡我說過,hwnd是用來傳句柄的,你也可以傳入其它窗口句柄,只要其它窗口有文本,都是可以通過這個API獲取的。還有Text2.Text = sBuffer其實是可以先把sBuffer處理一下再傳給Text2.Text的,關于字符串處理這裡不講。


好了,分析結束,來個小提示:在Windows操作系統中,任何有句柄的東東都可被看作為一個窗口。另外你可能會去試試QQ的密碼框,^_^ 這裡我要告訴你一下,無法成功,為什麼無法成功呢?這是一個技術問題目前不提!


接著再來試試GetWindowsDirectory,大家看表面意思吧!Get(獲取)Windows(就是Windows目錄)Directory(目錄),也就是獲取咱們那個系統目錄,如:C:\\Windows。可能我的Windows目錄中在C盤,而其它人的可能在D盤、E盤也說不定,所以有的時候軟件需要這個API進行獲取操作系統具體的Windows目錄。


好了,還是新建一個標準EXE,添加一個CommandButton,屬性Caption=顯示Windows目錄,OK,寫入以下代碼:


Private Declare Function GetWindowsDirectory Lib \"kernel32\" Alias \"GetWindowsDirectoryA\" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
Private Sub Command1_Click()
Dim sBuffer As String

sBuffer = Space(255)
GetWindowsDirectory sBuffer, 255
MsgBox \"Windows目錄在: \" & sBuffer
End Sub


分析!第一個Dim sBuffer As String字符串變量,sBuffer = Space(255)緩衝字符串,GetWindowsDirectory sBuffer, 255這個和上面所講的一樣,最後一個參數nSize為Long整形,所以傳入數值,那傳入什麼數值呢?Size???當然是緩衝字符串大小了,以後遇到這個nSize一般也是傳入相關類型的大小的。MsgBox \"Windows目錄在: \" & sBuffer,是用MsgBox消息框顯示出Windows目錄的位置。


OK,恭喜你,你又會使用了一個API,還要繼續嗎?(問:當然還要啦!答:最後一次哦!)GetWindowThreadProcessId,這次玩玩窗口進程,我估計有些人只要看見與進程有關的東東也會變得興奮,呵呵!好了,先看看這個API是什麼樣的?如下:


Private Declare Function GetWindowThreadProcessId Lib \"user32\" Alias \"GetWindowThreadProcessId\" (ByVal hwnd As Long, lpdwProcessId As Long) As Long


看表面意思:Get(獲取)Window(窗口)Thread(線程)Process(程序)Id(ID),組合:獲取當前線程的窗口進程ID。至于進程ID要著有什麼用,自己以後深入32編程就知道了。

看看參數,ByVal hwnd As Long,哈哈,熟悉吧,一個hWnd句柄。lpdwProcessId As Long這個就是咱們需要的進程ID,老規矩,新建標準EXE,添加一個CommandButton,屬性:Caption=獲取窗口進程ID。代碼如下:


Private Declare Function GetWindowThreadProcessId Lib \"user32\" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Sub Command1_Click()
Dim PID As Long

GetWindowThreadProcessId Me.hwnd, PID

MsgBox \"窗口進程的ID是:\" & PID
End Sub


我已經習慣了給大家分析了。首先看看第一個參數,ByVal hwnd As Long,又是句柄來的(問:廢話!答:教會了你也別這樣啊),lpdwProcessId As Long,這個就要注意了,看看這個參數的傳遞方式,是以ByRef進行傳遞的(問:呵呵,不懂什麼意思?答:不懂?轉回去看過程函數這章),也就是說ByRef是以地址進行傳遞的,過程中可以改變傳遞的參數值。明白了嗎?還不明白的話回去乖乖看書吧!現在明白了傳遞方式,也就是說我們聲明的PID是用來獲取窗口進程ID的,厲害啊。

F5,運行之,點擊Command1,PID出來了吧?沒出來我馬上從十樓跳下去。


溫馨小提示^_^:hWnd可以傳入其它窗口句柄,同樣可以獲取其它窗口進程ID。


接下來我們再來看看Set(設置),Set什麼呢?當然還是Window(窗口)容易些,先列出幾個常用的API:


SetWindowLong、SetWindowPos、SetWindowRgn、SetWindowText

接上面的。

首先咱們先看SetWindowText,咱們在上面講過GetWindowText這個API,GetWindowText是用來獲取窗口文本的,而這個正好相反。現在可以看看表面意思Set(設置)Window(窗口)Text(文本),好了這樣理解就夠了,我們已經知道這個API是設置窗口文本的,接著咱們就到API瀏覽器中找找這個API,如下:


Private Declare Function SetWindowText Lib \"user32\" Alias \"SetWindowTextA\" (ByVal hwnd As Long, ByVal lpString As String) As Long

接著咱們看裡面所需要傳遞的參數,一共有兩,第一個ByVal hwnd As Long我就不用說了,傳入句柄唄,第二個ByVal lpString As String,其中聲明的lpString是字符串變量,可想而知,這裡需要傳入字符串,好了,開始實踐。新建一個標準EXE,然後添加一個TextBox控件,然後再添加一個CommandButton,寫入以下代碼:


Private Declare Function SetWindowText Lib \"user32\" Alias \"SetWindowTextA\" (ByVal hwnd As Long, ByVal lpString As String) As Long

Private Sub Command1_Click()
SetWindowText Text1.hwnd, \"這是咱們設置的文本\"
End Sub


呵呵,這個看似比前面的更簡單,不過我還是要羅嗦一下,首先把Text1的句柄傳入第一個參數,這樣API知道咱們需要操作哪個窗口,第二個是一個字符串變量,所以這裡就是我們需要傳入的文本。好了,F5運行,點擊Command1,OK。


再看SetWindowPos,可以說這個API可以看成設置窗口位置,但是最終的實現效果取決于咱們傳遞的參數,好了,在API瀏覽器中找到這個API,如下:


Private 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

呵!好家伙,這個API看起來有些復雜啊?不過別擔心,有我在嘛,我會幫你好好分析的,這裡還請大家別光我一個人分析,必須把自己融入進來,咱們一起分析這樣不更有趣?好了,廢話少說,先看第一個參數:


ByVal hwnd As Long 這裡我就不講了,傳入窗口句柄


ByVal hWndInsertAfter As Long 好了,看看這個!hwndInstrAfter,可以看到裡面包函有hwnd字符,這時你可能會說我前面不是已經說過嘛,只要看見包函有hwnd字符的都應該傳入句柄嘛?呵呵,沒錯,你很聰明,記得我說的話呢!在這裡誇一下你,別驕傲啊!現在咱們好好分析一下這個地方應該傳入哪些參數!打開MSDN,不好意思是英文,這裡我就把翻譯過來的說明放上來,如下:


hWndInsertAfter - Long,窗口句柄。在窗口列表中,窗口hwnd會置于這個窗口句柄的後面。也可能選用下述值之一:


HWND_BOTTOM 將窗口置于窗口列表底部


HWND_TOP 將窗口置于Z序列的頂部;Z序列代表在分級結構中,窗口針對一個給定級別的窗口顯示的順序


HWND_TOPMOST 將窗口置于列表頂部,並位于任何最頂部窗口的前面


HWND_NOTOPMOST 將窗口置于列表頂部,並位于任何最頂部窗口的後面


可以看到這個地方有四個參數供我們選擇,一般我們會使用第三個API常數和第四個API常數,這幾個API常數都可以在API瀏覽器中找到,至于具體實現什麼功能我相信大家都知道吧,後面有寫呢!


再看看後面的幾個 x,y,cx,cy 分別為Long變量,我上面講過,SetWindowPos可以看成設置窗口位置嘛,所以這裡理所當然是傳入相關的坐標值,如果忽略則為0,自己可以試下。


ByVal wFlags As Long,這個參數,我又說過,看看字符Flags,呵呵,熟悉吧,所以這裡咱們需要傳入相關的標識常數,利用咱們以前學過的常數分析法進行分析,Set(S)Window(W)Pos(P)=SWP_ ,可以看到相關的常數了吧?這裡我把相關常數的說明發上來大家看下,如下:


SWP_DRAWFRAME 圍繞窗口畫一個框

SWP_HIDEWINDOW 隱藏窗口

SWP_NOACTIVATE 不激活窗口

SWP_NOMOVE 保持當前位置(x和y設定將被忽略)

SWP_NOREDRAW 窗口不自動重畫

SWP_NOSIZE 保持當前大小(cx和cy會被忽略)

SWP_NOZORDER 保持窗口在列表的當前位置(hWndInsertAfter將被忽略)

SWP_SHOWWINDOW 顯示窗口

SWP_FRAMECHANGED 強迫一條WM_NCCALCSIZE消息進入窗口,即使窗口的大小沒有改變

所以我說過,一個這樣的API他具體實現的功能取決于你所傳遞的參數。假設這裡咱們需要實現一個窗口永遠置前的功能,首先新建一個標準EXE,輸入以下代碼:


Private Declare Function SetWindowPos Lib \"user32\" (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
 Private Const HWND_TOPMOST = -1
 Private Const SWP_NOMOVE = &H2
 Private Const SWP_NOSIZE = &H1
 Private Sub Form_Load()
 SetWindowPos Me.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE
 End Sub

現在咱們開始分析,第一個參數傳入句柄,第二個我上面講過,實現什麼功能傳入什麼參數,這裡咱們是實現的窗口永久置前的功能,所以傳入HWND_TOPMOST常數,現在看看其實坐標,如果你不想改變窗口的具體位置的話,這裡可不設為0,再看看後面的wFlags,我傳入了兩個常數,這兩個常數的相關說明請大家看看上面就知道,主要是不改變窗口位置和不改變窗口大小的前提下把窗口置前,其它常數如果大家有興趣可以自己試試。


最後一個,看看SetWindowRgn,這裡我要解釋一番,這個API所實現的功能呢就是改變窗口外觀,也就是咱們所說的異形窗口等,通過這個API咱們可以把窗口改變成任何形狀,在API瀏覽器找到這個API,如下:


Private Declare Function SetWindowRgn Lib \"user32\" Alias \"SetWindowRgn\" (ByVal hWnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long

好了,第一個參數,句柄。第二個參數,Long變量,這裡需要傳入什麼咱們下面會講到。第三個,Boolean變量,可以說明這裡需要傳入布爾值,Redraw為重畫的意思,所以如果我們用這個API改變窗口形狀,這裡需要為True,表示重畫窗口。


現在新建一個標準EXE,然後把Form的ScaleMode設置成3-Pixel,我們知道Windows是以像素為單位的,所以使用這個API進行設置的時候是以像素為單位進行處理窗口外觀。然後把BorderStyle設置為0-None,這樣看得更明顯。好了,寫入以下代碼:


Private Declare Function SetWindowRgn Lib \"user32\" (ByVal hWnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long
Private Declare Function CreateRoundRectRgn Lib \"gdi32\" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long, ByVal X3 As Long, ByVal Y3 As Long) As Long
Private Sub Form_Load()
Dim hRgn As Long

hRgn = CreateRoundRectRgn(0, 0, Me.ScaleWidth, Me.ScaleHeight, 10, 10)
SetWindowRgn Me.hWnd, hRgn, True
End Sub

我不得不說一下這裡我又用了一個API,主要是因為使用SetWindowRgn API是需要和其它API一起進行工作的,首先讓我們先看看CreateRoundRectRgn這個API。分析如下:


整體的意思是:創建圓角矩形。這裡提示大家一個技巧,一般API中包函Rgn字符的都是代表可以改變對象外觀的。可以看看我們使用的兩個API,一個是SetWindowRgn(Rgn),一個是CreateRoundRectRgn(Rgn),希望你能明白其中的共同點。

參數:x1,y1,x2,y2,x3,y3這些都是坐標值,具體說明見以下:

X1,Y1 ---------- Long,矩形左上角的X,Y坐標
X2,Y2 ---------- Long,矩形右下角的X,Y坐標
X3 ------------- Long,圓角橢圓的寬。其範圍從0(沒有圓角)到矩形寬(全圓)
Y3 ------------- Long,圓角橢圓的高。其範圍從0(沒有圓角)到矩形高(全圓)

所以上面的代碼具體是先通過CreateRoundRectRgn創建一個圓角矩形對象,然後通過SetWindowRgn來改變窗口的外觀。

小提示:使用CreateRoundRectRgn可以創建圓角矩形,也可以使用CreateEllipticRgn創建橢圓形,CreatePolyPolygonRgn創建多邊形,CreateRectRgn矩形等,細心觀察它們最後三個字符 Rgn 呵呵,明白了吧。

3,獲取其它窗口的句柄

這個我本來打算不講的,不過網友們既然提出來了,我也只好詳細說說。一般獲取其它窗口的句柄使用以下API:


FindWindow,FindWindowEx,WindowFromPoint


這兩個API就足矣,先看看第一個API的原型:


Private Declare Function FindWindow Lib \"user32\" Alias \"FindWindowA\" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

裡面一共有兩個參數,先看第一個:ByVal lpClassName As String,字符串變量,所以這裡需要傳入字符串,第二個ByVal lpWindowName As String,同樣一個字符串變量,這裡也需要傳入字符串。再看這個API為Function,有返回值的,那返回值就是我們需要的句柄了。好了,現在了解了兩個參數的具體傳遞類型,那我們現在就要知道這兩個參數中到底應該傳入哪些值?如下:


ByVal lpClassName As String,lpClassName:類名。指窗口類名,如果忽略則傳入vbNullString。
ByVal lpWindowName As String,lpWindowName:窗口名稱。指窗口文本,如果忽略則傳入vbNullString。


現在明白了兩個參數需要傳入哪些值就好辦了,一個窗口的類名咱們有可能不知道,但是一個窗口的名稱就好辦了。如:咱們打開記事本程序,可以看到窗口標題顯示為“無標題-記事本”。好了這就是咱們需要的,現在咱們就要通過這個窗口標題來獲取記事本的句柄。新建一個標準EXE,然後輸入以下代碼:


Private Declare Function FindWindow Lib \"user32\" Alias \"FindWindowA\" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Sub Form_Load()
Dim WindowHandle As Long

WindowHandle = FindWindow(vbNullString, \"無標題 - 記事本\")

MsgBox WindowHandle
End Sub


好了,F5運行,顯示MsgBox消息框,如果不為0,那麼咱們就獲取成功了,如果為0,那麼表示獲取失敗,這個時候你有必要檢查一下你所要獲取的窗口文本是否符合你所要獲取的那個窗口文本(呵,這句話還真長!)。具體代碼意思我就不講了,大家可以自己分析下。


小提示:這個時候咱們已經得到句柄了,具體得到這個句柄幹什麼?那就看你了。給個例子,如下:


SetWindowText WindowHandle, \"哈哈\"


看看把這個代碼放在上面代碼中試下,呵呵!注意,SetWindowText你要先聲明這個API。別忘了。




再看第二個FindWindowEx,這個API是在窗口列表中尋找與指定條件相符的第一個子窗口,原型如下:


Private Declare Function FindWindowEx Lib \"user32\" Alias \"FindWindowExA\" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long

看裡面的參數,第一個和第二個:ByVal hWnd1 As Long,ByVal hWnd2 As Long,這裡都需要傳入句柄,再看第三個和第四個:ByVal lpsz1 As String, ByVal lpsz2 As String,這裡所要傳入的是字符串。具體意思如下:

hWnd1 ---------- Long,在其中查找子的父窗口。如設為零,表示使用桌面窗口(通常說的頂級窗口都被認為是桌面的子窗口,所以也會對它們進行查找)

hWnd2 ---------- Long,從這個窗口後開始查找。這樣便可利用對FindWindowEx的多次調用找到符合條件的所有子窗口。如設為零,表示從第一個子窗口開始搜索

lpsz1 ---------- String,欲搜索的類名。零表示忽略,注意一般傳入vbNullString

lpsz2 ---------- String,欲搜索的類名。零表示忽略,注意一般傳入vbNullString

用實踐幫我們分析,這裡還是拿記事本開刀。打開一個記事本,新建一個標準EXE,接著新建一個CommandButton,Caption設置為:設置文本。OK,寫入以下代碼:


Private Declare Function FindWindow Lib \"user32\" Alias \"FindWindowA\" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib \"user32\" Alias \"FindWindowExA\" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function EnableWindow Lib \"user32\" (ByVal hwnd As Long, ByVal fEnable As Long) As Long

Private Sub Command1_Click()
Dim WindowHandle As Long, ChildWindowHandle As Long

WindowHandle = FindWindow(vbNullString, \"無標題 - 記事本\")

If WindowHandle Then \'如果獲取句柄成功

ChildWindowHandle = FindWindowEx(WindowHandle, 0, \"Edit\", vbNullString)

If ChildWindowHandle Then \'如果成功獲取子句柄
EnableWindow ChildWindowHandle, False \'禁用子窗口
Else
MsgBox \"無法獲取子窗口\"
End If
End If
End Sub


好了,幫大家分析。看第一行:Dim WindowHandle As Long, ChildWindowHandle As Long,用于儲存獲取的句柄的。WindowHandle = FindWindow(vbNullString, \"無標題 - 記事本\")這個就不用講了,上面已經講過。


ChildWindowHandle = FindWindowEx(WindowHandle, 0, \"Edit\", vbNullString),這一段是通過我們已經獲取的記事本句柄獲取其中的子窗口句柄。大家可以用Spy++查看到記事本的TextBox類,然後根據類名寫入即可。


EnableWindow ChildWindowHandle, False 這又是一個新的API,雖然前面我沒有前過,但是這個API使用起來及其簡單。這個API中有兩個參數,第一個理所當然是傳入窗口句柄,第二個為Long變量,其實這裡應該設為Boolean變量好些,主要是用來處理當前窗口是否可用。True可用,False禁用。


現在F5運行,記得打開記事本哦,然後點擊Command1,看看能不能在記事本的文本框中輸入字符串?是否被禁用了?


小提示:EnableWindow之所有講出來,是希望提高大家使用API的興趣,有些被禁用的窗口你可以使用這個API把它激活,至于怎麼使用就看你自己了,這裡給大家布置一個作業,呵呵,自己去完成吧。




最後一個API,WindowFromPoint,這個API主要是獲取當前坐標的窗口句柄,不是有人想知道當前鼠標指針位置的窗口句柄嗎?用這個是不錯的選擇,原型如下:


Private Declare Function WindowFromPoint Lib \"user32\" Alias \"WindowFromPoint\" (ByVal xPoint As Long, ByVal yPoint As Long) As Long

兩個參數,一個是xPoint(x坐標值),一個是yPoint(y坐標值),現在你可以在這個兩個參數分別傳入其它窗口的坐標值就可以獲取其它窗口的句柄了。可以看到為Function聲明,返回值就是咱們需要的句柄。


咱們想實現的功能是獲取當前鼠標指針位置的句柄,所以這裡當然需要用到GetCursorPos了,結合前面所講的,新建一個標準EXE,添加一個Timer控件,Interval設置為100,Enabled=True,OK,寫如以下代碼:


Private Declare Function WindowFromPoint Lib \"user32\" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Declare Function GetCursorPos Lib \"user32\" (lpPoint As POINTAPI) As Long
Private Type POINTAPI
x As Long
y As Long
End Type
Private Sub Timer1_Timer()
Dim lpPoint As POINTAPI
Dim WindowHandle As Long

GetCursorPos lpPoint \'獲取當前鼠標指針坐標
WindowHandle = WindowFromPoint(lpPoint.x, lpPoint.y)

Me.Caption = \"當前鼠標指針位置句柄:\" & WindowHandle
End Sub


好了,最後一次給大家分析了,至于GetCursorPos的使用與說明前面已經講過,這裡不再分析。看看WindowHandle = WindowFromPoint(lpPoint.x, lpPoint.y)這句,它是通過GetCursorPos獲取的鼠標坐標值獲取當前鼠標坐標位置的句柄。最後一句我就不用說了,在程序窗口顯示獲取的句柄。




好了,API入門已經告一段落,其實我還想寫下去,不過似乎看的人多,響應的人少,很是打擊我寫下去的心情。不過還是希望大家能從上面學到一些知識。具體的API應用我就不多說,大家可以自己慢慢體會。如果你把以上我講的全部都搞懂的話,那麼證明你已經基本了解API的使用方法了,那下面就靠你自己了。至此,我希望我帶了一個好頭幫助你了解API。
轉至XD論壇

檢視會員個人資料 http://guage6110.freeluntan.com

上一篇主題 下一篇主題 回頂端  內容 [第1頁(共1頁)]

這個論壇的權限:
無法 在這個版面回復文章