有些窗体在设计时会定义一些特殊的功能消息,而当我们传递这些消息给这类窗体时,这类窗口就会执行某段程序,并返回执行的结果。为了让程序可以送出消息,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
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