消息传递在VB中的应用

来源:互联网 发布:c语言打开文件 编辑:程序博客网 时间:2024/06/06 02:58
有些窗体在设计时会定义一些特殊的功能消息,而当我们传递这些消息给这类窗体时,这类窗口就会执行某段程序,并返回执行的结果。为了让程序可以送出消息,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