日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

SendMessage函数的常用消息及其应用

發(fā)布時間:2023/12/10 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SendMessage函数的常用消息及其应用 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
  文本框控件通常用于輸入和編輯文字。它屬于標(biāo)準(zhǔn) Windows 編輯控件的一個子類,所以它支持所有
編輯控件消息?這兒講述的技術(shù)也適用于由其他廠商設(shè)計的 , 以Windows編輯控件類為基礎(chǔ)的其他控件?
函數(shù)原型:
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, _
ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
其中四個參數(shù)的含義和說明如下:
1.hWnd:
  對象的句柄。希望將消息傳送給哪個對象,就把該對象的句柄作為實參傳送,在 VB 中可以簡單地
用“對象.hWnd”獲得某個對象的句柄,如 Text1.hWnd和 Form1.hWnd分別可以得到 Text1和Form1的句
柄。它是一個長整型數(shù)。Windows給每個控件一個編號,這個編號就稱為窗口句柄。有了這個句柄,我們
就可告訴 Windows 我們要控制哪個控件,所以這個句柄在 API 調(diào)用中至關(guān)重要。VB 的大多數(shù)控件都包
括hwnd屬性,如下拉框、TreeView等,窗體也有這個屬性。但也有一些控件沒有這個屬性,如標(biāo)簽控件。
沒有這個屬性就無法利用Windows API函數(shù),但可以節(jié)省系統(tǒng)資源。
2.wMsg:
  被發(fā)送的消息。根據(jù)具體需求和不同的對象,將不同的消息作為實參傳送,以產(chǎn)生預(yù)期的動作。使
SendMessage 傳遞消息,大多是為了完成以下幾個工作:
  ①設(shè)置控件的一些選項,象我們要使用的CB_SETDROPPEDWIDTH的就屬于這種情況。盡管VB的每個控
件都提供了許多屬性,但仍然有許多控件的選項沒有包括在其中。而這些選項中的大多數(shù)都可以利用該
函數(shù)進行設(shè)置?
  ②獲得控件的一些設(shè)置。同上一種情況相反,有時我們需要獲得控件的一些設(shè)置,相當(dāng)于讀取屬性。
例如,如果想知道一個下拉框的下拉部分的寬度是多少,就可以向控件發(fā)送CB_GETDROPPEDWIDTH消息。
對于這種情況,SendMessage函數(shù)的返回值就是結(jié)果。
  ③執(zhí)行一定的操作。例如,我們要在下拉框中尋找是否有“ABC”這個字符串,當(dāng)然,我們可以編寫
一個循環(huán),逐條比較看是否存在這樣的字符串。如果使用API,我們只需要向下拉框發(fā)送CB_FINDSTRING
消息,這條消息就會自動進行查找工作并返回結(jié)果。
  ④模擬用戶操作。我們有時希望模擬用戶的操作,比如關(guān)閉其他應(yīng)用程序的窗口。其實只要我們能知
道那個窗口的句柄,我們就可以發(fā)送WM_CLOSE消息給那個窗口,窗口接受到這條消息就會關(guān)閉,如同用戶
關(guān)閉窗口一樣?
3.wParam、4.lParam:
  附加的消息信息。這兩個是可選的參數(shù),用來提供關(guān)于wMsg消息更多的信息,不同的wMsg可能使用這
兩個參數(shù)中的0、1或2個,如果不需要哪個附加參數(shù),則將實參賦為NULL(在VB中賦為0)。
  lParam定義為Any類型。指定 Any類型可禁止VB進行類型檢查,從而允許將任意數(shù)據(jù)類型傳遞給該過
程。由于每條消息對參數(shù)的類型和傳遞方式的要求都不同:有的可能要求為Long型,有的可能要求為自定
義類型;大多數(shù)要求按傳值方式傳遞,但也有一些要求按傳地址方式。為了滿足各種要求,我們將這個參
數(shù)定義為Any類型。比如,我們要傳遞一個Long型變量lData。如果消息要求傳地址方式傳遞,可以使用:
??? SendMessage ……, lData
  而如果要求傳值方式傳遞,則使用
??? SendMessage ……, ByVal lData
  如果傳遞常數(shù),我們則需要使用類型后綴來指定常數(shù)的類型,比如"0&",表示Long型的常數(shù)0,如
??? SendMessage ……, ByVal 0&
  我們也可以使用類型轉(zhuǎn)換函數(shù)CLng將常數(shù)指定為Long型,如CLng(0)。
  程序中,有時定義 lParam As Any,有時定義 ByVal lParam As String。這是為什么呢?對于
SendMessage函數(shù),lParam的使用是很靈活的,在一般情況下,lParam是一個指針,它指向的數(shù)據(jù)類型
有三種:長整形、自定義數(shù)據(jù)結(jié)構(gòu)類型、字符串類型。對于前兩種類型,需要將 lParam定義為 lParam
As Any,從而將 lParam 數(shù)據(jù)的指針傳遞到 SendMessage 函數(shù)。對于字符串類型,則需要定義 Byval
lParam As String,因為字符串類型數(shù)據(jù)不同,只有定義 ByVal,得到的才是字符串的指針,如果沒有
ByVal,得到的將是指向字符串指針的指針。另外對于少數(shù)的消息來說,SendMessage 函數(shù)需要的只是
lParam 本身的值,這時就需要將 lParam定義為 Byval lParam As Long,或者在程序調(diào)用時在 lParam
之前加 ByVal?
  當(dāng)用戶在編輯控件上進行各種操作時,其父窗口將收到 WM_COMMAND 通知消息,lParam帶控件句柄
(hWnd),同時 wParam 的低16位帶控件的 ID,高16位帶有如下表的消息代碼:
常用編輯控件消息:
EC_LEFTMARGIN(&H1)??????????????????? EC_USEFONTINF 設(shè)置左邊距時使用
EC_RIGHTMARGIN??????????????????????? EC_USEFONTINF 設(shè)置右邊距時使用
EC_USEFONTINF,O,邊距????????????????? 設(shè)置編輯控件的左、右邊距,當(dāng)wParam含EC_LEFTMARGIN時在lParam的低16位指定左邊距點數(shù),當(dāng)wParam含EC_RIGHTMARGIN時在lParam的高16位指定右邊距點數(shù)。當(dāng)指定wParam為EC_USEFONTINFO時,則用當(dāng)前字體的字符"A"的寬度指定右邊距和字符"C"的寬度指定左邊距l(xiāng)Param被忽略。
EM_CHARFROMPOS(&HD7=215),0,?????????? 取得編輯控件中指定位置的字符相對于文本頭部的偏移量。使用本操作應(yīng)先在第4個參數(shù)的高16位指定行號,低16位指定列號(或一個POINTAPI結(jié)構(gòu)),行列是按編輯控件的客戶區(qū)左上角為原點(0,0)計算的。如果指定的位置超出控件客戶區(qū)則返回-1
EM_CANUNDO(&HC6=198),0,0??  ???????? 決定前一次編輯操作是否能夠撤消:檢測控件撤消緩沖區(qū)是否為空,通常控件把最后一次在控件的編輯操作保存在一個撤消緩沖區(qū),如果緩沖區(qū)非空則返回TRUE表示上次操作可以撤消,否則返回FALSE,應(yīng)用程序可以利用該返回值來禁止或允許菜單或工具條的"撤消"項。
EM_EMPTYUNDOBUFFER(&HCD=205 ),0,0???? 清除控件的撤消緩沖區(qū),使其不能撤消前一次編輯操作
EM_FMTLINES(&HC8=200)??????????  ??? 決定是否在取回的文本宇串中包含軟回車字符
EM_GETFIRSTVISIBLEINE(&HCE=206),0,0?? 獲得文本控件中處于可見位置的最頂部的文本所在的行號
EM_GETLINE(&HC4=196 ),行號,ByVal 變量 獲取編輯控件某一行的內(nèi)容,變量須預(yù)先賦空格
EM_GETLINECOUNT(&HBA=186,0,0????????? 獲取編輯控件的總行數(shù)
EM_GETMODIFY(&HB8=184),0,0 ????????? 判斷編輯控件的內(nèi)容是否已發(fā)生變化,返回TRUE則控件文本已被修改,返回FALSE則未變。
EM_GETPASSWORDCHAR( ),0,0 ?????????? 獲取編輯控件的密碼字符,返回NULL表示沒有字符
EM_GETRECT(&HB2=178),0,結(jié)構(gòu)???????   獲取編輯控件的格式化矩形
EM_GETTHUMB(&HBE=190),0,0???????????? 取得多行文本編輯控件的滾動框的當(dāng)前位置(注意:是象素值)
EM_GETSEL(&HB0=176),0,變量??????????? 獲取光標(biāo)位置(以字節(jié)數(shù)表示),或:(緩沖區(qū)起點,緩沖區(qū)終點)取得編輯控件中選定內(nèi)容的范圍,返回值中低16位為起點,高16位為終點
EM_GETHANDLE(&HBD=189),0,0??????????? 取得文本緩沖區(qū)
EM_GETWORDBREAKPROC(&HD1=209),0,0???? 取得整字換行回調(diào)函數(shù)EditWordBreakProc指針
EM_GETLIMITTEXT(WM_USER+37=1061),0,0? 獲取一個編輯控件中文本的最大長度
EM_GETMARGINS( ),0,0????????????????? 獲取編輯控件的左、右邊距,返回值低16位為左邊距,高16位為右邊距(不得用于NT3.51)
EM_LIMITTEXT(&HC5=197),最大值,0?????? 設(shè)置編輯控件中的文本長度
EM_SCROLLCARET(&HB7=183),0,0????????? 把可見范圍移至光標(biāo)處
EM_LINEFROMCHAR(&HC9=201),偏移值,0??? 獲取指定位置(或:-1,0 表示光標(biāo)位置)所在的行號
EM_LINEINDEX(&HBB=187),行號,0???????? 獲取指定行(或:-1,0 表示光標(biāo)所在行)首字符在文本中的位置(以字節(jié)數(shù)表示)
EM_LINELENGTH(&hC1=193),偏移值,0????? 獲取指定位置所在行(或:-1,0 表示光標(biāo)所在行)的文本長度(以字節(jié)數(shù)表示)
EM_POSFROMCHARPOINT,結(jié)構(gòu)地址,偏移值?? 取得指定字符位置的行列號,偏移值是字符相對于文本頭部的偏移。
EM_LINESCROLL(&HB6=182),列數(shù),行數(shù)???? 指定行數(shù)的文本水平滾動,每次滾動N列
EM_EXGETSEL (&H434 = 1076)
EM_EXSETSEL(&H437=1079),0,結(jié)構(gòu)??????? RichEdit控件設(shè)置文本選定范圍,參閱 EM_SETSEL 消息,結(jié)構(gòu)是指 CHARRANGE 結(jié)構(gòu)
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)設(shè)置 RichTextBox 自動換行,后續(xù)代碼是:RichText.RightMargin = iif(RichText.RightMargin = 0,1,0)
EM_SETTARGETDEVICE, 0, 1????????????? 設(shè)置 RichTextBox 不自動換行
EM_POSFROMCHAR(&HD6或&H426)?????????? 判斷指定字符在編輯控件的位置(用于NT3.51)
EM_SCROLL(&HB5=181),*,0?????????????? 文本垂直滾動。第三個參數(shù)*控制滾動方向:SB_LINEDOWN(1)向下滾動一行,SB_LINEUP(0)向上滾動一行,SB_PAGEDOWN(3)向下滾動一頁,SB_PAGEUP(2)向上滾動一頁。
EM_REPLACESEL(&HC2=194),1(0),字符串?? 用指定字符串替換編輯控件中的當(dāng)前選定內(nèi)容,如果第三個參數(shù)wParam為1,則本次操作允許撤消,0禁止撤消。字符串可用傳值方式,也可用傳址方式(例:SendMessage Text1.hwnd, EM_REPLACESEL, 0, Text2.Text '這是傳值方式)
EM_SETSEL(&HB1=177),起點,終點??????? 設(shè)置編輯控件中文本選定內(nèi)容范圍(或設(shè)置光標(biāo)位置),該范圍被反相顯示,用于為復(fù)制、替換、粘貼、剪切、刪除等編輯功能指定范圍,光標(biāo)將被移至指定的終點后面。還可使用指定相同起點和終點來移動光標(biāo)而不是選定范圍。當(dāng)指定的起點等于0和終點等于-1時,文本全部被選中,此法常用在清空編輯控件。當(dāng)指定的起點等于-2和終點等于-1時,全文均不選,光標(biāo)移至文本未端,此法常用在文本未端追加內(nèi)容。注意:當(dāng)控件沒有輸入焦點時,本操作將會失敗,一般在執(zhí)行本操作前都應(yīng)調(diào)用SetFocus先取得輸入焦點。
EM_UNDO(&HC7=199),0,0???????????????? 撤消前一次編輯操作,當(dāng)重復(fù)發(fā)送本消息,控件將在撤消和恢復(fù)中來回切換
EM_SETCHARFORMAT(&H444)?????????????? 改變選定文本的顏色
EM_SETHANDLE(&HBC=188),緩沖區(qū)指針,0? 為編輯控件指定新的文本緩沖區(qū)。此操作僅適用對話框創(chuàng)建帶DS_LOCALEDIT風(fēng)格的控件。
EM_SETLIMITTEXT,長度(字節(jié)),0????????? 設(shè)置編輯控件中的文本最大長度(不得用于NT3.51)
EM_SETMARGINS(&HD3=211)?????????????? 設(shè)置編輯控件的左、右邊距(不得用于NT3.51)
EM_SETMODIFY(&HB9=185),1(0),0???????? 設(shè)置或清除一個編輯控件的修改標(biāo)志
EM_SETPASSWORDCHAR(&HCC=204),字符,0?? 指定控件用來顯示密碼的字符,缺省為"*"。當(dāng)?shù)谌齻€參數(shù)wParam為0時,本操作將清除控件的ES_PASSWORD風(fēng)格,并按實際字符顯示。
EM_SETREADONLY(&HCF=207),1(0),0?????? 決定是否將編輯控件設(shè)為只讀,同時決定控件的ES_READONLY風(fēng)格
EM_SETRECT(&HB3=179),0(或RECT),結(jié)構(gòu)地址????? 為一個編輯控件設(shè)置格式化矩形
EM_SETRECTNP(&HB4=180),0(或RECT),結(jié)構(gòu)地址??? 為一個編輯控件設(shè)置格式化矩形,只是控件此時不會重畫
EN_CHANGE(&H300=768)????????????????? 編輯控件的內(nèi)容發(fā)生改變。與EN_UPDATE不同,該消息是在編輯框顯示的正文被刷新后才發(fā)出的。
EN_ERRSPACE(&H500=1280)?????????????? 任何時候只要由于內(nèi)存不足以完成一項編輯操作
EN_HSCROLL(&H601=1537)??????????????? 用戶單擊了編輯控件的水平滾動條。注意:這條消息是在控件更新顯示之前發(fā)送出去的。
EN_VSCROLL(&H602=1538)??????????????? 用戶單擊了編輯控件的垂直滾動條。注意:這條消息是在控件更新顯示之前發(fā)送出去的。
EN_KILLFOCUS(&H200=512)?????????????? 編輯控件失去了輸入焦點
EN_SETFOCUS(&H100=256)??????????????? 編輯控件獲得了輸入焦點
EN_UPDATE(&H400=1024)???????????????? 控件準(zhǔn)備顯示改變了的正文時發(fā)送該消息。它與EN_CHANGE通知消息相似,只是它發(fā)生于更新文本顯示出來之前。
EN_MAXTEXT(&H501=1281)??????????????? 用戶輸人的文字?jǐn)?shù)超出由EM_LIMITTEXT消息規(guī)定的界限,或超出由VB Maxlength屬性規(guī)定的界限,就會發(fā)送這條消息 。此外,倘若不允許自動進行水平滾動,同時插入點要超出控件的寬度;或者不允許自動垂直滾動,同時插入點要超出控件的高度,那么也會觸發(fā)這條消息。在沒有ES_AUTOHSCROLL或ES_AUTOVSCROLL的編輯框中,當(dāng)正文超出了編輯框的邊框時也會發(fā)出該消息。
編輯風(fēng)格消息:
ES_MULTILINE  ?????????????????????? 指定編輯控件能否進行多行文本編輯,若多行編輯器不指定ES_AUTOHSCROLL風(fēng)格,則會自動換行,用戶每按一次Enter,在當(dāng)前光標(biāo)處輸入一個回車換行符(0Dh,0Ah),文本增加一行。若不指定ES_AUTOVSCROLL,則多行編輯器會在窗口中正文裝滿時發(fā)出警告聲響。
ES_LEFT 文本顯示居左?
ES_CENTER 文本顯示居中?
ES_RIGHT 文本顯示居右?
ES_LOWERCASE 把用戶輸入的字母統(tǒng)統(tǒng)轉(zhuǎn)換成小寫字母?
ES_UPPERCASE 把用戶輸入的字母統(tǒng)統(tǒng)轉(zhuǎn)換成大寫字母?
ES_OEMCONVERT ?????????????????????? 把輸入的文本從ANSI碼轉(zhuǎn)換成OEM碼,然后又轉(zhuǎn)換成ANSI碼,目的是保證函數(shù)AnsiToOem的正確調(diào)用。這在編輯框中包含文件名時是很有用的。
ES_AUTOHSCROLL(自動增加水平滾動條?) 當(dāng)用戶在行尾鍵入一個字符時,正文將自動向右滾動10個字符,當(dāng)用戶按回車鍵時,正文總是滾向左邊。
ES_AUTOVSCROLL ????????????????????? 當(dāng)用戶在最后一個可見行按回車鍵時,正文向上滾動一頁。
ES_NUMBER ?????????????????????????? 只接收數(shù)碼輸入,其它字符輸入一律無效。
ES_NOHIDESEL(&H100=256)?????????????? 當(dāng)編輯框失去輸入焦點時,選中的文本將隱藏,正文中的選擇保持不變。缺省時正文中的選擇將失效,當(dāng)獲得輸入焦點后才又顯示出來。
ES_READONLY 將編輯框設(shè)置成只讀的?
ES_PASSWORD(&H20=32)????????????????? 使所有鍵入的字符都用"*"來顯示。
ES_WANTRETURN ?????????????????????? 使多行編輯器接收回車鍵輸入并換行。如果不指定該風(fēng)格,按回車鍵會選擇缺省的命令按鈕,這往往會導(dǎo)致對話框的關(guān)閉。
列表框操作:
LB_FINDSTRING(&H18F=399),-1,ByVal 字串?? 查找列表項的字符串,返回值=字符串所在的列表項的索引。-1表示從第0行開始查找,如果改為一個有效的列表項索引值,將從該行開始查找。
LB_ITEMFROMPOINT(&H1A9=425)????????????? 獲取光標(biāo)所在的列表項的索引
LB_SETHORIZONTALEXTENT(&H194=404),長度,0 設(shè)置列表框的橫向滾動條以及滾動長度,長度為象素值
組合框操作:
CB_SHOWDROPDOWN(&H14F),1(0),0???????? 打開(關(guān)閉)組合框的列表
TVM_SETBKCOLOR(&H1100+29=4381)??????? 設(shè)置擴展樹型列表控件的背景色(TVM開頭的常數(shù))
常用窗口消息:
WM_GETFONT(&H31=49)?????????????????? 得到當(dāng)前控件繪制文本的字體(的句柄)
WM_GETTEXT(&HD=13),變量長度,變量?????? 取得窗體的標(biāo)題,變量須預(yù)先賦空字串(chr(0)),變量長度=Len(變量)
WM_SETTEXT(&HC=12),0,ByVal "字串"???? 設(shè)置窗體的標(biāo)題
WM_NCLBUTTONDOWN(&HA1=161),2,0??????? 在非客戶區(qū),即邊框及標(biāo)題欄上(假如定義的是一個組件,則非客戶區(qū)包括Form等)按下鼠標(biāo)左鍵;
WM_LBUTTONDOWN(&H201=513),2,0???????? 在客戶區(qū),也就是除邊框及標(biāo)題欄以外按下鼠標(biāo)左鍵
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?????????????? 復(fù)制
WM_PASTE(&H302=770)),0,0????????????? 粘貼
WM_CLEAR(&H303=771)),0,0????????????? 刪除
WM_UNDO(&H304=772)),0,0?????????????? 撤消
按紐消息:
BM_SETSTYLE(&HF4)?????????????????? 設(shè)置按紐樣式
BS_RADIOBUTTON(&H4)???????????????? 收音機旋紐式的按紐,是 BM_SETSTYLE 使用的參數(shù)
SendMessage函數(shù)應(yīng)用 (一)
??? 在Windows系統(tǒng)的很多消息中,有一些不僅僅是提供一個窗口消息那么簡單。它們可以控制窗口的
動作和屬性。下面向大家介紹SendMessage函數(shù)在擴充列表(ListBox)控件功能方面的應(yīng)用。
  在 Windows 中,有一系列的以 LB_ 開頭的列表消息,這里介紹的就是利用LB消息控制的ListBox
的應(yīng)用?
1 ?使列表中光標(biāo)移動到不同的列表項上有不同的提示 (ToolTip)
  在列表框控件中有一個 ToolTipText 屬性,該屬性決定了當(dāng)光標(biāo)在列表框上移動時出現(xiàn)的提示文
字。但是如何使得當(dāng)光標(biāo)在不同的列表項上移動時的提示文字也不同呢?問題的關(guān)鍵是要知道在光標(biāo)移
動時光標(biāo)所在的列表項的索引,使用SendMessage函數(shù)發(fā)送 LB_ITEMFROMPOINT 消息就可以獲得。
  在 Form1 中加入一個 ListBox 控件,運行程序,當(dāng)光標(biāo)在列表中移動時,可以看到根據(jù)光標(biāo)所在
的不同的列表項,提示文字也不相同。代碼如下(我已試驗成功):
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 '確定在移動鼠標(biāo)的同時沒有按下功能鍵或者鼠標(biāo)鍵
? lXPoint = CLng(x / Screen.TwipsPerPixelX) '獲得光標(biāo)的位置,以像素為單位
? lYPoint = CLng(y / Screen.TwipsPerPixelY)
? With List1
??? lIndex = SendMessage(.hwnd, LB_ITEMFROMPOINT, 0, ByVal ((lYPoint * 65536) + lXPoint)) '獲得光標(biāo)所在的標(biāo)題行的索引
??? If lIndex < .ListCount Then .TooltipText = .List(lIndex) Else .TooltipText = ""
? End With
End If
End Sub
2 ?向列表中加入橫向滾動條使得可以瀏覽長列表項
當(dāng)向列表中加入的列表項超出了列表的顯示范圍后,列表并不會出現(xiàn)橫向滾動條讓你可以通過滾動來瀏覽
項目的全部內(nèi)容。利用 LB_SETHORIZONTALEXTENT 消息可以設(shè)置列表框的橫向滾動條以及滾動長度。
  在 Form1 中加入一個 ListBox 控件,運行程序,可以看到列表中出現(xiàn)了橫向滾動條,而且滾動范圍正好
是列表項的長度?代碼如下 (我已試驗成功):
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 ?使列表框可以響應(yīng)用戶擊鍵
有時我們需要列表根據(jù)用戶的敲入字符串自動調(diào)整列表的ListIndex到最接近的列表項,就象VB中動態(tài)
響應(yīng)用戶輸入控件屬性的編輯器一樣。問題的關(guān)鍵是如何在列表中查找含有指定字符串的列表項,使用
LB_FINDSTRING消息可以在列表中查找指定字符串?
  在 Form1 中加入一個 TextBox 控件和一個 ListBox 控件,并將 List1的 Sorted 屬性設(shè)置為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) '注意!當(dāng)參數(shù)4傳入的是字符串時,必須用ByVal傳遞
? If L Then List1.ListIndex = L
End If
End Sub
4.在列表框中查找匹配的項目
?? 在Win95風(fēng)格的幫助系統(tǒng)中一般都有一個“索引”頁,索引頁含有一個文本框和一個列表框,當(dāng)用戶
在文本框中輸入文字時,下拉列表會動態(tài)地顯示與文本框中文字最匹配的項目,為用戶提供了最大的方
便。這種效果在應(yīng)用程序的幫助系統(tǒng)中很容易實現(xiàn)(只要按照 Win95幫助系統(tǒng)的正常制作過程制作就可
以實現(xiàn)),如果想在應(yīng)用程序的其它地方實現(xiàn)這種特性就需費一番心思了。
?? 而使用SendMessage函數(shù)實現(xiàn)上述特性則非常簡單,甚至只需一條語句就足夠了,那就是在文本框的
Change事件中給列表框發(fā)一條LB_FINDSTRING(&H18F)消息,該消息告訴列表框在列表中查找匹配的項
目?
?? 在發(fā)LB_FINDSTRING消息時,wParam參數(shù)代表從列表框的哪一個項目后面開始查找,一般情況下該參
數(shù)可定為-1,表示從List1(0)即第一項開始向后循環(huán)查找,lParam則傳進欲搜索的字符串(必須采用值
傳遞)。
?? 具體的代碼和運行畫面與下面的 5. 合并在一起演示。
5.為ListBox添加水平滾動條
?? 在VB中,列表框控件僅提供垂直滾動條,沒有設(shè)置水平滾動條的能力,當(dāng)某些項目的文本寬度較長
時,超出列表框?qū)挾炔糠值奈谋揪蜔o法顯示出來,因此,很有必要為ListBox添加一個水平滾動條來方
便操作?
?? 為添加水平滾動條,只需發(fā)一條 LB_SETHORIZONTALEXTENT(&H194) 消息給列表框即可。發(fā)送消息
時,wParam為滾動條的長度(以像素為單位,可通過計算得出準(zhǔn)確的長度,上面例2 就是如此的,也可
隨便給一個數(shù)字,如本例的 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()
'注意!當(dāng)lParam傳入的是字符串時,必須用ByVal傳遞
List1.ListIndex = SendMessage(List1.hwnd, LB_FINDSTRING, -1, ByVal Text1.Text)
End Sub
6.在API文本瀏覽器里,當(dāng)我們在搜索欄輸入任意字母,“可用項”里以該字母開頭的項目以高亮顯
示以引起我們注意該項是不是我們所需的?象這樣的功能一切提供搜索選項的程序都應(yīng)該具備?以下例
子采用SendMessage函數(shù)實現(xiàn)這一技術(shù)?
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 = "" '按下任意鍵則令原內(nèi)容消失
Text1.SelLength = 1 '限制長度
Text1.SelText = Chr(KeyAscii) '顯示鍵盤符號
KeyAscii = 0 '禁止響應(yīng)
'ListBox中的項目文本若與文本框的一致則選中(高亮)
List1.ListIndex = SendMessage(List1.hwnd, LB_FINDSTRING, -1, ByVal CStr(Text1.Text)) '經(jīng)試,不需CStr函數(shù)
End Sub
  以上程序適用于單項目為多個字母的查詢,但必須注意,在TextBox的KeyPress事件中要作相應(yīng)的
改動
SendMessage函數(shù)應(yīng)用 (二)
  介紹如何利用消息函數(shù)來擴展樹型列表 TreeView 控件的功能。相信對于樹型列表控件大家十分的
熟悉,典型的應(yīng)用就是 Windows 資源管理器中的目錄列表。而在VB中,樹型列表控件包含在Microsoft
Windows Common Control 6.0(也可能是5.0,視你的VB或者系統(tǒng)版本而定)中。在Windows API 中,
有一系列的以 TVM_ 開頭的消息值,這些消息就是擴展樹型列表控件所特定的消息值,下面向大家介紹
其中的一些應(yīng)用
1 ?設(shè)置樹型列表控件的背景顏色
首先做如下的定義:
Const TV_FIRST = &H1100
Const TVM_SETBKCOLOR = TV_FIRST + 29(4381)
調(diào)用:
Call SendMessage(TreeView1.hwnd, 4381, 0, ByVal RGB(255, 0, 0))
??? 上面的SendMessage調(diào)用將TreeView1的背景顏色設(shè)置為紅色?
  大家可能注意到了。在上面的 Sendmessage 函數(shù)定義中,我們將 lParam 定義為 ByVal lParam
As Long,而不是象前面的那些范例那樣定義為 Any 或者 String 類型,關(guān)于這個問題,我會在最后的
一章中做介紹?
2 ?設(shè)置樹型列表控件標(biāo)題行高度
  TVM_SETITEMHEIGHT 消息設(shè)定控件的標(biāo)題行的高度,該消息的定義及調(diào)用方法如下:
Const TV_FIRST = &H1100
Const TVM_SETITEMHEIGHT = TV_FIRST + 27
Call SendMessage(TreeView1.hwnd, TVM_SETITEMHEIGHT, 60, 0) '將TreeView1標(biāo)題行高度設(shè)置到60像素高
3 ?為樹型列表控件中不同的標(biāo)題行設(shè)置不同的提示
 介紹如何為樹型列表控件中的每一個標(biāo)題設(shè)置不同的提示。同 ListBox控件不通,樹型列表控件中
并沒有根據(jù)光標(biāo)位置獲得標(biāo)題行索引的消息,我們需要另外想辦法。在TVM類消息中有一個TVM_HITTEST
消息,發(fā)送該消息可以檢測控件表面上的某一點,如果該點位于一個標(biāo)題上,則返回該標(biāo)題的句柄。而
利用 TVM_GETITEM消息,則可以根據(jù)標(biāo)題句柄返回該標(biāo)題行的文本。所以結(jié)合利用這兩個消息可以獲取
光標(biāo)所在標(biāo)題行的標(biāo)題文本?具體的范例代碼如下:
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
  '獲得當(dāng)前光標(biāo)所在的位置坐標(biāo)
  ptA.x = Int(x / Screen.TwipsPerPixelX)
  ptA.y = Int(y / Screen.TwipsPerPixelY)
  tf.pt = ptA
  tf.flags = TVHT_ONITEMLABEL
  '獲得光標(biāo)所在的Item的句柄
  hItem = SendMessageRef(TreeView1.hwnd, TVM_HITTEST, 0, tf)
  '如果未獲得句柄或者同上一次是同一個Item的句柄則退出
  If ((hItem <= 0) Or (hItem = hItemPrv)) Then Exit Sub
  hItemPrv = hItem
  '分配一定的內(nèi)存空間用以存儲Item的標(biāo)題
  hStr = GlobalAlloc(GMEM_FIXED, 1024)
  If hStr > 0 Then
  tv.mask = TVIF_TEXT '獲取標(biāo)題文本
  tv.HTreeItem = hItem 'Item句柄
  tv.pszText = hStr
  tv.cchTextMax = 1023
  '發(fā)送TVM_GETITEM獲得標(biāo)題文本
  Call SendMessageRef(TreeView1.hwnd, TVM_GETITEM, 0, tv)
  '將標(biāo)題文本拷貝到字符串a(chǎn)str中
  CopyMemory astr, hStr, 1024
  bstr = Left$(astr, (InStr(astr, Chr(0)) - 1))
  TreeView1.ToolTipText = bstr
  '釋放分配的內(nèi)存空間
  GlobalFree hStr
  End If
  Exit Sub
errLab:
  Resume Next
??? End Sub
運行上面的程序,當(dāng)光標(biāo)在 TreeView1上面移動時,TreeView1的 ToolTips就會根據(jù)光標(biāo)所在的不
同標(biāo)題行而變動?
SendMessage函數(shù)應(yīng)用 (三)
? 介紹關(guān)于RichTextBox(簡稱RTF)控件的消息和ListView控件的消息控制。
1.在Windows消息中,以EM_開頭的消息是專門控制TextBox類控件和RTF類控件的。下面介紹的是如何利
用 EM_ 消息實現(xiàn)向 RichTextBox 中粘貼文本和位圖。在 EM_消息中,有一個 EM_PASTESPECIAL 消息
可以從剪貼板中獲取文本或者位圖類數(shù)據(jù)并拷貝到 RTF 上。
  運行程序,點擊Command1,可以將剪貼板中的數(shù)據(jù)(位圖或者文本)拷貝到RichTextBox1上。
  在 EM_PASTESPECIAL 消息中,wParam 定義剪貼板數(shù)據(jù)類型,lParam 定義一個 repastespecial
類型的數(shù)據(jù),其中的 dwAspect 說明數(shù)據(jù)以何種方式顯示到 RTF 對象上,如果是 DVASPECT_CONTENT,
則將整個數(shù)據(jù)顯示在 RTF 上,如果是 DVASPECT_ICON ,則只在 RTF 上顯示一個圖標(biāo)。
  經(jīng)試,repastespecial 格式?jīng)]有作用,因此參數(shù)4設(shè)為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
2.ListView控件也是Windows界面開發(fā)中重要的控件,典型的應(yīng)用就是Windows資源管理器中的文件列
表。而在VB中,ListView控件包含在Microsoft Windows Common Control 6.0(也可能是5.0,視你的
VB或者系統(tǒng)版本而定)中。在 Windows API 中,有一系列的以 LVM_開頭的消息值,這些消息就是擴展
ListView控件所特定的消息值,下面的范例介紹如何通過LVM_消息設(shè)置ListView控件中圖標(biāo)的間距。范
例如下:
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 消息來控制圖標(biāo)間距。其中SendMessage中的參數(shù)lParam定義圖標(biāo)間距,
高位為縱向間距,低位為橫向間距,在上面的范例中,我們將圖標(biāo)的縱向間距定義為60像素,橫向間距
定義為190像素?
  
SendMessage函數(shù)的應(yīng)用 (四)
1,獲得光標(biāo)位置和字符個數(shù).
Cpos = SendMessage(Text1.hwnd, 187, -1, 0) '光標(biāo)所在行的首字符在文本中的位置
Lpos = SendMessage(Text1.hwnd, 201, Cpos, 0) '光標(biāo)所在的行號
Line = SendMessage(Text1.hwnd, 193, Cpos, 0) '這行的字符數(shù).
2.獲取第N行的文本
Dim ST As String
ST = Space(110) '必須要事先賦空格
Line=SendMessage(text1.hwnd,196, N-1, ByVal ST 'ST返回獲取到的文本,Line返回文本的長度字節(jié)數(shù)
'下面的未成功
Dim str(256) As Byte, K As Integer
str(1) = 1 '最大允許存放256個字符
K = SendMessage(Text1.hwnd, 196, 2, str(0)) '獲取第3行的數(shù)據(jù)放在str中
Text1.Text = StrConv(str, vbUnicode) '轉(zhuǎn)換為字符串后顯示
  說明:在調(diào)用SendMessage獲取第N行字符串時,lParam需要說明為字節(jié)數(shù)組,在調(diào)用完成后,再將
字節(jié)數(shù)組轉(zhuǎn)換為字符串;另外,調(diào)用前必須在lParam的前兩個字節(jié)指明允許存放的最大長度,其中第一
個字節(jié)為低位,第二個字節(jié)為高位,本例將高位(即str(1))置1.說明最大允許存放256個字符。
3.開關(guān)顯示器.
SendMessage Handle, WM_SYSCOMMAND, SC_MONITORPOWER, 0 '關(guān)閉顯示器.
SendMessage Handle, WM_SYSCOMMAND, SC_MONITORPOWER, -1 '打開顯示器
4.程序控制拉下或收起組合框的下拉列表
?? 一般情況下,為了拉下或收起組合框的下拉列表,需要用鍵盤或鼠標(biāo)進行操作,而有時我們希望程
序運行的某個時刻自動拉出下拉列表(比如在一些演示程序中),為了實現(xiàn)這個目的,我們也只有借助
于SendMessage函數(shù),方法是發(fā)一個CB_SHOWDROPDOWN(&H14F)消息給組合框。
?? 在發(fā)CB_SHOWDROPDOWN消息時,wParam參數(shù)決定了是拉下列表(=True)還是收起表(=False),
lParam無用(設(shè)為0)。
?? 為說明具體的使用方法,下面提供簡單的程序片段:
Const CB_SHOWDROPDOWN = &H14F
?? 當(dāng)程序中某處需要拉下組合框Combol的列表時,調(diào)用如下語句:
SendMessage Combol.hwnd, CB_SHOWDROPDOWN, True, 0
?? 當(dāng)需要收起組合框Combol的列表時,調(diào)用如下語句:
SendMessage Combol.hwnd, CB_SHOWDROPDOWNN, False, 0
5. 返回控件中顯示的第一行的行號。
LineNo = SendMessageBynum(CTextBox.hwnd, EM_GETFIRSTVISIBLELINE, 0, 0)
6.下面的函數(shù)能夠滾動控件,不過在滾動之前最好判斷控件的文本行數(shù)和能夠顯示的行數(shù),以免滾動時
發(fā)生混亂?函數(shù)SendMessageBynum是SendMessage函數(shù)的安全聲明函數(shù) , 其定義與SendMessage函數(shù)完全
相同 , 只是函數(shù)名不同?
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.下面的函數(shù)將返回控件能顯示的行數(shù):(經(jīng)試,總是引起程序崩潰)
'獲取當(dāng)前字體的矩形區(qū)域(即字體的高度與平均寬度等信息)
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定義的字符高度的頂部空間數(shù)目
? tmExternalLeading As Long? '加在兩行之間的空間數(shù)目
? tmAveCharWidth As Long???? '平均字符寬度
? tmMaxCharWidth As Long???? '最寬字符的寬度
? tmWeight As Long?????????? '字體的粗細(xì)輕重程度
? tmOverhang As Long???????? '加入某些拼接字體上的附加高度
? tmDigitizedAspectX As Long '字體設(shè)計所針對的設(shè)備水平方向
? tmDigitizedAspectY As Long '字體設(shè)計所針對的設(shè)備垂直方向
? 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
8.設(shè)置控件的左邊距。
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函數(shù)還可以實現(xiàn)一些有趣的效果:
例如在按鈕的Click事件中加入如下語句:
SendMessage(Command1.hWnd,BM_SETSTYLE,BS_RADIOBUTTON,1)'BM_SETSTYLE = &HF4,BS_RADIOBUTTON = &H4
  運行后點擊按鈕,就可以把按鈕變成一個收音機按鈕(經(jīng)試,變成一個圓孔,有點象單選按紐)。
如要得到圓形或橢圓形按紐可使用另外2個API函數(shù):
hDC = CreateEllipticRgn(3, 3, 25, 25) '試驗成功,這兩個函數(shù)也用于創(chuàng)建圓形窗體
SetWindowRgn Command1.hwnd, hDC, True
DeleteObject hDC
10.窗體操作
Public Const WM_SYSCOMMAND = &H112
Public Const SC_CLOSE = &HF060 '關(guān)閉窗體
Public Const SC_MINIMIZE = &HF020 '最小化窗體
Public Const SC_MAXIMIZE = &HF030 '最大化窗體
Public Const SC_RESTORE = &HF120 '恢復(fù)窗體大小
Public Const WM_SETTEXT = &HC '設(shè)置窗體的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) '設(shè)置窗體的Caption,由于Text1.text屬于Variant類型,所以一定先要用CStr把它轉(zhuǎn)換成字符串
? 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& '窗體恢復(fù)原來的大小
? Case 5: SendMessage Me.hwnd, WM_SYSCOMMAND, SC_CLOSE, ByVal 0& '關(guān)閉窗體
End Select
End Sub
11.文本垂直居中:
  實現(xiàn)這個效果首先TextBox的MultiLine屬性必須為True(多行文本,其實這個屬性關(guān)系創(chuàng)建TextBox內(nèi)部
使用哪個類,因此一旦創(chuàng)建就不能修改這個屬性,所以不能在代碼中修改這個屬性)
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) '獲得窗口區(qū)域的邊界
?? '進行位置數(shù)據(jù)計算
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
?? '數(shù)據(jù)計算完畢,再發(fā)送EM_SETRECTNP消息(為一個編輯控件設(shè)置格式化矩形,與EM_SETRECT類似,只是控件此時不會重畫)
Call SendMessage(mText.hwnd, EM_SETRECTNP, 0&, rc)
mText.Refresh
End Sub
12.調(diào)整邊距:
  如果你查看TextBox中常用的消息,你會發(fā)現(xiàn)有這樣一對消息:EM_GETMARGINS 和 EM_SETMARGINS,MSDN的解
釋是:獲取和設(shè)置編輯控件的左、右邊距(不得用于NT3.51)。具體是左還是右由該消息的參數(shù)決定。
  這樣做有什么意義呢?有的時候如果你想在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
SendMessage函數(shù)應(yīng)用 (五)
??? RichEdit控件的正文操作
一?正文搜索
???? RichEdit 控件具有幾種正文操作,搜索指定正文就是其中的一種。搜索正文是通過發(fā)送
EM_FINDTEXT 或者 EM_FINDTEXTEX 消息來完成的。這兩個消息有一點很小的不同點。
1.EM_FINDTEXT
 wParam=搜索選項,可以是下面3個參數(shù)的任意組合值(這些選項對 EM_FINDTEXT 和 EM_FINDTEXTEX
都是一樣的):
①FR_DOWN(&H1):搜索方向。如果指定了這個標(biāo)志值,搜索操作從當(dāng)前選定的 end 位置開始,直到控件
  中正文的 end 位置結(jié)束(向下搜索)。這個標(biāo)志影響 RichEdit 2.0 和以后版本,是 RichEdit 1.0
  的缺省行為。RichEdit 2.0或以后版本的缺省行為是:在當(dāng)前選定正文內(nèi)的從結(jié)尾搜索到開始位置
  (向前搜索)。概括來說就是,如果你使用 RichEdit 1.0, 無論你做什么都沒法影響搜索的方向,它
  總使用向后搜索。但是如果你使用 RichEdit 2.0 而且你想使用向后搜索的話,你必須指定這個標(biāo)
  志值,否則使用的是向前搜索了。
②FR_MATCHCASE (&H4): 區(qū)分大小寫?
③FR_WHOLEWORD (&H2): 匹配指定搜索串的整個詞?
 lParam = FINDTEXT 結(jié)構(gòu)的指針。
Type FINDTEXT??????? 'STRUCT
? chrg As CHARRANGE? '
? lpstrText As Long
End Type
? chrg 是一個 CHARRANGE 結(jié)構(gòu),其定義如下:
Type CHARRANGE?????? 'STRUCT
? cpMin As Long????? '包含字符數(shù)組中第一個字符的字符索引
? cpMax As Long????? '包含緊跟在字符數(shù)組中最后一個字符的字符的字符索引
End Type
  基本上,要搜索一個正文串,你必須指定要搜索的字符范圍。cpMin 和 cpMax 的具體意義根據(jù)搜索是向
后還是向前是不同的?
  如果是向后搜索,cpMin 指定搜索的開始字符索引,而 cpMax 則是結(jié)束字符索引。
  如果是向前搜索,則反過來才對,也就是說 cpMin 包含結(jié)束字符索引而cpMax 包含開始字符索引。
? lpstrText 是要搜索的正文串的指針?
2.EM_FINDTEXTEX
  返回控件中跟搜索串匹配的的正文串的一個字符的索引。如果沒找到匹配的則返回 -1。
? wParam = 搜索選項,跟 EM_FINDTEXT 的一樣。
? lParam = FINDTEXTEX 結(jié)構(gòu)的指針。
Type FINDTEXTEX????? 'STRUCT
? chrg As CHARRANGE? '
? lpstrText As Long
? chrgText CHARRANGE 'CHARRANGE
End Type
? FINDTEXTEX 中開始的兩個成員是跟 FINDTEXT 結(jié)構(gòu)中的一樣的。
? chrgText 是一個 CHARRANGE 結(jié)構(gòu),如果搜索到匹配串的話,其開始/結(jié)束字符索引會被填入這個結(jié)構(gòu)中。
? EM_FINDTEXTEX 的返回值跟 EM_FINDTEXT的是一樣的。
? EM_FINDTEXT 跟 EM_FINDTEXTEX 的不同處:
FINDTEXTEX 結(jié)構(gòu)有一個另外的chrgText成員, 如果搜索到匹配串的話,其開始/結(jié)束字符索引會被填入這個成
員中。如果我們想對這個正文串進行更多的正文操作的話,有這個就方便多了。
二、替換/插入正文
? RichEdit 控件提供了 EM_SETTEXTEX 來進行正文替換/插入操作。這個消息混合了 WM_SETTEXT 和
EM_REPLACESEL 的功能.它具有以下語法:
? wParam = SETTEXTEX 結(jié)構(gòu)的指針。
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 來編程選擇正文.其中任意的一個都可以工作的很好。
要使用哪一個消息要根據(jù)可用的字符索引格式來選擇。如果它們保存在一個 CHARRANGE 結(jié)構(gòu)中,則使用
EM_EXSETSEL更容易實現(xiàn)?
? EM_EXSETSEL
? wParam = 沒有使用,必須為 0 。
? lParam = CHARRANGE 結(jié)構(gòu)的指針,包含想要選定的正文字符范圍。
四 事件通知
? 在使用多行Edit控件時,你必須子類化它以便得到輸入信息象鼠標(biāo)/鍵盤事件等。RichEdit 控件提供了一
個更好的方案,它可以把這些消息通知父窗口。為了注冊得到通知消息,父窗口發(fā)送 EM_SETEVENTMASK 消息
給 RichEdit 控件,指定它對哪些消息感興趣。
??? EM_SETEVENTMASK 具有以下的語法:
wParam? 沒有使用,必須為 0 。
lParam = 事件掩碼值,可以是以下標(biāo)志值的任意組合:
? ENM_CHANGE 發(fā)送 EN_CHANGE 通知
? ENM_CORRECTTEXT 發(fā)送 EN_CORRECTTEXT 通知
? ENM_DRAGDROPDONE 發(fā)送 EN_DRAGDROPDONE 通知
? ENM_DROPFILES 發(fā)送 EN_DROPFILES 通知
? ENM_KEYEVENTS 為鍵盤消息發(fā)送 EN_MSGFILTER 通知
? ENM_LINK Rich Edit 2.0 或以后版本: 當(dāng)鼠標(biāo)在具有 CFE_LINK 風(fēng)格的正文上面移過,而且執(zhí)行了一個
或幾個鼠標(biāo)動作時,就發(fā)送 EN_LINK 通知。
? ENM_MOUSEEVENTS 為鼠標(biāo)消息發(fā)送 EN_MSGFILTER 通知。
? ENM_OBJECTPOSITIONS 發(fā)送 EN_OBJECTPOSITIONS 通知
? ENM_PROTECTED 發(fā)送 EN_PROTECTED 通知
? ENM_REQUESTRESIZE 發(fā)送 EN_REQUESTRESIZE 通知
? ENM_SCROLL 發(fā)送 EN_HSCROLL 和 EN_VSCROLL 通知
? ENM_SCROLLEVENTS 為鼠標(biāo)滑輪發(fā)送 EN_MSGFILTER 通知。
? ENM_SELCHANGE 發(fā)送 EN_SELCHANGE 通知
? ENM_UPDATE 發(fā)送 EN_UPDATE 通知
? Rich Edit 2.0 和以后版本: 這個標(biāo)志值會被忽略,而經(jīng)常發(fā)送 EN_UPDATE 通知。然而如果 RichEdit
3.0 模擬 RichEdit 1.0的話,你必須使用這個標(biāo)志值來發(fā)送 EN_UPDATE 通知
? 上面的所有通知都被做為 WM_NOTIFY 消息來發(fā)送:你必須檢查 NMHDR 結(jié)構(gòu)的 code 成員來得到通知消
息。譬如,如果你想注冊得到鼠標(biāo)消息(也就是說,你想提供一給上下文相關(guān)的彈出菜單)

轉(zhuǎn)載于:https://www.cnblogs.com/wangminbai/archive/2008/03/14/1105002.html

總結(jié)

以上是生活随笔為你收集整理的SendMessage函数的常用消息及其应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。