现在的位置: 首页 > 编程语言 > 正文

SendMessage 的各种参数

2018年09月24日 编程语言 ⁄ 共 26538字 ⁄ 字号 评论关闭

SendMessage函数的常用消息及其应用(有点长,希望能对大家有所帮助)
函数原型:

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 使用的参数 

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. 合并在一起演示。
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像素高
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 
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

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

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 成员来得到通知消
息。譬如,如果你想注册得到鼠标消息(也就是说,你想提供一给上下文相关的弹出菜单)

【上篇】
【下篇】

抱歉!评论已关闭.