有些窗体在设计时会定义一些特殊的功能消息,而当我们传递这些消息给这类窗体时,这类窗口就会执行某段程序,并返回执行的结果。为了让程序可以送出消息,Windows提供了SendMessage API函数。
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long | hWnd:接收消息的窗口;
wMsg:消息的编号;
wParam:消息的第一个参数;
lParam:消息的第二个参数。
wParam及lParam参数的意义会随着wMsg参数而变,因此我们要传递消息给某一个窗体时,除了了解该消息的意义外,还要了解wParam及lparam的意义。
lParam参数在SendMessage定义句中为"lParam As Any",因此它有以下几中写法:
当数值为 0 时,写成:ByVal 0&
当为字符串常数 时,写成:ByVal "字符串的内容"
当为字符串变量时,写成:ByVal S
第一个实例:对窗体进行操作
下面我们对窗体的几个消息进行解释和应用:WM_GETTEXT:读取窗体的Caption属性;WMSETTEXT:设置窗体的Caption属性;WM_SYSCOMMAND(wParam=SC_MAXIMIZE):将窗体的属性设置为2;WM_SYSCOMMAND(wParam=SC_MINIMIZE):将窗体的属性设置为1;WM_SYSCOMMAND(wParam=SC_RESTORE):将窗体的属性设置为0;WM_SYSCOMMAND(wParam=SC_CLOSE):Unload窗体.
下面我们在窗体上放置几个Command控件和一个Text控件:
 | 我们先把所需要的参数和API函数定义到模块里面:
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 Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long 双击Command中放入: 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 '读出窗体的Caption Text1.Text = Left(S, InStr(S, Chr(0)) - 1) Case 1 '因为Text1.text属于Variant类型,所以一定先要用CStr把它转换成字符串 SendMessage Me.hwnd, WM_SETTEXT, 0, ByVal CStr(Text1.Text)'设置窗体的Caption 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 | 第二个实例:TextBox的消息
消息 |
用途 |
EM_LINESCROLL |
以行为单位,卷动TexBox |
EM_SCROLL |
以行或页为单位,卷动TexBox |
EM_GETLINECOUNT |
读取TextBox的总行数 |
EM_GETLINE |
读取某一行的字符串 |
EM_LINEINDEX |
读取某一行的第一个字符在TextBox中的索引 |
EM_LINELENGTH |
读取某一字符索引所在行次的"行字符数" |
EM_CHARFROMPOS |
读取鼠标所在位置的字符索引 |
EM_SETSEL |
设置选取区域 | 在窗体上放置好相应的控件,如下:
在模块中定义好所需要的变量和函数:
Public Const EM_SCROLL = &HB5 '以行或页为单位,卷动TexBox Public Const SB_LINEUP = 0 '上卷一行 Public Const SB_LINEDOWN = 1 '下卷一行 Public Const SB_PAGEUP = 2 '上卷一页 Public Const SB_PAGEDOWN = 3 '下卷一页 Public Const EM_LINESCROLL = &HB6 '以行为单位,卷动TexBox Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long | 双击Command,写入以下代码:
Private Sub Command_Click(Index As Integer) Select Case Index Case 0 SendMessage Text1.hwnd, EM_SCROLL, SB_PAGEUP, ByVal 0&'上卷一页 Case 1 SendMessage Text1.hwnd, EM_SCROLL, SB_LINEUP, ByVal 0&'上卷一行 Case 2 SendMessage Text1.hwnd, EM_SCROLL, SB_LINEDOWN, ByVal 0&'下卷一行 Case 3 SendMessage Text1.hwnd, EM_SCROLL, SB_PAGEDOWN, ByVal 0&'下卷一页 Case 4 'Text1.text用来输入水平方向行数的TextBox,Text2.text:用来输入垂直方向行数的TextBox '因为lParam采用"As Any"的定义方式,所以我们传入是一定要将参数强制设置成Long类型 SendMessage Text1.hwnd, EM_LINESCROLL, Val(Text1.text), ByVal CLng(Val(Text2.text)) End Select End Sub | 第三个实例:ListBox的消息
消息 |
用途 |
LB_SELECTSTRING |
选取开头含有某个字符串的选项 |
LB_FINDSTRING |
搜寻开头含有某个字符串的选项 |
LB_FINDSTRINGEXACT |
搜寻完全相符的选项 |
SETHORIZONTALEXTENT |
设置水平滚动条的宽度 |
LB_ITEMFROMPOINT |
检测鼠标所在位置的选项 | 下面我们用一个例子来说明这些消息的具体用法:
在窗体上放置好一个Lable,Text,List,三个Command控件.并在List控件中输入字母,且最少有一行要超出List的水平宽度。
 | 在模块中定义相应的参数和函数:
Option Explicit Public Const LB_FINDSTRING = &H18F '搜寻开头含有某个字符串的选项 Public Const LB_FINDSTRINGEXACT = &H1A2 ‘搜寻完全相同的字符串的选项 Public Const LB_ITEMFROMPOINT = &H1A9 '检测鼠标所在的位置的选项
Public Const WM_USER = &H400 Public Const LB_GETITEMHEIGHT = (WM_USER + 34)'取得List的行间高度 Public Const LB_SETITEMHEIGHT = &H1A0 '设置得List的行间高度 Public Const WM_SETREDRAW = &HB
Public Const LB_SETHORIZONTALEXTENT = &H194 '设置水平滚动条 Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long 在Text1_Change中加入如下代码: Private Sub Text1_Change() Dim Search As String, Index As Long
Search = Text1.Text If Len(Search) > 0 Then Index = SendMessage(List1.hwnd, LB_FINDSTRING, -1, ByVal Search) '搜寻开头含有某个字符串的选项 List1.ListIndex = Index Else List1.ListIndex = 0 End If End Sub '下面的代码为设置水平滚动条的宽度 Private Sub Command2_Click() Dim max As Long, f As Font, i As Integer
Me.ScaleMode = vbPixels ' 以像素为单位 Set f = Me.Font ' 保留窗体的Font Set Me.Font = List1.Font ' 将List1的Font设置给窗体,便可用窗体的TextWidth方法来计算ListBox每一个选项的宽度 With List1 For i = 0 To .ListCount If Me.TextWidth(.List(i)) > max Then max = Me.TextWidth(.List(i)) End If Next End With max = max + 10 ' Set Me.Font = f ' 还原窗体的Font SendMessage List1.hwnd, LB_SETHORIZONTALEXTENT, max, ByVal 0& End Sub '当我们的鼠标在List中移动时可以检测鼠标所在的位置,其代码如下: Private Sub List1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) Dim lXPoint As Long Dim lYPoint As Long Dim lIndex As Long If Button = 0 Then ' 如果没有按钮被按下 lXPoint = CLng(X / Screen.TwipsPerPixelX)'List的宽度(以Pixel为单位) lYPoint = CLng(Y / Screen.TwipsPerPixelY)'List的高度(以pixel为单位) With List1 ' 获得当前的光标所在的的屏幕位置确定标题位置 lIndex = SendMessage(.hwnd, LB_ITEMFROMPOINT, 0, ByVal ((lYPoint * 65536) + lXPoint)) ' 显示提示行或清除提示行 If (lIndex >= 0) And (lIndex <= .ListCount) Then .ToolTipText = .List(lIndex) Else .ToolTipText = "" End If End With End If '我们也可以设置List的行间高度,代码如下: Private Sub Command1_Click() Dim i As Long '返回 listbox高度 i = SendMessage((List1.hwnd), LB_GETITEMHEIGHT, 0, &O0) '在原高度中增加一个值 i = i + 3 '设置高度 i = SendMessage((List1.hwnd), LB_SETITEMHEIGHT, 0, ByVal i) i = SendMessage((List1.hwnd), WM_SETREDRAW, True, 0&) End Sub |
 |
|