正文

SendMessage函数应用(二)2005-09-27 13:27:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/iamben250/5409.html

分享到:








在上一篇文章中我向大家介绍了关于ListBox类控件消息的应用,在这一章我将向大家?br />樯苋绾卫孟⒉倏豑extBox类控件。


1、获得光标所在的行和列
一般的比较完善的文本编辑器一般都有在状态栏中显示当前光标所在行和列的功能。利
用SendMessage向TextBox控件发送编辑控件类型消息。也可以实现这样的功能。下面首先来
看程序,然后再分析。
首先在VB中建立一个新工程,并在Form1中加入一个TextBox控件和两个Label控件。将T
extBox控件的MultiLine属性设置为True。然后在Form1的代码窗口中加入如下代码:


Option Explicit


Private Declare Function SendMessage Lib "user32" Alias "SendMessageW" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
lParam As Any) As Long

Private Declare Function SendMessageByRef Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, wParam As Long, _
lParam As Long) As Long

Const EM_LINEFROMCHAR = &HC9
Const EM_LINEINDEX = &HBB
Const EM_GETLINE = &HC4
Const EM_GETSEL = &HB0


Dim iLineX, iLineY As Long


Sub GetCurPos(txtA As TextBox)
Dim l, l1, l2 As Long
Dim astr As String * 256

l = SendMessage(txtA.hwnd, EM_LINEINDEX, -1, 0)
iLineY = SendMessage(txtA.hwnd, EM_LINEFROMCHAR, l, 0)

SendMessageByRef txtA.hwnd, EM_GETSEL, l1, l2
iLineX = l1 - l
Label1.Caption = "列:" + Str(iLineX)
Label2.Caption = "行:" + Str(iLineY)
End Sub


Private Sub Form_Load()
Dim iFile
Dim astr As String

Label1.Height = 300: Label2.Height = 300
Text1.Left = 0: Text1.Top = 0
Text1.Text = ""
Label1.Caption = ""
Label2.Caption = ""

iFile = FreeFile
Open "C:windowsreadme.txt" For Input As #iFile
Do
Line Input #iFile, astr
Text1.Text = Text1.Text + astr + vbCrLf
Loop Until EOF(iFile)
Close iFile
End Sub


Private Sub Form_Resize()
Label1.Top = Me.ScaleHeight - 300
Label2.Top = Me.ScaleHeight - 300


Label1.Left = 0: Label2.Left = 1200
Label1.Width = 1200
Label2.Width = 1200

Text1.Width = Me.ScaleWidth
Text1.Height = Me.ScaleHeight - Label1.Height
End Sub


Private Sub Text1_Click()
GetCurPos Text1
End Sub


Private Sub Text1_KeyUp(KeyCode As Integer, Shift As Integer)
GetCurPos Text1
End Sub

在运行程序前,确保在你的硬盘上有 c:windowsreadme.txt 这个文件。否则程序会出错。然后运行程序。当在编辑文本时,可以看到在窗口底部可以显
示当前光标所在的行、列值。在上面的程序中。我们首先发送EM_LINEINDEX消息,发送该消
息可以返回某一行的第一个字符在整个文本控件中的位置,如果wParam参数设置为- 1,则返回当前行的字符位置。然后发送EM_LINEFROMCHAR,发送该消息可以根据参数wParam
指定的字符位置返回该字符所在的行号,文本第一行的位置为0。这样使用这两个消息就获?br /> 玫鼻肮獗晁诘男泻拧R〉昧泻牛紫确⑺虴M_GETSEL消息,发送该消息返回当前被选中
文本的起始位置,如果没有文本被选中,则返回当前光标所在字符在文本中的位置。由于上
面的EM_LINEINDEX消息返回的是当前行的第一个字符在文本中的位置。所以将两值相减,就
是光标所在字符的列位置。在上面的程序中,如果你的文本中有中文字符的话,当你的光标
在中文字符中移动一个位置,你会看到标签中的列位置增加了2,这是由于SendMessage发送
的消息所得到的结果是不支持中文的,它将一个中文字算做两个字符。这也算是程序中的一
个Bug吧(这也就是为什么我要使用EM_GETSEL消息而不直接使用TextBox控件的SelStart属?br /> 岳椿袢」獗晁谧址恢昧耍蛭绻褂肧elStart返回的值将一个中文算一个字符,同E
M_LINEINDEX返回值相减有可能得到负值),如果你有什么更好的建议,欢迎到我的主页 http://member.netease.com/~blackcat同我讨论。


2、获得文本控件中整行文本
利用EM_GETLINE消息我们可以获得文本控件中某一行的文本。具体的范例如下:


Option Explicit


Private Declare Function SendMessage Lib "user32" Alias "SendMessageW" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
lParam As Any) As Long
Private Declare Function SendMessageStr Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
ByVal lParam As String) As Long

Const EM_LINEFROMCHAR = &HC9
Const EM_LINEINDEX = &HBB
Const EM_GETLINE = &HC4


Private Sub Text1_Click()
Dim astr As String
Dim l, iLineY As Long

astr = Space(1024)
l = SendMessage(Text1.hwnd, EM_LINEINDEX, -1, 0)
iLineY = SendMessage(Text1.hwnd, EM_LINEFROMCHAR, l, 0)
l = SendMessageStr(Text1.hwnd, EM_GETLINE, iLineY, ByVal astr)
Me.CurrentX = 30: Me.CurrentY = 30
Me.Print "该行包含文本长度:" + Str(l)
Text2.Text = Trim(astr)
End Sub


要运行上面的程序,首先你要在Form中加入两个TextBox控件,并将Text1的MultiLine?br /> 粜陨柚梦猅rue。然后运行程序,在text1中点击鼠标,Text2中就会显示光标所在行的文本?br />?


3、其它消息
下面介绍一些控制TextBox控件行为的消息
EM_GETFIRSTVISIBLELINE
发送EM_GETFIRSTVISIBLELINE消息可以获得文本控件中处于可见位置的最顶部的文本所
在的行。如果消息处理成功,将返回该行的索引,以0为基数。
EM_LINESCROLL
发送该消息可以控制textBox水平或垂直滚动。参数wParam指定水平滚动的字符数。参?br />齦Param指定垂直滚动的行数,定义以及调用方法如下:

Private Declare Function SendMessage Lib "user32" Alias "SendMessageW" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
lParam As Any) As Long

Const EM_LINESCROLL = &HB6

SendMessage Text1.hwnd, EM_LINESCROLL, 5, ByVal 1 '将Text1中的文本向下滚动1行,向右滚动5个字符


EM_SETREADONLY
发送该消息可以设置文本控件是否具有只读属性,如果将SendMessage参数wParam设置?br />猅rue,则控件具有只读属性,否则控件可读写。范例如下:

Const EM_SETREADONLY = &HCF
SendMessage Text1.hwnd, EM_SETREADONLY, True, 0 '设置text1为只读


EM_UNDO
发送该消息将使文本控件回复上一次的操作,相当于运行时在文本控件的右键菜单中选
择"撤销"操作。


阅读(3316) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册