功能強大的SendMessage函數

來源:互聯網
上載者:User

 

功能強大的SendMessage函數

Windows API(應用程式介面)是Windows系列軟體為程式開發人員提供的火力強大的“武器庫”,在這個武器庫中,有很多極具威力的武器,SendMessage就是其中之一,它的功能非常豐富,靈活使用這個函數,會給編程工作帶來很多便利,本文以Visual Basic為例,結合幾個具體的例子介紹該函數的功能。

一、SendMessage函數簡介

顧名思義,SendMessage函數的功能是“發送訊息”,即將一條訊息發送到指定對象(作業系統、視窗或控制項等)上,以產生特定的動作(如滾屏、修改對象外觀等)。

SendMessage函數在VB中的函數說明如下:

Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

其中四個自變數的含義和說明如下:

  • hwnd:對象的控制代碼。

希望將訊息傳送給哪個對象,就把該對象的控制代碼作為實參傳送,在VB中可以簡單地用“對象.hWnd”獲得某個對象的控制代碼,如Text1.hWnd和Form1.hWnd分別可以得到Text1和Form1的控制代碼。

  • wMsg:被發送的訊息。

根據具體需求和不同的對象,將不同的訊息作為實參傳送,以產生預期的動作。

  • wParam、lParam:附加的訊息資訊。

這兩個是可選的參數,用來提供關於wMsg訊息更多的資訊,不同的wMsg可能使用這兩個參數中的0、1或2個,如果不需要哪個附加參數,則將實參賦為NULL(在VB中賦為0)。

在簡單瞭解了SendMessage函數的格式和功能後,讓我們以幾個例子來看看它的威力:

二、SendMessage函數使用執行個體

例1、多行TextBox中的快速處理功能

在處理多行TextBox時我們經常會碰到以下幾種情況:

  • 希望瞭解多行TextBox中目前共有多少行文字;

  • 想快速返回第
  • N行的文字;

對於上面的情況,如果用VB自身的語句或函數來實現的話,要寫不短的代碼,而且由於要採用順序尋找的辦法來完成,因此代碼的執行效率也很低。如果使用SendMessage函數則可以大大減少代碼量,並大幅度的提高執行效率。

用SendMessage函數完成上面兩個任務的方法非常簡單,每個任務只需簡單地發送一條訊息給多行TextBox即可,兩個訊息分別為:EM_GETLINECOUNT 、EM_GETLINE,其它參數和傳回值見下表:

訊息常量名

訊息值

wParam

lParam

傳回值

EM_GETLINECOUNT

&HBA

未用

未用

行數

EM_GETLINE

&HC4

要找的行號

存結果的位元組串

結果位元組串的位元組數

 

下面用一個簡單的執行個體示範這兩個功能:

建立工程,在Form1上添加三個TextBox,名稱分別為Text1、txtLineCount、TxtString,將Text1的MultiLine屬性置為True,三個標籤和一個命令按鈕。為工程添加一個模組Moudle1,在其中寫如下聲明(其中SendMessage函數的聲明可以從VB的“API瀏覽器”中複製):

Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Public Const EM_GETLINECOUNT = &HBA

Public Const EM_GETLINE = &HC4

在Form1的代碼模組中寫如下代碼:

Private Sub Command1_Click()

Dim str(256) As Byte

str(1) = 1 '最大允許存放256個字元

'擷取總行數,結果顯示在文字框txtLineCount中

txtLineCount = SendMessage(Text1.hwnd, EM_GETLINECOUNT, 0, 0)

'擷取第3行的資料放在str中,轉換為字串後顯示在文字框txtString中

SendMessage Text1.hwnd, EM_GETLINE, 2, str(0)

txtString = StrConv(str, vbUnicode)

End Sub

之後,按F5運行程式,在多行文字框中隨便鍵入幾行文字,然後按下“確定”按鈕,出現畫面,說明程式正確統計出了總行數和第3行的文字。

兩點補充說明:在調用SendMessage擷取第N行字串時,lParam需要說明為位元組數組,在調用完成後,再將位元組數群組轉換為字串;另外,調用前必須在lParam的前兩個位元組指明允許存放的最大長度,其中第一個位元組為低位,第二個位元組為高位,本例將高位(即str(1))置1,說明最大允許存放256個字元。

 

例2、程式控制拉下或收合組合框的下拉式清單

一般情況下,為了拉下或收合組合框的下拉式清單,需要用鍵盤或滑鼠進行操作,而有時我們希望程式啟動並執行某個時刻自動拉出下拉式清單(比如在一些示範程式中),為了實現這個目的,我們也只有藉助於SendMessage函數,方法是發一個CB_SHOWDROPDOWN(&H14F)訊息給組合框。

在發CB_SHOWDROPDOWN訊息時,wParam參數決定了是拉下列表(=True時)還是收合列表(=False時),lParam無用(設為0)

為說明具體的使用方法,下面提供簡單的程式片段:

首先在代碼模組中做如下聲明:

Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Const CB_SHOWDROPDOWN = &H14F

當程式中某處需要拉下組合框Combo1的列表時,寫如下調用語句:

SendMessage Combo1.hwnd, CB_SHOWDROPDOWN, True, 0

當需要收合組合框Combo1的列表時,寫如下語句:

SendMessage Combo1.hwnd, CB_SHOWDROPDOWN, False, 0

例3、在列表框中尋找匹配的項目

在Win95風格的協助系統中一般都有一個“索引”頁,索引頁含有一個文字框和一個列表框,當使用者在文字框中輸入文字時,下拉式清單會動態地顯示與文字框中文字最匹配的項目,為使用者提供了最大的方便。這種效果在應用程式的協助系統中很容易實現(只要按照Win95協助系統的正常製作過程製作就可以實現),如果想在應用程式的其它地方實現這種特性就須費一番心思了。

而使用SendMessage函數實現上述特性則非常簡單,甚至只需一條語句就足夠了,那就是在文字框的Change事件中給列表框發一條LB_FINDSTRING(&H18F)訊息,該訊息告訴列表框在列表中尋找匹配的項目。

在發LB_FINDSTRING訊息時,wParam參數代表從列表框的哪一個項目後面開始尋找,一般情況下該參數可定為-1,表示從List1(0)即第一項開始向後迴圈尋找,lParam則傳進欲搜尋的字串(必須採用值傳遞)。

具體的代碼和運行畫面與後面的例4合并在一起示範。

 

例4、為ListBox添加水平捲軸

在VB中,列表框控制項僅提供垂直捲軸,沒有設定水平捲軸的能力,當某些項目的文本寬度較長時,超出列表框寬度部分的文本就無法顯示出來,因此,很有必要為ListBox添加一個水平捲軸來方便操作。

為添加水平捲軸,只需發一條LB_SETHORIZONTALEXTENT(&H194)訊息給列表框即可,發送訊息時,wParam為捲軸的長度(以像素為單位,可通過計算得出準確的長度,也可隨便給一個大於最大文本寬度的數字,如本例的250),lParam無用。

下面是例3和例4合并在一起的代碼和運行畫面:

Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Public Const LB_FINDSTRING = &H18F

Public Const LB_SETHORIZONTALEXTENT = &H194

Private Sub Form_Load()

List1.AddItem "軟體"

List1.AddItem "電腦遊戲"

List1.AddItem "電視機"

List1.AddItem "電視台"

List1.AddItem "電腦"

List1.AddItem "電腦遊戲軟體"

'下一句為列表框添加水平捲軸

SendMessage List1.hwnd, LB_SETHORIZONTALEXTENT, 250, 0

End Sub

Private Sub Text1_Change()

'注意!當lParam傳入的是字串時,必須用ByVal傳遞

List1.ListIndex = SendMessage(List1.hwnd, LB_FINDSTRING, -1, ByVal Text1.Text)

End Sub

通過上面幾個例子,想必您已經對SendMessage函數的強大功能有了初步的瞭解,事實上利用該函數我們還可以完成更多更好的任務,如控制文字框的自動滾屏、實現文字編輯過程中的Undo功能、操縱應用程式的表單控制功能表等等,感興趣的讀者請參閱有關Windows API的資料。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.