SendMessage函數的常用消息及其應用

  文本框控件通常用於輸入和編輯文字。它屬於標准 Windows 編輯控件的一個子類,所以它支持所有
編輯控件消息。這兒講述的技術也適用於由其他廠商設計的,以Windows編輯控件類為基礎的其他控件。

  函數原型:

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

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

1.hWnd:
  對象的句柄。希望將消息傳送給哪個對象,就把該對象的句柄作為實參傳送,在 VB 中可以簡單地
用「對象.hWnd」獲得某個對象的句柄,如 Text1.hWnd和 Form1.hWnd分別可以得到 Text1和Form1的句
柄。它是一個長整型數。Windows給每個控件一個編號,這個編號就稱為窗口句柄。有了這個句柄,我們
就可告訴 Windows 我們要控制哪個控件,所以這個句柄在 API 調用中至關重要。VB 的大多數控件都包
括hwnd屬性,如下拉框、TreeView等,窗體也有這個屬性。但也有一些控件沒有這個屬性,如標簽控件。
沒有這個屬性就無法利用Windows API函數,但可以節省系統資源。
 
2.wMsg:
  被發送的消息。根據具體需求和不同的對象,將不同的消息作為實參傳送,以產生預期的動作。使
SendMessage 傳遞消息,大多是為了完成以下幾個工作: 
  ①設置控件的一些選項,象我們要使用的CB_SETDROPPEDWIDTH的就屬於這種情況。盡管VB的每個控
件都提供了許多屬性,但仍然有許多控件的選項沒有包括在其中。而這些選項中的大多數都可以利用該
函數進行設置。
  ②獲得控件的一些設置。同上一種情況相反,有時我們需要獲得控件的一些設置,相當於讀取屬性。
例如,如果想知道一個下拉框的下拉部分的寬度是多少,就可以向控件發送CB_GETDROPPEDWIDTH消息。
對於這種情況,SendMessage函數的返回值就是結果。 
  ③執行一定的操作。例如,我們要在下拉框中尋找是否有「ABC」這個字符串,當然,我們可以編寫
一個循環,逐條比較看是否存在這樣的字符串。如果使用API,我們只需要向下拉框發送CB_FINDSTRING
消息,這條消息就會自動進行查找工作並返回結果。 
  ④模擬用戶操作。我們有時希望模擬用戶的操作,比如關閉其他應用程序的窗口。其實只要我們能知
道那個窗口的句柄,我們就可以發送WM_CLOSE消息給那個窗口,窗口接受到這條消息就會關閉,如同用戶
關閉窗口一樣。 

3.wParam、4.lParam:
  附加的消息信息。這兩個是可選的參數,用來提供關於wMsg消息更多的信息,不同的wMsg可能使用這
兩個參數中的0、1或2個,如果不需要哪個附加參數,則將實參賦為NULL(在VB中賦為0)。
  lParam定義為Any類型。指定 Any類型可禁止VB進行類型檢查,從而允許將任意數據類型傳遞給該過
程。由於每條消息對參數的類型和傳遞方式的要求都不同:有的可能要求為Long型,有的可能要求為自定
義類型;大多數要求按傳值方式傳遞,但也有一些要求按傳地址方式。為了滿足各種要求,我們將這個參
數定義為Any類型。比如,我們要傳遞一個Long型變量lData。如果消息要求傳地址方式傳遞,可以使用: 
  SendMessage ……, lData 
  而如果要求傳值方式傳遞,則使用 
  SendMessage ……, ByVal lData 
  如果傳遞常數,我們則需要使用類型後綴來指定常數的類型,比如"0&",表示Long型的常數0,如 
  SendMessage ……, ByVal 0& 
  我們也可以使用類型轉換函數CLng將常數指定為Long型,如CLng(0)。

  程序中,有時定義 lParam As Any,有時定義 ByVal lParam As String。這是為什麼呢?對於
SendMessage函數,lParam的使用是很靈活的,在一般情況下,lParam是一個指針,它指向的數據類型
有三種:長整形、自定義數據結構類型、字符串類型。對於前兩種類型,需要將 lParam定義為 lParam
As Any,從而將 lParam 數據的指針傳遞到 SendMessage 函數。對於字符串類型,則需要定義 Byval
lParam As String,因為字符串類型數據不同,只有定義 ByVal,得到的才是字符串的指針,如果沒有
ByVal,得到的將是指向字符串指針的指針。另外對於少數的消息來說,SendMessage 函數需要的只是
lParam 本身的值,這時就需要將 lParam定義為 Byval lParam As Long,或者在程序調用時在 lParam
之前加 ByVal。

  當用戶在編輯控件上進行各種操作時,其父窗口將收到 WM_COMMAND 通知消息,lParam帶控件句柄
(hWnd),同時 wParam 的低16位帶控件的 ID,高16位帶有如下表的消息代碼:

常用編輯控件消息:
EC_LEFTMARGIN(&H1)                    EC_USEFONTINF 設置左邊距時使用
EC_RIGHTMARGIN                        EC_USEFONTINF 設置右邊距時使用
EC_USEFONTINF,O,邊距                  設置編輯控件的左、右邊距,當wParam含EC_LEFTMARGIN時在lParam的低16位指定左邊距點數,當wParam含EC_RIGHTMARGIN時在lParam的高16位指定右邊距點數。當指定wParam為EC_USEFONTINFO時,則用當前字體的字符"A"的寬度指定右邊距和字符"C"的寬度指定左邊距lParam被忽略。

EM_CHARFROMPOS(&HD7=215),0,           取得編輯控件中指定位置的字符相對於文本頭部的偏移量。使用本操作應先在第4個參數的高16位指定行號,低16位指定列號(或一個POINTAPI結構),行列是按編輯控件的客戶區左上角為原點(0,0)計算的。如果指定的位置超出控件客戶區則返回-1
EM_CANUNDO(&HC6=198),0,0             決定前一次編輯操作是否能夠撤消:檢測控件撤消緩沖區是否為空,通常控件把最後一次在控件的編輯操作保存在一個撤消緩沖區,如果緩沖區非空則返回TRUE表示上次操作可以撤消,否則返回FALSE,應用程序可以利用該返回值來禁止或允許菜單或工具條的"撤消"項。
EM_EMPTYUNDOBUFFER(&HCD=205 ),0,0     清除控件的撤消緩沖區,使其不能撤消前一次編輯操作 
EM_FMTLINES(&HC8=200)                決定是否在取回的文本宇串中包含軟回車字符
EM_GETFIRSTVISIBLEINE(&HCE=206),0,0   獲得文本控件中處於可見位置的最頂部的文本所在的行號

EM_GETLINE(&HC4=196 ),行號,ByVal 變量 獲取編輯控件某一行的內容,變量須預先賦空格
EM_GETLINECOUNT(&HBA=186,0,0          獲取編輯控件的總行數
EM_GETMODIFY(&HB8=184),0,0           判斷編輯控件的內容是否已發生變化,返回TRUE則控件文本已被修改,返回FALSE則未變。 
EM_GETPASSWORDCHAR( ),0,0            獲取編輯控件的密碼字符,返回NULL表示沒有字符
EM_GETRECT(&HB2=178),0,結構          獲取編輯控件的格式化矩形
EM_GETTHUMB(&HBE=190),0,0             取得多行文本編輯控件的滾動框的當前位置(注意:是象素值)
EM_GETSEL(&HB0=176),0,變量            獲取光標位置(以字節數表示),或:(緩沖區起點,緩沖區終點)取得編輯控件中選定內容的范圍,返回值中低16位為起點,高16位為終點
EM_GETHANDLE(&HBD=189),0,0            取得文本緩沖區
EM_GETWORDBREAKPROC(&HD1=209),0,0     取得整字換行回調函數EditWordBreakProc指針
EM_GETLIMITTEXT(WM_USER+37=1061),0,0  獲取一個編輯控件中文本的最大長度 
EM_GETMARGINS( ),0,0                  獲取編輯控件的左、右邊距,返回值低16位為左邊距,高16位為右邊距(不得用於NT3.51) 
EM_LIMITTEXT(&HC5=197),最大值,0       設置編輯控件中的文本長度
EM_SCROLLCARET(&HB7=183),0,0          把可見范圍移至光標處
EM_LINEFROMCHAR(&HC9=201),偏移值,0    獲取指定位置(或:-1,0 表示光標位置)所在的行號
EM_LINEINDEX(&HBB=187),行號,0         獲取指定行(或:-1,0 表示光標所在行)首字符在文本中的位置(以字節數表示)
EM_LINELENGTH(&hC1=193),偏移值,0      獲取指定位置所在行(或:-1,0 表示光標所在行)的文本長度(以字節數表示)
EM_POSFROMCHARPOINT,結構地址,偏移值   取得指定字符位置的行列號,偏移值是字符相對於文本頭部的偏移。
EM_LINESCROLL(&HB6=182),列數,行數     指定行數的文本水平滾動,每次滾動N列
EM_EXGETSEL(&H434=1076)   

EM_EXSETSEL(&H437=1079),0,結構        RichEdit控件設置文本選定范圍,參閱 EM_SETSEL 消息,結構是指 CHARRANGE 結構
EM_PASTESPECIAL(&H440=1088),2(1),1    RichEdit控件粘貼剪貼板中的位圖(或文本)
EM_FINDTEXT(&H738=1080)               RichEdit控件正文搜索操作
EM_FINDTEXTEX(&H44F=1103)             同上
EM_SETTEXTEX(&H461=1121)              RichEdit控件正文替換/插入操作
EM_SETTARGETDEVICE, GetDC(RichText.hWnd), RichText.Width / 15)設置 RichTextBox 自動換行,後續代碼是:RichText.RightMargin = iif(RichText.RightMargin = 0,1,0)
EM_SETTARGETDEVICE, 0, 1              設置 RichTextBox 不自動換行

EM_POSFROMCHAR(&HD6或&H426)           判斷指定字符在編輯控件的位置(用於NT3.51) 
EM_SCROLL(&HB5=181),*,0               文本垂直滾動。第三個參數*控制滾動方向:SB_LINEDOWN(1)向下滾動一行,SB_LINEUP(0)向上滾動一行,SB_PAGEDOWN(3)向下滾動一頁,SB_PAGEUP(2)向上滾動一頁。
EM_REPLACESEL(&HC2=194),1(0),字符串   用指定字符串替換編輯控件中的當前選定內容,如果第三個參數wParam為1,則本次操作允許撤消,0禁止撤消。字符串可用傳值方式,也可用傳址方式(例:SendMessage Text1.hwnd, EM_REPLACESEL, 0, Text2.Text '這是傳值方式)
EM_SETSEL(&HB1=177),起點,終點        設置編輯控件中文本選定內容范圍(或設置光標位置),該范圍被反相顯示,用於為復制、替換、粘貼、剪切、刪除等編輯功能指定范圍,光標將被移至指定的終點後面。還可使用指定相同起點和終點來移動光標而不是選定范圍。當指定的起點等於0和終點等於-1時,文本全部被選中,此法常用在清空編輯控件。當指定的起點等於-2和終點等於-1時,全文均不選,光標移至文本未端,此法常用在文本未端追加內容。注意:當控件沒有輸入焦點時,本操作將會失敗,一般在執行本操作前都應調用SetFocus先取得輸入焦點。
EM_UNDO(&HC7=199),0,0                 撤消前一次編輯操作,當重復發送本消息,控件將在撤消和恢復中來回切換
EM_SETCHARFORMAT(&H444)               改變選定文本的顏色
EM_SETHANDLE(&HBC=188),緩沖區指針,0  為編輯控件指定新的文本緩沖區。此操作僅適用對話框創建帶DS_LOCALEDIT風格的控件。
EM_SETLIMITTEXT,長度(字節),0          設置編輯控件中的文本最大長度(不得用於NT3.51)
EM_SETMARGINS(&HD3=211)               設置編輯控件的左、右邊距(不得用於NT3.51)
EM_SETMODIFY(&HB9=185),1(0),0         設置或清除一個編輯控件的修改標志
EM_SETPASSWORDCHAR(&HCC=204),字符,0   指定控件用來顯示密碼的字符,缺省為"*"。當第三個參數wParam為0時,本操作將清除控件的ES_PASSWORD風格,並按實際字符顯示。
EM_SETREADONLY(&HCF=207),1(0),0       決定是否將編輯控件設為只讀,同時決定控件的ES_READONLY風格
EM_SETRECT(&HB3=179),0(或RECT),結構地址      為一個編輯控件設置格式化矩形
EM_SETRECTNP(&HB4=180),0(或RECT),結構地址    為一個編輯控件設置格式化矩形,只是控件此時不會重畫

EN_CHANGE(&H300=768)                  編輯控件的內容發生改變。與EN_UPDATE不同,該消息是在編輯框顯示的正文被刷新後才發出的。 
EN_ERRSPACE(&H500=1280)               任何時候只要由於內存不足以完成一項編輯操作 
EN_HSCROLL(&H601=1537)                用戶單擊了編輯控件的水平滾動條。注意:這條消息是在控件更新顯示之前發送出去的。
EN_VSCROLL(&H602=1538)                用戶單擊了編輯控件的垂直滾動條。注意:這條消息是在控件更新顯示之前發送出去的。
EN_KILLFOCUS(&H200=512)               編輯控件失去了輸入焦點
EN_SETFOCUS(&H100=256)                編輯控件獲得了輸入焦點
EN_UPDATE(&H400=1024)                 控件准備顯示改變了的正文時發送該消息。它與EN_CHANGE通知消息相似,只是它發生於更新文本顯示出來之前。 
EN_MAXTEXT(&H501=1281)                用戶輸人的文字數超出由EM_LIMITTEXT消息規定的界限,或超出由VB Maxlength屬性規定的界限,就會發送這條消息 。此外,倘若不允許自動進行水平滾動,同時插入點要超出控件的寬度;或者不允許自動垂直滾動,同時插入點要超出控件的高度,那麼也會觸發這條消息。在沒有ES_AUTOHSCROLL或ES_AUTOVSCROLL的編輯框中,當正文超出了編輯框的邊框時也會發出該消息。 

編輯風格消息:
ES_MULTILINE                         指定編輯控件能否進行多行文本編輯,若多行編輯器不指定ES_AUTOHSCROLL風格,則會自動換行,用戶每按一次Enter,在當前光標處輸入一個回車換行符(0Dh,0Ah),文本增加一行。若不指定ES_AUTOVSCROLL,則多行編輯器會在窗口中正文裝滿時發出警告聲響。
ES_LEFT                               文本顯示居左。
ES_CENTER                            文本顯示居中。
ES_RIGHT                             文本顯示居右。
ES_LOWERCASE                         把用戶輸入的字母統統轉換成小寫字母。
ES_UPPERCASE                         把用戶輸入的字母統統轉換成大寫字母。
ES_OEMCONVERT                        把輸入的文本從ANSI碼轉換成OEM碼,然後又轉換成ANSI碼,目的是保證函數AnsiToOem的正確調用。這在編輯框中包含文件名時是很有用的。
ES_AUTOHSCROLL(自動增加水平滾動條?) 當用戶在行尾鍵入一個字符時,正文將自動向右滾動10個字符,當用戶按回車鍵時,正文總是滾向左邊。
ES_AUTOVSCROLL                       當用戶在最後一個可見行按回車鍵時,正文向上滾動一頁。
ES_NUMBER                            只接收數碼輸入,其它字符輸入一律無效。
ES_NOHIDESEL(&H100=256)               當編輯框失去輸入焦點時,選中的文本將隱藏,正文中的選擇保持不變。缺省時正文中的選擇將失效,當獲得輸入焦點後才又顯示出來。
ES_READONLY                          將編輯框設置成只讀的。
ES_PASSWORD(&H20=32)                  使所有鍵入的字符都用"*"來顯示。
ES_WANTRETURN                        使多行編輯器接收回車鍵輸入並換行。如果不指定該風格,按回車鍵會選擇缺省的命令按鈕,這往往會導致對話框的關閉。

列表框操作:
LB_FINDSTRING(&H18F=399),-1,ByVal 字串   查找列表項的字符串,返回值=字符串所在的列表項的索引。-1表示從第0行開始查找,如果改為一個有效的列表項索引值,將從該行開始查找。
LB_ITEMFROMPOINT(&H1A9=425)              獲取光標所在的列表項的索引
LB_SETHORIZONTALEXTENT(&H194=404),長度,0 設置列表框的橫向滾動條以及滾動長度,長度為象素值

組合框操作:
CB_SHOWDROPDOWN(&H14F),1(0),0         打開(關閉)組合框的列表

TVM_SETBKCOLOR(&H1100+29=4381)        設置擴展樹型列表控件的背景色(TVM開頭的常數)

常用窗口消息:
WM_GETFONT(&H31=49)                   得到當前控件繪制文本的字體(的句柄)
WM_GETTEXT(&HD=13),變量長度,變量       取得窗體的標題,變量須預先賦空字串(chr(0)),變量長度=Len(變量)
WM_SETTEXT(&HC=12),0,ByVal "字串"     設置窗體的標題
WM_NCLBUTTONDOWN(&HA1=161),2,0        在非客戶區,即邊框及標題欄上(假如定義的是一個組件,則非客戶區包括Form等)按下鼠標左鍵;
WM_LBUTTONDOWN(&H201=513),2,0         在客戶區,也就是除邊框及標題欄以外按下鼠標左鍵
WM_VSCROLL(&H115=277),&H10000*p+SB_THUMBPOSITION(&H4),0 同步滾動文本,p是位置改變量
WM_PAINT
WM_USER(&H400=1024)

WM_CUT(&H300=768),0,0                 剪切
WM_COPY(&H301=769)),0,0               復制
WM_PASTE(&H302=770)),0,0              粘貼
WM_CLEAR(&H303=771)),0,0              刪除
WM_UNDO(&H304=772)),0,0               撤消

按紐消息:
BM_SETSTYLE(&HF4)                   設置按紐樣式
BS_RADIOBUTTON(&H4)                 收音機旋紐式的按紐,是 BM_SETSTYLE 使用的參數

 

作者:一江秋水      發表時間:2007-8-27 10:17:00

 1樓  

SendMessage函數應用(一)
    在Windows系統的很多消息中,有一些不僅僅是提供一個窗口消息那麼簡單。它們可以控制窗口的
動作和屬性。下面向大家介紹SendMessage函數在擴充列表(ListBox)控件功能方面的應用。 
  在 Windows 中,有一系列的以 LB_ 開頭的列表消息,這裡介紹的就是利用LB消息控制的ListBox
的應用。

1、使列表中光標移動到不同的列表項上有不同的提示(ToolTip)
  在列表框控件中有一個 ToolTipText 屬性,該屬性決定了當光標在列表框上移動時出現的提示文
字。但是如何使得當光標在不同的列表項上移動時的提示文字也不同呢?問題的關鍵是要知道在光標移
動時光標所在的列表項的索引,使用SendMessage函數發送 LB_ITEMFROMPOINT 消息就可以獲得。
  在 Form1 中加入一個 ListBox 控件,運行程序,當光標在列表中移動時,可以看到根據光標所在
的不同的列表項,提示文字也不相同。代碼如下(我已試驗成功):

Const LB_ITEMFROMPOINT = &H1A9

Private Sub Form_Load()
Dim ZXS As Long
Drive1.Drive = "G:": Dir1.Path = "G:\一江秋水的文檔"
Combo1.Text = Combo1.List(0)
ZXS = SendMessage(Text1.hwnd, 186, 0, 0)
Label1.Caption = "共 " & ZXS & " 行," & Len(Text1.Text) & " 字"
For i = 1 To 200: List1.AddItem Str(i) + " 列表框試驗項目": Next
End Sub

Private Sub List1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim lXPoint As Long, lYPoint As Long, lIndex As Long
If Button = 0 Then '確定在移動鼠標的同時沒有按下功能鍵或者鼠標鍵
  lXPoint = CLng(X / Screen.TwipsPerPixelX) '獲得光標的位置,以像素為單位
  lYPoint = CLng(Y / Screen.TwipsPerPixelY)
  With List1
    lIndex = SendMessage(.hwnd, LB_ITEMFROMPOINT, 0, ByVal ((lYPoint * 65536) + lXPoint)) '獲得光標所在的標題行的索引
    If lIndex < .ListCount Then .ToolTipText = .List(lIndex) Else .ToolTipText = ""
  End With
End If
End Sub

2、向列表中加入橫向滾動條使得可以瀏覽長列表項
當向列表中加入的列表項超出了列表的顯示范圍後,列表並不會出現橫向滾動條讓你可以通過滾動來瀏覽
項目的全部內容。利用 LB_SETHORIZONTALEXTENT 消息可以設置列表框的橫向滾動條以及滾動長度。
  在 Form1 中加入一個 ListBox 控件,運行程序,可以看到列表中出現了橫向滾動條,而且滾動范圍正好
是列表項的長度。代碼如下(我已試驗成功):

Option Explicit

Private Type RECT
  Left As Long
  Top As Long
  Right As Long
  Bottom As Long
End Type

Private Declare Function DrawText Lib "user32" Alias "DrawTextA" (ByVal hdc As Long, _
  ByVal lpStr As String, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long
Private 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 LB_SETHORIZONTALEXTENT = &H194
Const DT_CALCRECT = &H400

Public Function ListTextWidth(ByRef lstThis As ListBox) As Long '獲取最長項目的象素長度值
Dim i As Long
Dim tR As RECT
Dim lW As Long
Dim lWidth As Long
Dim lHDC As Long
With lstThis.Parent.Font
  .Name = lstThis.Font.Name
  .Size = lstThis.Font.Size
  .Bold = lstThis.Font.Bold
  .Italic = lstThis.Font.Italic
End With
lHDC = lstThis.Parent.hdc
For i = 0 To lstThis.ListCount - 1 '遍歷所有的列表項以找到最長的項
  DrawText lHDC, lstThis.List(i), -1, tR, DT_CALCRECT
  lW = tR.Right - tR.Left + 8
  If lW > lWidth Then lWidth = lW
Next 
ListTextWidth = lWidth '返回最長列表項的長度(像素)
End Function

Private Sub Form_Load()
Dim astr As String
Dim i
Dim l As Long
For i = 1 To 10: astr = Str(i) + "這是真正的長項目" + astr: List1.AddItem astr: Next '加入一個很大的列表項
L = ListTextWidth(List1)
SendMessage List1.hwnd, LB_SETHORIZONTALEXTENT, L, 0
End Sub

3、使列表框可以響應用戶擊鍵
有時我們需要列表根據用戶的敲入字符串自動調整列表的ListIndex到最接近的列表項,就象VB中動態
響應用戶輸入控件屬性的編輯器一樣。問題的關鍵是如何在列表中查找含有指定字符串的列表項,使用
LB_FINDSTRING消息可以在列表中查找指定字符串。
  在 Form1 中加入一個 TextBox 控件和一個 ListBox 控件,並將 List1的 Sorted 屬性設置為True。
運行程序,在文本框中敲入字符,例如"av" "gm",列表就會高亮顯示相近的列表項。代碼如下(已成功):

Const LB_FINDSTRING = &H18F
Dim st As String

Private Sub Form_Load()
For i = 65 To 90: For j = 65 To 90: List1.AddItem Chr(i) + Chr(j): Next: Next '向List中加入列表項
End Sub

Private Sub Text1_KeyPress(KeyAscii As Integer)
If Len(st) > 1 Then st = ""
If ((KeyAscii > 64 And KeyAscii < 91) Or (KeyAscii > 96 Or KeyAscii < 123)) Then
  Dim L As Long
  st = st + Chr(KeyAscii)
  L = SendMessage(List1.hwnd, LB_FINDSTRING, -1, ByVal st)'注意!當參數4傳入的是字符串時,必須用ByVal傳遞
  If L Then List1.ListIndex = L
End If
End Sub

4.在列表框中查找匹配的項目
   在Win95風格的幫助系統中一般都有一個「索引」頁,索引頁含有一個文本框和一個列表框,當用戶
在文本框中輸入文字時,下拉列表會動態地顯示與文本框中文字最匹配的項目,為用戶提供了最大的方
便。這種效果在應用程序的幫助系統中很容易實現(只要按照 Win95幫助系統的正常制作過程制作就可
以實現),如果想在應用程序的其它地方實現這種特性就需費一番心思了。
   而使用SendMessage函數實現上述特性則非常簡單,甚至只需一條語句就足夠了,那就是在文本框的
Change事件中給列表框發一條LB_FINDSTRING(&H18F)消息,該消息告訴列表框在列表中查找匹配的項
目。
   在發LB_FINDSTRING消息時,wParam參數代表從列表框的哪一個項目後面開始查找,一般情況下該參
數可定為-1,表示從List1(0)即第一項開始向後循環查找,lParam則傳進欲搜索的字符串(必須采用值
傳遞)。
   具體的代碼和運行畫面與下面的 5. 合並在一起演示。

 

作者:一江秋水      發表時間:2007-8-27 10:17:00

 2樓  

5.為ListBox添加水平滾動條
   在VB中,列表框控件僅提供垂直滾動條,沒有設置水平滾動條的能力,當某些項目的文本寬度較長
時,超出列表框寬度部分的文本就無法顯示出來,因此,很有必要為ListBox添加一個水平滾動條來方
便操作。
   為添加水平滾動條,只需發一條 LB_SETHORIZONTALEXTENT(&H194) 消息給列表框即可。發送消息
時,wParam為滾動條的長度(以像素為單位,可通過計算得出准確的長度,上面例2 就是如此的,也可
隨便給一個數字,如本例的 250),lParam無用。代碼如下(已試驗成功):

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,&H194,250,0 '為列表框添加水平滾動條
End Sub

Private Sub Text1_Change()
'注意!當lParam傳入的是字符串時,必須用ByVal傳遞
List1.ListIndex = SendMessage(List1.hwnd,LB_FINDSTRING,-1,ByVal Text1.Text)
End Sub

6.在API文本瀏覽器裡,當我們在搜索欄輸入任意字母,「可用項」裡以該字母開頭的項目以高亮顯
示以引起我們注意該項是不是我們所需的。象這樣的功能一切提供搜索選項的程序都應該具備。以下例
子采用SendMessage函數實現這一技術。

Const LB_FINDSTRING = &H18F 

Private Sub Form_Load()
Dim i As Integer
For i = Asc("A") To Asc("Z") '給列表框添加26個字母(大寫)
List1.AddItem Chr$(i)
Next
Text1 = "" '令文本框為空
End Sub

Private Sub Text1_KeyPress(KeyAscii As Integer)
Text1 = "" '按下任意鍵則令原內容消失
Text1.SelLength = 1 '限制長度
Text1.SelText = Chr(KeyAscii) '顯示鍵盤符號
KeyAscii = 0 '禁止響應
'ListBox中的項目文本若與文本框的一致則選中(高亮)
List1.ListIndex = SendMessage(List1.hwnd, LB_FINDSTRING, -1, ByVal CStr(Text1.Text))'經試,不需CStr函數 
End Sub

  以上程序適用於單項目為多個字母的查詢,但必須注意,在TextBox的KeyPress事件中要作相應的
改動

SendMessage函數應用(二) 
  介紹如何利用消息函數來擴展樹型列表 TreeView 控件的功能。相信對於樹型列表控件大家十分的
熟悉,典型的應用就是 Windows 資源管理器中的目錄列表。而在VB中,樹型列表控件包含在Microsoft
Windows Common Control 6.0(也可能是5.0,視你的VB或者系統版本而定)中。在Windows API 中,
有一系列的以 TVM_ 開頭的消息值,這些消息就是擴展樹型列表控件所特定的消息值,下面向大家介紹
其中的一些應用

1、設置樹型列表控件的背景顏色
 首先做如下的定義:

Const TV_FIRST = &H1100
Const TVM_SETBKCOLOR = TV_FIRST + 29(4381)
  
  調用:
Call SendMessage(TreeView1.hwnd, 4381, 0,ByVal RGB(255, 0, 0))

  上面的SendMessage調用將TreeView1的背景顏色設置為紅色。
  大家可能注意到了。在上面的 Sendmessage 函數定義中,我們將 lParam 定義為 ByVal lParam
As Long,而不是象前面的那些范例那樣定義為 Any 或者 String 類型,關於這個問題,我會在最後的
一章中做介紹。

2、設置樹型列表控件標題行高度
  TVM_SETITEMHEIGHT 消息設定控件的標題行的高度,該消息的定義及調用方法如下:

Const TV_FIRST = &H1100
Const TVM_SETITEMHEIGHT = TV_FIRST + 27

Call SendMessage(TreeView1.hwnd, TVM_SETITEMHEIGHT, 60, 0) '將TreeView1標題行高度設置到60像素高

 

作者:一江秋水      發表時間:2007-8-27 10:18:00

 3樓  

3、為樹型列表控件中不同的標題行設置不同的提示
 介紹如何為樹型列表控件中的每一個標題設置不同的提示。同 ListBox控件不通,樹型列表控件中
並沒有根據光標位置獲得標題行索引的消息,我們需要另外想辦法。在TVM類消息中有一個TVM_HITTEST
消息,發送該消息可以檢測控件表面上的某一點,如果該點位於一個標題上,則返回該標題的句柄。而
利用 TVM_GETITEM消息,則可以根據標題句柄返回該標題行的文本。所以結合利用這兩個消息可以獲取
光標所在標題行的標題文本。具體的范例代碼如下:

Option Explicit
Private Type TPoint
x As Long
y As Long
End Type

Private Type TVHITTESTINFO
pt As TPoint
flags As Long

hItem As Long
End Type

Private Type TVITEM
mask As Long
HTreeItem As Long
state As Long
stateMask As Long
pszText As Long
cchTextMax As Long
iImage As Long
iSelectedImage As Long
cChildren As Long
lParam As Long
End Type

Const TV_FIRST = &H1100
Const TVM_HITTEST = TV_FIRST + 17
Const TVM_GETITEM = TV_FIRST + 12
Const TVHT_ONITEMLABEL = &H4
Const TVIF_TEXT = &H1
Const GMEM_FIXED = &H0

Private Declare Function SendMessageRef Lib "user32" Alias "SendMessageA" (ByVal hwnd As _
  Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As _
  String, ByVal Source As Long, ByVal Length As Long)
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes _
  As Long) As Long
Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long

Dim hItemPrv As Long

Private Sub Form_Load()
Dim ndX As Node
  '加入若干Item
  Set ndX = TreeView1.Nodes.Add(, , "R", "Root")
  Set ndX = TreeView1.Nodes.Add("R", tvwChild, "Key1", "Node1")
  Set ndX = TreeView1.Nodes.Add("Key1", tvwChild, "SubKey1", "SubNode1")
  Set ndX = TreeView1.Nodes.Add("SubKey1", tvwChild, "SubKeys1", "SubNode1")
  Set ndX = TreeView1.Nodes.Add("Key1", tvwChild, "SubKey2", "SubNode2")
  Set ndX = TreeView1.Nodes.Add("Key1", tvwChild, "SubKey3", "SubNode3")
  Set ndX = TreeView1.Nodes.Add("Key1", tvwChild, "SubKey4", "SubNode4")
End Sub

Private Sub TreeView1_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
  Dim ptA As TPoint
  Dim tf As TVHITTESTINFO
  Dim tv As TVITEM
  Dim hStr As Long
  Dim hItem As Long
  Dim astr As String * 1024
  Dim bstr
  On Error GoTo errLab

  '獲得當前光標所在的位置坐標
  ptA.x = Int(x / Screen.TwipsPerPixelX)
  ptA.y = Int(y / Screen.TwipsPerPixelY)
  tf.pt = ptA
  tf.flags = TVHT_ONITEMLABEL

  '獲得光標所在的Item的句柄
  hItem = SendMessageRef(TreeView1.hwnd, TVM_HITTEST, 0, tf)
  '如果未獲得句柄或者同上一次是同一個Item的句柄則退出
  If ((hItem <= 0) Or (hItem = hItemPrv)) Then Exit Sub

  hItemPrv = hItem
  '分配一定的內存空間用以存儲Item的標題
  hStr = GlobalAlloc(GMEM_FIXED, 1024)

  If hStr > 0 Then
  tv.mask = TVIF_TEXT '獲取標題文本
  tv.HTreeItem = hItem 'Item句柄
  tv.pszText = hStr
  tv.cchTextMax = 1023
  '發送TVM_GETITEM獲得標題文本
  Call SendMessageRef(TreeView1.hwnd, TVM_GETITEM, 0, tv)
  '將標題文本拷貝到字符串astr中
  CopyMemory astr, hStr, 1024
  bstr = Left$(astr, (InStr(astr, Chr(0)) - 1))
  TreeView1.ToolTipText = bstr
  '釋放分配的內存空間
  GlobalFree hStr
  End If
  Exit Sub
  errLab:
  Resume Next
  End Sub

運行上面的程序,當光標在 TreeView1上面移動時,TreeView1的 ToolTips就會根據光標所在的不
同標題行而變動。

 
SendMessage函數應用(三) 
  介紹關於RichTextBox(簡稱RTF)控件的消息和ListView控件的消息控制。

1.在Windows消息中,以EM_開頭的消息是專門控制TextBox類控件和RTF類控件的。下面介紹的是如何利
用 EM_ 消息實現向 RichTextBox 中粘貼文本和位圖。在 EM_消息中,有一個 EM_PASTESPECIAL 消息
可以從剪貼板中獲取文本或者位圖類數據並拷貝到 RTF 上。
  運行程序,點擊Command1,可以將剪貼板中的數據(位圖或者文本)拷貝到RichTextBox1上。
  在 EM_PASTESPECIAL 消息中,wParam 定義剪貼板數據類型,lParam 定義一個 repastespecial
類型的數據,其中的 dwAspect 說明數據以何種方式顯示到 RTF 對象上,如果是 DVASPECT_CONTENT,
則將整個數據顯示在 RTF 上,如果是 DVASPECT_ICON ,則只在 RTF 上顯示一個圖標。
  經試,repastespecial 格式沒有作用,因此參數4設為0即可。

Private Type repastespecial
  dwAspect As Long '顯示方式
  dwParam As Long
End Type

Const WM_USER = &H400
Const EM_PASTESPECIAL = 1088
Const CF_BITMAP = 2
Const CF_TEXT = 1
Const DVASPECT_CONTENT = 1
Const DVASPECT_ICON = 4

Private Sub Command1_Click()
Dim re As repastespecial
re.dwAspect = DVASPECT_CONTENT
If Clipboard.GetFormat(vbCFText) Then ''剪貼板中為文本信息
Call SendMessage(RichTextBox1.hwnd, EM_PASTESPECIAL, CF_TEXT, re)
ElseIf Clipboard.GetFormat(vbCFBitmap) Then ''剪貼板中為位圖信息
Call SendMessage(RichTextBox1.hwnd, EM_PASTESPECIAL, CF_BITMAP, re)
End If
End Sub

 

作者:一江秋水      發表時間:2007-8-27 10:19:00

 4樓  

2.ListView控件也是Windows界面開發中重要的控件,典型的應用就是Windows資源管理器中的文件列
表。而在VB中,ListView控件包含在Microsoft Windows Common Control 6.0(也可能是5.0,視你的
VB或者系統版本而定)中。在 Windows API 中,有一系列的以 LVM_開頭的消息值,這些消息就是擴展
ListView控件所特定的消息值,下面的范例介紹如何通過LVM_消息設置ListView控件中圖標的間距。范
例如下:

Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type

Const LVM_FIRST = &H1000
Const LVM_SETWORKAREA = LVM_FIRST + 65
Const LVM_SETICONSPACING = LVM_FIRST + 53

Private Sub Form_Load()
Dim xn As ListItem
Me.Show
ListView1.Width = 4500
ListView1.Height = 3000
ListView1.Refresh
Set xn = ListView1.ListItems.Add
xn.Text = "List1"
Set xn = ListView1.ListItems.Add
xn.Text = "List2"
Set xn = ListView1.ListItems.Add
xn.Text = "List3"
Set xn = ListView1.ListItems.Add
xn.Text = "List4"
Set xn = ListView1.ListItems.Add
xn.Text = "List5"
Set xn = ListView1.ListItems.Add
xn.Text = "List6"
ListView1.Refresh
Call SendMessage(ListView1.hwnd, LVM_SETICONSPACING, 0, ByVal (60 * 65536 + 190&))
End Sub

  要運行上面的程序,首先要確保ListView1的Arrange屬性為1,View屬性為0。在上面的程序中,我
們利用了 VM_SETICONSPACING 消息來控制圖標間距。其中SendMessage中的參數lParam定義圖標間距,
高位為縱向間距,低位為橫向間距,在上面的范例中,我們將圖標的縱向間距定義為60像素,橫向間距
定義為190像素。
  

SendMessage函數的應用(四) 
   
1,獲得光標位置和字符個數.
Cpos=SendMessage(text1.hwnd,187,-1,0)   '光標所在行的首字符在文本中的位置
Lpos=SendMessage(text1.hwnd,201,Cpos,0) '光標所在的行號
Line=SendMessage(text1.hwnd,193,Cpos,0) '這行的字符數.

2.獲取第N行的文本
Dim ST As String
ST = Space(110)'必須要事先賦空格
Line=SendMessage(text1.hwnd,196, N-1, ByVal ST 'ST返回獲取到的文本,Line返回文本的長度字節數

'下面的未成功
Dim str(256) As Byte, K As Integer
str(1)=1 '最大允許存放256個字符
K = SendMessage (Text1.hwnd,196,2,str(0)) '獲取第3行的數據放在str中
text1.text = StrConv(str,vbUnicode) '轉換為字符串後顯示
   
  說明:在調用SendMessage獲取第N行字符串時,lParam需要說明為字節數組,在調用完成後,再將
字節數組轉換為字符串;另外,調用前必須在lParam的前兩個字節指明允許存放的最大長度,其中第一
個字節為低位,第二個字節為高位,本例將高位(即str(1))置1.說明最大允許存放256個字符。
 
3.開關顯示器.

SendMessage Handle, WM_SYSCOMMAND, SC_MONITORPOWER, 0 '關閉顯示器.
SendMessage Handle, WM_SYSCOMMAND, SC_MONITORPOWER, -1 '打開顯示器

4.程序控制拉下或收起組合框的下拉列表
   一般情況下,為了拉下或收起組合框的下拉列表,需要用鍵盤或鼠標進行操作,而有時我們希望程
序運行的某個時刻自動拉出下拉列表(比如在一些演示程序中),為了實現這個目的,我們也只有借助
於SendMessage函數,方法是發一個CB_SHOWDROPDOWN(&H14F)消息給組合框。
   在發CB_SHOWDROPDOWN消息時,wParam參數決定了是拉下列表(=True)還是收起表(=False),
lParam無用(設為0)。
   為說明具體的使用方法,下面提供簡單的程序片段:

Const CB_SHOWDROPDOWN=&H14F

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

SendMessage Combol.hwnd,CB_SHOWDROPDOWN,True,0

   當需要收起組合框Combol的列表時,調用如下語句:

SendMessage Combol.hwnd,CB_SHOWDROPDOWNN,False,0


5. 返回控件中顯示的第一行的行號。

LineNo = SendMessageBynum(CTextBox.hwnd, EM_GETFIRSTVISIBLELINE, 0, 0) 
  
6.下面的函數能夠滾動控件,不過在滾動之前最好判斷控件的文本行數和能夠顯示的行數,以免滾動時
發生混亂。函數SendMessageBynum是SendMessage函數的安全聲明函數,其定義與SendMessage函數完全
相同,只是函數名不同。 

Function ScrollTextBox(CTextBox As TextBox, nVal As Long, Optional nVertical As _
  Boolean = True) As Long 
If nVertical Then 
 ScrollTextBox = SendMessageBynum(CTextBox.hwnd, EM_LINESCROLL, 0, nVal) 
Else 
 ScrollTextBox = SendMessageBynum(CTextBox.hwnd, EM_LINESCROLL, nVal, 0) 
End If 
End Function 

7.下面的函數將返回控件能顯示的行數:(經試,總是引起程序崩潰)

'獲取當前字體的矩形區域(即字體的高度與平均寬度等信息)
Private Declare Function GetTextMetrics Lib "gdi32" Alias "GetTextMetricsA" (ByVal hdc As Long, lpMetrics As TEXTMETRIC) As Long
Private Type TEXTMETRIC
  tmHeight As Long           '字符高度
  tmAscent As Long           '字符上部高度(基線以上)
  tmDescent As Long          '字符下部高度(基線以下)
  tmInternalLeading As Long  '由tmHeight定義的字符高度的頂部空間數目
  tmExternalLeading As Long  '加在兩行之間的空間數目
  tmAveCharWidth As Long     '平均字符寬度
  tmMaxCharWidth As Long     '最寬字符的寬度
  tmWeight As Long           '字體的粗細輕重程度
  tmOverhang As Long         '加入某些拼接字體上的附加高度
  tmDigitizedAspectX As Long '字體設計所針對的設備水平方向
  tmDigitizedAspectY As Long '字體設計所針對的設備垂直方向
  tmFirstChar As String      '為字體定義的第一個字符
  tmLastChar As String       '為字體定義的最後一個字符
  tmDefaultChar As String    '字體中所沒有字符的替代字符
  tmBreakChar As String      '用於拆字的字符
  tmItalic As Byte           '字體為斜體時非零
  tmUnderlined As Byte       '字體為下劃線時非零
  tmStruckOut As Byte        '字體被刪去時非零
  tmPitchAndFamily As Byte   '字體間距(低4位)和族(高4位)
  tmCharSet As Byte          '字體的字符集
End Type
Type RECT
  Left As Long
  Top As Long
  Right As Long
  bottom As Long
End Type
Public ST As String

Function GetVisibleLines(CTextBox As TextBox) As Long 
Dim rc As RECT  '以象素為單位
Dim tm As TEXTMETRIC
Dim hDC&, lfont&, oldfont& 
Dim di&, lc& 
lc = SendMessage(CTextBox.hwnd, EM_GETRECT, 0, rc) 
lfont = SendMessage(CTextBox.hwnd, WM_GETFONT, 0, 0) 
hDC = GetDC(CTextBox.hwnd) 
If lfont <> 0 Then oldfont = SelectObject(hDC, lfont) 
di = GetTextMetrics(hDC, tm) 
If lfont <> 0 Then lfont = SelectObject(hDC, oldfont) 
GetVisibleLines = (rc.bottom - rc.top) / tm.tmHeight 
di = ReleaseDC(CTextBox.hwnd, hDC) 
End Function

 

作者:一江秋水      發表時間:2007-8-27 10:20:00

 5樓  

8.設置控件的左邊距。 

Public Const EM_SETMARGINS& = &HD3 
Public Const EC_LEFTMARGIN& = &H1 

Function SetMargins(CTextBox As TextBox, nVal As Long) As Long 
SetMargins = SendMessageBynum(CTextBox.hwnd, EM_SETMARGINS, EC_LEFTMARGIN, nVal) 
End Function

9.利用SendMessage函數還可以實現一些有趣的效果:
  例如在按鈕的Click事件中加入如下語句:

SendMessage(Command1.hWnd,BM_SETSTYLE,BS_RADIOBUTTON,1)'BM_SETSTYLE = &HF4,BS_RADIOBUTTON = &H4

  運行後點擊按鈕,就可以把按鈕變成一個收音機按鈕(經試,變成一個圓孔,有點象單選按紐)。
  如要得到圓形或橢圓形按紐可使用另外2個API函數:

hdc=CreateEllipticRgn(3, 3, 25, 25) '試驗成功,這兩個函數也用於創建圓形窗體
SetWindowRgn Command1.hWnd, hdc, True
DeleteObject hdc

10.窗體操作
  
Public Const WM_SYSCOMMAND = &H112
Public Const SC_CLOSE = &HF060 '關閉窗體
Public Const SC_MINIMIZE = &HF020 '最小化窗體
Public Const SC_MAXIMIZE = &HF030 '最大化窗體
Public Const SC_RESTORE = &HF120 '恢復窗體大小
Public Const WM_SETTEXT = &HC '設置窗體的Caption
Public Const WM_GETTEXT = &HD '取得窗體的caption

Private Sub Command_Click(Index As Integer)
Dim S As String
S = String(80, Chr(0)) 
Select Case Index
 Case 0: SendMessage Me.hwnd, WM_GETTEXT, Len(S), ByVal S: Text1 = Left(S, InStr(S, Chr(0)) - 1) '讀出窗體的Caption
 Case 1: SendMessage Me.hwnd, WM_SETTEXT, 0, ByVal CStr(Text1.Text)'設置窗體的Caption,由於Text1.text屬於Variant類型,所以一定先要用CStr把它轉換成字符串
 Case 2: SendMessage Me.hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, ByVal 0&'窗體最大化
 Case 3: SendMessage Me.hwnd, WM_SYSCOMMAND, SC_MINIMIZE, ByVal 0&'窗體最小化
 Case 4: SendMessage Me.hwnd, WM_SYSCOMMAND, SC_RESTORE, ByVal 0&'窗體恢復原來的大小
 Case 5: SendMessage Me.hwnd, WM_SYSCOMMAND, SC_CLOSE, ByVal 0&'關閉窗體
End Select
End Sub

11.文本垂直居中:
  實現這個效果首先TextBox的MultiLine屬性必須為True(多行文本,其實這個屬性關系創建TextBox內部

使用哪個類,因此一旦創建就不能修改這個屬性,所以不能在代碼中修改這個屬性)

Public Sub VerMiddleText(mText As TextBox)
Dim rc As RECT '以象素為單位
Dim tmpTop As Long
Dim tmpBot As Long
If mText.MultiLine = False Then Exit Sub
Call SendMessage(mText.hwnd, EM_GETRECT, 0, rc)'獲得窗口區域的邊界
   '進行位置數據計算
With Me.Font
  .Name = mText.Font.Name
  .Size = mText.Font.Size
  .Bold = mText.Font.Bold
End With
tmpTop = ((rc.Bottom - rc.Top) - (mText.Parent.TextHeight("H") \ Screen.TwipsPerPixelY)) \ 2
tmpBot = ((rc.Bottom - rc.Top) + (mText.Parent.TextHeight("H") \ Screen.TwipsPerPixelY)) \ 2
rc.Top = tmpTop
rc.Bottom = tmpBot
mText.Alignment = vbCenter
   '數據計算完畢,再發送EM_SETRECTNP消息(為一個編輯控件設置格式化矩形,與EM_SETRECT類似,只是控件此時不會重畫)
Call SendMessage(mText.hwnd, EM_SETRECTNP, 0&, rc)
mText.Refresh
End Sub

12.調整邊距:
  如果你查看TextBox中常用的消息,你會發現有這樣一對消息:EM_GETMARGINS 和 EM_SETMARGINS,MSDN的解
釋是:獲取和設置編輯控件的左、右邊距(不得用於NT3.51)。具體是左還是右由該消息的參數決定。
  這樣做有什麼意義呢?有的時候如果你想在texebox中放入其他對象,而又不希望文本被覆蓋掉,你就需要用
到這個方法。

Private Sub SetMargin(nLeft As Integer, nRight As Integer, lhWnd As Long)
Dim lLongValue As Long
lLongValue = nRight * &H10000 + nLeft '高四位表示右邊距,低四位為左邊距
SendMessage lhWnd, EM_SETMARGINS, EC_LEFTMARGIN Or EC_RIGHTMARGIN, lLongValue
End Sub

 

作者:一江秋水      發表時間:2007-8-27 10:21:00

 6樓  

SendMessage函數應用(五)
  RichEdit控件的正文操作

一、正文搜索
     RichEdit 控件具有幾種正文操作,搜索指定正文就是其中的一種。搜索正文是通過發送
EM_FINDTEXT 或者 EM_FINDTEXTEX 消息來完成的。這兩個消息有一點很小的不同點。

1.EM_FINDTEXT
 wParam=搜索選項,可以是下面3個參數的任意組合值(這些選項對 EM_FINDTEXT 和 EM_FINDTEXTEX
都是一樣的):
①FR_DOWN(&H1):搜索方向。如果指定了這個標志值,搜索操作從當前選定的 end 位置開始,直到控件
  中正文的 end 位置結束(向下搜索)。這個標志影響 RichEdit 2.0 和以後版本,是 RichEdit 1.0
  的缺省行為。RichEdit 2.0或以後版本的缺省行為是:在當前選定正文內的從結尾搜索到開始位置
  (向前搜索)。概括來說就是,如果你使用 RichEdit 1.0, 無論你做什麼都沒法影響搜索的方向,它
  總使用向後搜索。但是如果你使用 RichEdit 2.0 而且你想使用向後搜索的話,你必須指定這個標
  志值,否則使用的是向前搜索了。
②FR_MATCHCASE(&H4):區分大小寫。
③FR_WHOLEWORD(&H2):匹配指定搜索串的整個詞。

 lParam = FINDTEXT 結構的指針。
Type FINDTEXT        'STRUCT
  chrg As CHARRANGE  '
  lpstrText As Long
End Type

  chrg 是一個 CHARRANGE 結構,其定義如下:
Type CHARRANGE       'STRUCT
  cpMin As Long      '包含字符數組中第一個字符的字符索引
  cpMax As Long      '包含緊跟在字符數組中最後一個字符的字符的字符索引
End Type 

  基本上,要搜索一個正文串,你必須指定要搜索的字符范圍。cpMin 和 cpMax 的具體意義根據搜索是向
後還是向前是不同的。
  如果是向後搜索,cpMin 指定搜索的開始字符索引,而 cpMax 則是結束字符索引。
  如果是向前搜索,則反過來才對,也就是說 cpMin 包含結束字符索引而cpMax 包含開始字符索引。

  lpstrText 是要搜索的正文串的指針。

2.EM_FINDTEXTEX
  返回控件中跟搜索串匹配的的正文串的一個字符的索引。如果沒找到匹配的則返回 -1。

  wParam = 搜索選項,跟 EM_FINDTEXT 的一樣。
  lParam = FINDTEXTEX 結構的指針。

Type FINDTEXTEX      'STRUCT
  chrg As CHARRANGE  '
  lpstrText As Long 
  chrgText CHARRANGE 'CHARRANGE
End Type

  FINDTEXTEX 中開始的兩個成員是跟 FINDTEXT 結構中的一樣的。
  chrgText 是一個 CHARRANGE 結構,如果搜索到匹配串的話,其開始/結束字符索引會被填入這個結構中。

  EM_FINDTEXTEX 的返回值跟 EM_FINDTEXT的是一樣的。

  EM_FINDTEXT 跟 EM_FINDTEXTEX 的不同處:
FINDTEXTEX 結構有一個另外的chrgText成員, 如果搜索到匹配串的話,其開始/結束字符索引會被填入這個成
員中。如果我們想對這個正文串進行更多的正文操作的話,有這個就方便多了。

二、替換/插入正文

  RichEdit 控件提供了 EM_SETTEXTEX 來進行正文替換/插入操作。這個消息混合了 WM_SETTEXT 和
EM_REPLACESEL 的功能. 它具有以下語法:

  wParam = SETTEXTEX 結構的指針。
Type SETTEXTEX      'STRUCT
  flags As Long 
  codepage As Long
End Type

  flags 可以是以下值的組合:
  ST_DEFAULT   刪除Undo堆棧,丟棄RTF格式,替換所有的正文。
  ST_KEEPUNDO  保留Undo堆棧。
  ST_SELECTION 替換選定正文並且保留RTF格式

  codepage 是一個常量,指定你的正文想要的代碼頁。我們通常簡單的使用 CP_ACP。

三、正文選擇

  我們可以使用消息 EM_SETSEL 或者 EM_EXSETSEL 來編程選擇正文.其中任意的一個都可以工作的很好。
要使用哪一個消息要根據可用的字符索引格式來選擇。如果它們保存在一個 CHARRANGE 結構中,則使用
EM_EXSETSEL更容易實現。

  EM_EXSETSEL
  wParam = 沒有使用,必須為 0 。
  lParam = CHARRANGE 結構的指針,包含想要選定的正文字符范圍。

四、事件通知

  在使用多行Edit控件時,你必須子類化它以便得到輸入信息象鼠標/鍵盤事件等。RichEdit 控件提供了一
個更好的方案,它可以把這些消息通知父窗口。為了注冊得到通知消息,父窗口發送 EM_SETEVENTMASK 消息
給 RichEdit 控件,指定它對哪些消息感興趣。 
  EM_SETEVENTMASK 具有以下的語法:
wParam  沒有使用,必須為 0 。

lParam = 事件掩碼值,可以是以下標志值的任意組合:

  ENM_CHANGE 發送 EN_CHANGE 通知
  ENM_CORRECTTEXT 發送 EN_CORRECTTEXT 通知
  ENM_DRAGDROPDONE 發送 EN_DRAGDROPDONE 通知
  ENM_DROPFILES 發送 EN_DROPFILES 通知
  ENM_KEYEVENTS 為鍵盤消息發送 EN_MSGFILTER 通知
  ENM_LINK Rich Edit 2.0 或以後版本: 當鼠標在具有 CFE_LINK 風格的正文上面移過,而且執行了一個
或幾個鼠標動作時,就發送 EN_LINK 通知。
  ENM_MOUSEEVENTS 為鼠標消息發送 EN_MSGFILTER 通知。
  ENM_OBJECTPOSITIONS 發送 EN_OBJECTPOSITIONS 通知
  ENM_PROTECTED 發送 EN_PROTECTED 通知
  ENM_REQUESTRESIZE 發送 EN_REQUESTRESIZE 通知
  ENM_SCROLL 發送 EN_HSCROLL 和 EN_VSCROLL 通知
  ENM_SCROLLEVENTS 為鼠標滑輪發送 EN_MSGFILTER 通知。
  ENM_SELCHANGE 發送 EN_SELCHANGE 通知
  ENM_UPDATE 發送 EN_UPDATE 通知

  Rich Edit 2.0 和以後版本: 這個標志值會被忽略,而經常發送 EN_UPDATE 通知。然而如果 RichEdit 
3.0 模擬 RichEdit 1.0的話,你必須使用這個標志值來發送 EN_UPDATE 通知

  上面的所有通知都被做為 WM_NOTIFY 消息來發送:你必須檢查 NMHDR 結構的 code 成員來得到通知消
息。譬如,如果你想注冊得到鼠標消息(也就是說,你想提供一給上下文相關的彈出菜單)
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 nineaddnine 的頭像
    nineaddnine

    nineaddnine的部落格

    nineaddnine 發表在 痞客邦 留言(0) 人氣()