VB与API学习笔记(4)消息传递

前端之家收集整理的这篇文章主要介绍了VB与API学习笔记(4)消息传递前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

windows是以消息为基础的。

学一个SendMessage传送消息(命令)的API

  1. Option Explicit
  2. '发送消息命令
  3. 'hwnd接收消息的句柄,wMsg消息的编号(类型)
  4. 'wParam消息的第一参数
  5. 'IParam消息的第二参数,此参数是传址,为了传值,前须加byval
  6.  
  7. Private Declare Function SendMessage _
  8. Lib "user32" _
  9. Alias "SendMessageA" (ByVal hwnd As Long,ByVal wMsg As Long,ByVal wParam As Long,lParam As Any) As Long
  10.  
  11. Private Const WM_SYSCOMMAND = &H112
  12. Private Const SC_MAXIMIZE = &HF030&
  13. Private Const WM_SETTEXT = &HC
  14. Private Const WM_GETTEXT = &HD
  15.  
  16. Private Sub Command1_Click()
  17. Dim s As String
  18. SendMessage Me.hwnd,WM_SYSCOMMAND,SC_MAXIMIZE,ByVal 0& '最大化
  19. SendMessage Me.hwnd,WM_SETTEXT,ByVal "新的标题" '设置窗体标题
  20. '为返回值做准备
  21. s = String(80,Chr(0))
  22. SendMessage Me.hwnd,WM_GETTEXT,Len(s),ByVal s '返回窗体标题
  23. s = Left$(s,InStr(s,Chr(0)) - 1)
  24. Print s
  25. End Sub
  26. '可以看到第二参数情况:
  27. '传数据0 byval 0&
  28. '字符串常数 byval "新的标题"
  29. '字符串变量 byval s 这是取回返回值时

上面可以看到消息种类有:WM_GETTEXT,WM_SYSCOMMAND

最后一种还有几个参数:SC_MINIMIZE,SC_RESTORE,SC_CLOSE和窗体的几个状态命令等同

注: WM即:windows message

SC即:system command


一、TEXTBox

对应VB有的:

事件:

En_Change change

En_KillFocus LostFocus

EN_SetFocus GotFocus

属性

EM_GetPasswordChar PasswordChar

EM_GetSel SelText,SelStart,SelLength

EM_LimitText MaxLength

EM_ReplaceSel SelText

EM_SetLimitText MaxLength

EM_SetPasswordChar PasswordChar

EM_SetReadOnly Locked

VB中没有的类型:

EM_LineScroll 以行为单位,卷动TextBox

EM_Scroll 以行或页为单位卷动

EM_GetLineCount 计算总行数

EM_GetLine 读取某一行的字符串

EM_LineIndex 读取某一行第一个字母在TextBox中的索引

EM_LineLength 读取某一字母所在行次的“行字符数” (即这一行的字符数)

EM_CharFromPos 读取鼠标所在位置的字符索引

EM_SetSel 设置选择区域


视觉上的滚动如下:

  1. Private Declare Function SendMessage _
  2. Lib "user32" _
  3. Alias "SendMessageA" (ByVal hwnd As Long,lParam As Any) As Long
  4.  
  5. Private Const EM_LINESCROLL = &HB6
  6.  
  7. Private Sub Command1_Click() '注意卷动受“视察”限制,最后刚好满足视窗时,不再上卷,同理左右卷。同时加上滚动条,可看出效果
  8. ' SendMessage Text1.hwnd,EM_LINESCROLL,ByVal 9 '下卷3行
  9. ' SendMessage Text1.hwnd,ByVal -1 '上卷1行
  10. ' SendMessage Text1.hwnd,1,ByVal 0 '右卷1行
  11. ' SendMessage Text1.hwnd,-1,ByVal 0 '左卷1行
  12. SendMessage Text1.hwnd,ByVal 1 '同时向下向右卷一行
  13. End Sub
  14.  
  15. Private Sub Form_Load()
  16. Text1.Text = "第一行.........................." & vbCrLf & _
  17. "第二行.........................." & vbCrLf & _
  18. "第三行.........................." & vbCrLf & _
  19. "第四行.........................." & vbCrLf & _
  20. "第五行.........................." & vbCrLf & _
  21. "第六行.........................." & vbCrLf & _
  22. "第七行.........................." & vbCrLf & _
  23. "第八行.........................." & vbCrLf & _
  24. "第九行.........................." & vbCrLf & _
  25. "第十行.........................." & vbCrLf
  26. End Sub
  27. InStr

注意:第一参数wParam是水平卷动,向下为正,向上为负

第二参数IParam是垂直卷动,向右为正,向左为负。 这两个受视窗限制。到“底”后不会再卷动

另一个卷动类型:EM_Scroll 是以行或页,由wParam具体指出:

wParam: SB_LineUp 向上一行

SB_LineDown 向下。。

SB_PageUp 向上一页

SB_PageDown 向下一页

SB:傻B,傻瓜式的:)

此时IParam无作用,用byval 0&

SentMessage Text1.hwnd,EM_Scroll,SB_PageDown,byval 0& '向下翻一页




获取总行数:EM_GetLineCount

LineCount=SendMessage(text1.hwnd,em_getlineCount,byval 0&) '后两参数无作用,用0


读取某行字串:EM_GetLine

  1. Option Explicit
  2. Private Declare Sub RtlMoveMemory _
  3. Lib "kernel32" (Dest As Any,_
  4. Src As Any,_
  5. ByVal Length As Long)
  6. Private Declare Function SendMessage _
  7. Lib "user32" _
  8. Alias "SendMessageA" (ByVal hwnd As Long,lParam As Any) As Long
  9.  
  10. Private Const EM_LINESCROLL = &HB6
  11. Private Const EM_GETLINECOUNT = &HBA
  12. Private Const EM_LINEINDEX = &HBB
  13. Private Const EM_LINELENGTH = &HC1
  14. Private Const EM_GETLINE = &HC4 '取得某行串,返回值在最后一参数中
  15.  
  16. Private Sub Command1_Click()
  17. Dim a As Long
  18. a = SendMessage(Text1.hwnd,EM_GETLINECOUNT,ByVal 0&)
  19. Print a '显示11行,为什么?因为最后有一个回车换行,将计算为第11行。注意行索引是从0开始的
  20. End Sub
  21.  
  22. Private Sub Command2_Click()
  23. Dim s As String
  24. Dim pos As Long
  25. Dim Length As Integer
  26. '先取出该行的长度
  27. pos = SendMessage(Text1.hwnd,EM_LINEINDEX,3,ByVal 0&) '3行首字母索引
  28. Length = SendMessage(Text1.hwnd,EM_LINELENGTH,pos,ByVal 0&) '该索引所在行的长度
  29. '初始化返回字串
  30. s = String$(Length,Chr(0)) '行串长度初始化
  31. RtlMoveMemory ByVal s,Length,2 '前两字节指定字串总长,不指定取不出字串
  32. SendMessage Text1.hwnd,EM_GETLINE,ByVal s
  33. Print s '显示第4行,因为行索引是从0开始的。
  34. End Sub
  35.  
  36. Private Sub Form_Load()
  37. Text1.Text = "第一行..........................1" & vbCrLf & _
  38. "第二行..........................2" & vbCrLf & _
  39. "第三行..........................3" & vbCrLf & _
  40. "第四行..........................4" & vbCrLf & _
  41. "第五行..........................5" & vbCrLf & _
  42. "第六行..........................6" & vbCrLf & _
  43. "第七行..........................7" & vbCrLf & _
  44. "第八行..........................8" & vbCrLf & _
  45. "第九行..........................9" & vbCrLf & _
  46. "第十行..........................10" & vbCrLf
  47.  
  48. End Sub

读取字符串位置:EM_CharFromPos=&HD7& '在win32api.txt中没有,手动添加

CharPos = SendMessage(txtText1.hwnd,EM_CharFromPos,ByVal pos)

wParam:无用,用0

IParam: Long, 传入相对于TextBox左上角的像素位置,&H11223344,高位两字节是Y坐标,低两字节是X坐标。

即:Y*65536+X. 注意是像素,若为Twip要转换

返回值: Long,&H11223344,高两字节是行数,低两字节是字符位置。CharPos\65536即行,CharPos mod 65536即字符位置。

  1. Private Declare Function SendMessage _
  2. Lib "user32" _
  3. Alias "SendMessageA" (ByVal hwnd As Long,_
  4. ByVal wMsg As Long,_
  5. ByVal wParam As Long,_
  6. lParam As Any) As Long
  7.  
  8. Private Const EM_CharFromPos As Long = &HD7&
  9.  
  10. Private Sub txtText1_MouseDown(Button As Integer,_
  11. Shift As Integer,_
  12. X As Single,_
  13. Y As Single)
  14.  
  15. Dim pos As Long '传入位置
  16.  
  17. Dim CharPos As Long '传出位置
  18. pos = Y / Screen.TwipsPerPixelY * 65536 + X / Screen.TwipsPerPixelY
  19. CharPos = SendMessage(txtText1.hwnd,ByVal pos) '转入,获取行,位置
  20. Print "第" & CharPos \ 65536 & "行" '提取高两字节
  21. Print "第" & CharPos Mod 65536 & "个字符" '提取低两字节
  22. End Sub


再次可以看到,行索引是从0开始,字符位置是从最开始算起的(注意上面因为回车与换行算两个字符,所以位置是9)



获取鼠标所在位置的单词:

思路:

1、取得鼠标的位置

2、从鼠标位置分别向前和向后循环检查分隔符的位置,以确定整个单词的起点和终点。

3、根据起点和终点提取单词。


  1. Private Declare Function SendMessage _
  2. Lib "user32" _
  3. Alias "SendMessageA" (ByVal hwnd As Long,_
  4. Y As Single)
  5.  
  6. Dim pos As Long '传入位置
  7.  
  8. Dim CharPos As Long '传出位置
  9. Dim i As Integer '字符位置
  10. pos = Y / Screen.TwipsPerPixelY * 65536 + X / Screen.TwipsPerPixelY
  11. CharPos = SendMessage(txtText1.hwnd,ByVal pos) '转入,获取行,位置
  12. i = CharPos Mod 65536
  13. Print GetWord(txtText1,i)
  14. End Sub
  15.  
  16. Private Function IsDelimiter(ByVal char As Byte) As Boolean '判断是否是分隔号
  17.  
  18. Dim s As String
  19.  
  20. s = Chr(char)
  21. IsDelimiter = False
  22.  
  23. If s = " " Or s = "." Or s = "?" Or s = vbCr Or s = vbLf Then '分隔符自定
  24. IsDelimiter = True
  25.  
  26. End If
  27.  
  28. End Function
  29.  
  30. Private Function GetWord(txtBox As TextBox,pos As Integer) As String '取得鼠标所在单词
  31.  
  32. Dim pos1 As Integer,pos2 As Integer
  33.  
  34. Dim b() As Byte,i As Integer
  35.  
  36. b = StrConv(txtBox,vbFromUnicode)
  37. pos1 = 0
  38. pos2 = UBound(b)
  39.  
  40. '分别取得鼠标位置的前后分隔符位置,为下一步取单词作准备
  41. For i = pos To 0 Step -1 '鼠标位置的前一个分隔符位置
  42.  
  43. If IsDelimiter(b(i)) Then
  44. pos1 = i + 1
  45. Exit For
  46.  
  47. End If
  48.  
  49. Next
  50.  
  51. For i = pos To pos2 '鼠标位置的后一个分隔符位置
  52.  
  53. If IsDelimiter(b(i)) Then
  54. pos2 = i - 1
  55. Exit For
  56.  
  57. End If
  58.  
  59. Next
  60.  
  61. If pos2 > pos1 Then
  62.  
  63. ReDim b2(pos2 - pos1) As Byte '变量上下限定义时,用ReDim
  64.  
  65. For i = pos1 To pos2
  66. b2(i - pos1) = b(i)
  67. Next
  68. GetWord = StrConv(b2,vbUnicode)
  69. Else
  70. GetWord = ""
  71.  
  72. End If
  73. End Function

看到这个程序不由得再次感叹,为啥要用vbformunicode,因为API是外国用的,不适用中国的双字节字符。为了适合中文(比如上面是

中英文混合字符),就得全转到字节方式,取得单词后,再回到unicode状态。所以上面的pos1,pos2是字节状态的位置,和字符的位置

是不同的。

因此若根据pos1,pos2来用:

text1.selstart=pos1

text1.sellength=pos2-pos1+1

来选择这个单词将会出错。



若要选择这个单词,再次用API: EM_SetSel

sendMessage txt.hwnd,Em_SetSel,pos1,byval cLng(pos2+1)

wParam: 起始位置

Iparam: 终点位置+1



二、listBox,Combo 这个两个的API感到用处不大。略过。

猜你在找的VB相关文章