VB与API学习笔记(4)消息传递
来源:互联网 发布:2003excel查找重复数据 编辑:程序博客网 时间:2024/06/04 18:58
windows是以消息为基础的。
学一个SendMessage传送消息(命令)的API
Option Explicit'发送消息命令'hwnd接收消息的句柄,wMsg消息的编号(类型)'wParam消息的第一参数'IParam消息的第二参数,此参数是传址,为了传值,前须加byvalPrivate Declare Function SendMessage _ Lib "user32" _ Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As LongPrivate Const WM_SYSCOMMAND = &H112Private Const SC_MAXIMIZE = &HF030&Private Const WM_SETTEXT = &HCPrivate Const WM_GETTEXT = &HDPrivate Sub Command1_Click() Dim s As String SendMessage Me.hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, ByVal 0& '最大化 SendMessage Me.hwnd, WM_SETTEXT, 0, ByVal "新的标题" '设置窗体标题 '为返回值做准备 s = String(80, Chr(0)) SendMessage Me.hwnd, WM_GETTEXT, Len(s), ByVal s '返回窗体标题 s = Left$(s, InStr(s, Chr(0)) - 1) Print sEnd Sub'可以看到第二参数情况:'传数据0 byval 0&'字符串常数 byval "新的标题"'字符串变量 byval s 这是取回返回值时
上面可以看到消息种类有:WM_GETTEXT,WM_SETTEXT,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 设置选择区域
视觉上的滚动如下:
Private Declare Function SendMessage _ Lib "user32" _ Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As LongPrivate Const EM_LINESCROLL = &HB6Private Sub Command1_Click() '注意卷动受“视察”限制,最后刚好满足视窗时,不再上卷,同理左右卷。同时加上滚动条,可看出效果。' SendMessage Text1.hwnd, EM_LINESCROLL, 0, ByVal 9 '下卷3行' SendMessage Text1.hwnd, EM_LINESCROLL, 0, ByVal -1 '上卷1行' SendMessage Text1.hwnd, EM_LINESCROLL, 1, ByVal 0 '右卷1行' SendMessage Text1.hwnd, EM_LINESCROLL, -1, ByVal 0 '左卷1行 SendMessage Text1.hwnd, EM_LINESCROLL, 1, ByVal 1 '同时向下向右卷一行End SubPrivate Sub Form_Load() Text1.Text = "第一行.........................." & vbCrLf & _ "第二行.........................." & vbCrLf & _ "第三行.........................." & vbCrLf & _ "第四行.........................." & vbCrLf & _ "第五行.........................." & vbCrLf & _ "第六行.........................." & vbCrLf & _ "第七行.........................." & vbCrLf & _ "第八行.........................." & vbCrLf & _ "第九行.........................." & vbCrLf & _ "第十行.........................." & vbCrLfEnd SubInStr
注意:第一参数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,0,byval 0&) '后两参数无作用,用0
读取某行字串:EM_GetLine
Option ExplicitPrivate Declare Sub RtlMoveMemory _ Lib "kernel32" (Dest As Any, _ Src As Any, _ ByVal Length 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 LongPrivate Const EM_LINESCROLL = &HB6Private Const EM_GETLINECOUNT = &HBAPrivate Const EM_LINEINDEX = &HBBPrivate Const EM_LINELENGTH = &HC1Private Const EM_GETLINE = &HC4 '取得某行串,返回值在最后一参数中Private Sub Command1_Click() Dim a As Long a = SendMessage(Text1.hwnd, EM_GETLINECOUNT, 0, ByVal 0&) Print a '显示11行,为什么?因为最后有一个回车换行,将计算为第11行。注意行索引是从0开始的End SubPrivate Sub Command2_Click() Dim s As String Dim pos As Long Dim Length As Integer '先取出该行的长度 pos = SendMessage(Text1.hwnd, EM_LINEINDEX, 3, ByVal 0&) '3行首字母索引 Length = SendMessage(Text1.hwnd, EM_LINELENGTH, pos, ByVal 0&) '该索引所在行的长度 '初始化返回字串 s = String$(Length, Chr(0)) '行串长度初始化 RtlMoveMemory ByVal s, Length, 2 '前两字节指定字串总长,不指定取不出字串 SendMessage Text1.hwnd, EM_GETLINE, 3, ByVal s Print s '显示第4行,因为行索引是从0开始的。 End SubPrivate Sub Form_Load() Text1.Text = "第一行..........................1" & vbCrLf & _ "第二行..........................2" & vbCrLf & _ "第三行..........................3" & vbCrLf & _ "第四行..........................4" & vbCrLf & _ "第五行..........................5" & vbCrLf & _ "第六行..........................6" & vbCrLf & _ "第七行..........................7" & vbCrLf & _ "第八行..........................8" & vbCrLf & _ "第九行..........................9" & vbCrLf & _ "第十行..........................10" & vbCrLfEnd Sub
读取字符串位置:EM_CharFromPos=&HD7& '在win32api.txt中没有,手动添加
CharPos = SendMessage(txtText1.hwnd, EM_CharFromPos, 0, ByVal pos)
wParam:无用,用0
IParam: Long, 传入相对于TextBox左上角的像素位置,&H11223344,高位两字节是Y坐标,低两字节是X坐标。
即:Y*65536+X. 注意是像素,若为Twip要转换
返回值: Long, &H11223344,高两字节是行数,低两字节是字符位置。CharPos\65536即行,CharPos mod 65536即字符位置。
Private Declare Function SendMessage _ Lib "user32" _ Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ lParam As Any) As LongPrivate Const EM_CharFromPos As Long = &HD7&Private Sub txtText1_MouseDown(Button As Integer, _ Shift As Integer, _ X As Single, _ Y As Single) Dim pos As Long '传入位置 Dim CharPos As Long '传出位置 pos = Y / Screen.TwipsPerPixelY * 65536 + X / Screen.TwipsPerPixelY CharPos = SendMessage(txtText1.hwnd, EM_CharFromPos, 0, ByVal pos) '转入,获取行,位置 Print "第" & CharPos \ 65536 & "行" '提取高两字节 Print "第" & CharPos Mod 65536 & "个字符" '提取低两字节 End Sub
再次可以看到,行索引是从0开始,字符位置是从最开始算起的(注意上面因为回车与换行算两个字符,所以位置是9)
获取鼠标所在位置的单词:
思路:
1、取得鼠标的位置
2、从鼠标位置分别向前和向后循环检查分隔符的位置,以确定整个单词的起点和终点。
3、根据起点和终点提取单词。
Private Declare Function SendMessage _ Lib "user32" _ Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ lParam As Any) As LongPrivate Const EM_CharFromPos As Long = &HD7&Private Sub txtText1_MouseDown(Button As Integer, _ Shift As Integer, _ X As Single, _ Y As Single) Dim pos As Long '传入位置 Dim CharPos As Long '传出位置 Dim i As Integer '字符位置 pos = Y / Screen.TwipsPerPixelY * 65536 + X / Screen.TwipsPerPixelY CharPos = SendMessage(txtText1.hwnd, EM_CharFromPos, 0, ByVal pos) '转入,获取行,位置 i = CharPos Mod 65536 Print GetWord(txtText1, i)End SubPrivate Function IsDelimiter(ByVal char As Byte) As Boolean '判断是否是分隔号 Dim s As String s = Chr(char) IsDelimiter = False If s = " " Or s = "." Or s = "?" Or s = vbCr Or s = vbLf Then '分隔符自定 IsDelimiter = True End IfEnd FunctionPrivate Function GetWord(txtBox As TextBox, pos As Integer) As String '取得鼠标所在单词 Dim pos1 As Integer, pos2 As Integer Dim b() As Byte, i As Integer b = StrConv(txtBox, vbFromUnicode) pos1 = 0 pos2 = UBound(b) '分别取得鼠标位置的前后分隔符位置,为下一步取单词作准备 For i = pos To 0 Step -1 '鼠标位置的前一个分隔符位置 If IsDelimiter(b(i)) Then pos1 = i + 1 Exit For End If Next For i = pos To pos2 '鼠标位置的后一个分隔符位置 If IsDelimiter(b(i)) Then pos2 = i - 1 Exit For End If Next If pos2 > pos1 Then ReDim b2(pos2 - pos1) As Byte '变量上下限定义时,用ReDim For i = pos1 To pos2 b2(i - pos1) = b(i) Next GetWord = StrConv(b2, vbUnicode) Else GetWord = "" End If 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与API学习笔记(4)消息传递
- VB与API学习笔记(2)Unicode与参数
- VB与API学习笔记(1)热身
- VB与API学习笔记(3)资源文件
- WIN32 API/WTL 学习笔记(消息传递过程)
- VB与API学习笔记(7)动画与特效
- VB与API学习笔记(6)绘图DC
- VB与API学习笔记(8)GDI对象
- VB与API学习笔记(9)程序间的会话
- Handler消息传递学习笔记
- VB与API学习笔记(5) 认识DC(Device Context简介)
- 深入浅出MFC学习笔记(第9章:消息映射与命令传递。)
- 深入浅出MFC学习笔记(第9章:消息映射与命令传递。)
- 学习VB前应了解windows的消息传递
- VC++ 学习笔记(11)——传递自定义消息
- Akka学习笔记(六):消息传递可靠性
- android学习笔记(七):Handler消息传递机制
- android学习笔记之Intent消息传递
- Statistical Formulas For Programmers
- 接入层的流程和非接入层
- 红黑树的插入和删除
- 【Android MyEclipse】no projects are found to import 如何解决 .
- Resources.Load 与 Resources.LoadAssetAtPath 注意
- VB与API学习笔记(4)消息传递
- 自己实现的水版MPI_Bcast(使用binomial tree,跟mpich2实现思路一样)
- JQuery实现二级 select框联动选择
- C#串口操作类 【转】
- Java异常详解
- frameset使用方法
- oracle开发中的nvl函数
- 使用NSNotificationCenter 事件通知
- Privacy Policy of the The apk