一般的比较完善的文本编辑器一般都有在状态栏中显示当前光标所在行和列的功能。利用SendMessage向TextBox 控件发送编辑控件类型消息。也可以实现这样的功能。下面首先来看程序,然后再分析。 首先在VB中建立一个新工程,并在Form1中加入一个TextBox控件和两个Label控件。将TextBox控件的MultiLine 属性设置为True。然后在Form1的代码窗口中加入如下代码:Option ExplicitPrivate 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 = &HB0Dim iLineX, iLineY As LongSub GetCurPos(txtA As TextBox) Dim l, l1, l2 As Long Dim astr As String * 256
SendMessageByRef txtA.hwnd, EM_GETSEL, l1, l2 iLineX = l1 - l Label1.Caption = "列:" + Str(iLineX) Label2.Caption = "行:" + Str(iLineY) End SubPrivate Sub Form_Load() Dim iFile Dim astr As String
iFile = FreeFile Open "C:\windows\readme.txt" For Input As #iFile Do Line Input #iFile, astr Text1.Text = Text1.Text + astr + vbCrLf Loop Until EOF(iFile) Close iFile End SubPrivate 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 SubPrivate Sub Text1_Click() GetCurPos Text1 End SubPrivate Sub Text1_KeyUp(KeyCode As Integer, Shift As Integer) GetCurPos Text1 End Sub 在运行程序前,确保在你的硬盘上有 c:\windows\readme.txt 这个文件。否则程序会出错。然后运行 程序。当在编辑文本时,可以看到在窗口底部可以显示当前光标所在的行、列值。 在上面的程序中。我们首先发送EM_LINEINDEX消息,发送该消息可以返回某一行的第一个字符在整个 文本控件中的位置,如果wParam参数设置为-1,则返回当前行的字符位置。然后发送EM_LINEFROMCHAR,发 送该消息可以根据参数wParam指定的字符位置返回该字符所在的行号,文本第一行的位置为0。这样使用这 两个消息就获得当前光标所在的行号。要取得列号,首先发送EM_GETSEL消息,发送该消息返回当前被选中 文本的起始位置,如果没有文本被选中,则返回当前光标所在字符在文本中的位置。由于上面的EM_LINEINDEX 消息返回的是当前行的第一个字符在文本中的位置。所以将两值相减,就是光标所在字符的列位置。
得到行数: Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long,lParam As Any) As Long Public Const EM_GETLINECOUNT=&HBA Public Const EM_GETLINE=&HC4 在Form1的代码模块中写如下代码: Private Sub Command1_Click() Dim str(256) As Byte str(1)=1 '最大允许存放256个字符 '获取总行数,结果显示在文本框txtLineCount中 txtlineCount=SendMessage(Text1.hwnd,EM_GETLINECOUNT,0,0) '获取第3行的数据放在str中,转换为字符串后显示在文本框txtString中 SendMessage Text1.hwnd,EM_GETLINE,2,str(0) txtString= StrConv(str,vbUnicode) End Sub
' 写个函数,以后用起来也方便。Option Explicit Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long Private Const EM_GETSEL = &HB0 Private Const EM_LINEFROMCHAR = &HC9 Private Const EM_LINEINDEX = &HBBPrivate Sub Command1_Click() Dim line As Long, col As Long GetTextCursorPos RichTextBox1.hwnd, line, col Debug.Print line, col End Sub' 获得文本框中光标的所在位置 ' hwnd 为文本框的句柄, LineNo 为光标所在的行数, ColNo 为光标所在的列数 Sub GetTextCursorPos(ByVal hwnd As Long, ByRef LineNo As Long, ByRef ColNo As Long) Dim i As Long, j As Long, k As Long Dim lParam As Long, wParam As Long i = SendMessage(hwnd, EM_GETSEL, wParam, lParam) j = i / 2 ^ 16 '取得目前光标前面有多少个字节 LineNo = SendMessage(hwnd, EM_LINEFROMCHAR, j, 0) '取得前面有多少行 LineNo = LineNo + 1 k = SendMessage(hwnd, EM_LINEINDEX, -1, 0) '取得目前光标所在行前面有多少个字节 ColNo = j - k + 1 End Sub
感谢大家,问题已解决了,小弟谢过了.下面是我实际使用的代码:Option ExplicitPrivate 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 = &HB0Dim iLineX, iLineY As LongSub GetCurPos(txtA As TextBox) Dim l, l1, l2 As Long Dim astr As String * 256
SendMessageByRef txtA.hwnd, EM_GETSEL, l1, l2 iLineX = l1 - l Label1.Caption = "列:" + Str(iLineX + 1) Label2.Caption = "行:" + Str(iLineY + 1) End Sub Private Sub Text1_Click() GetCurPos Text1 End Sub Private Sub Text1_KeyUp(KeyCode As Integer, Shift As Integer) GetCurPos Text1 End Sub form1里面有text1,label1,label2,text1的multiline设为true
控件发送编辑控件类型消息。也可以实现这样的功能。下面首先来看程序,然后再分析。
首先在VB中建立一个新工程,并在Form1中加入一个TextBox控件和两个Label控件。将TextBox控件的MultiLine
属性设置为True。然后在Form1的代码窗口中加入如下代码:Option ExplicitPrivate 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 = &HB0Dim iLineX, iLineY As LongSub 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 SubPrivate 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:\windows\readme.txt" For Input As #iFile
Do
Line Input #iFile, astr
Text1.Text = Text1.Text + astr + vbCrLf
Loop Until EOF(iFile)
Close iFile
End SubPrivate 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 SubPrivate Sub Text1_Click()
GetCurPos Text1
End SubPrivate Sub Text1_KeyUp(KeyCode As Integer, Shift As Integer)
GetCurPos Text1
End Sub
在运行程序前,确保在你的硬盘上有 c:\windows\readme.txt 这个文件。否则程序会出错。然后运行
程序。当在编辑文本时,可以看到在窗口底部可以显示当前光标所在的行、列值。
在上面的程序中。我们首先发送EM_LINEINDEX消息,发送该消息可以返回某一行的第一个字符在整个
文本控件中的位置,如果wParam参数设置为-1,则返回当前行的字符位置。然后发送EM_LINEFROMCHAR,发
送该消息可以根据参数wParam指定的字符位置返回该字符所在的行号,文本第一行的位置为0。这样使用这
两个消息就获得当前光标所在的行号。要取得列号,首先发送EM_GETSEL消息,发送该消息返回当前被选中
文本的起始位置,如果没有文本被选中,则返回当前光标所在字符在文本中的位置。由于上面的EM_LINEINDEX
消息返回的是当前行的第一个字符在文本中的位置。所以将两值相减,就是光标所在字符的列位置。
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long,lParam As Any) As Long
Public Const EM_GETLINECOUNT=&HBA
Public Const EM_GETLINE=&HC4
在Form1的代码模块中写如下代码:
Private Sub Command1_Click()
Dim str(256) As Byte
str(1)=1 '最大允许存放256个字符
'获取总行数,结果显示在文本框txtLineCount中
txtlineCount=SendMessage(Text1.hwnd,EM_GETLINECOUNT,0,0)
'获取第3行的数据放在str中,转换为字符串后显示在文本框txtString中
SendMessage Text1.hwnd,EM_GETLINE,2,str(0)
txtString= StrConv(str,vbUnicode)
End Sub
Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Const EM_GETSEL = &HB0
Private Const EM_LINEFROMCHAR = &HC9
Private Const EM_LINEINDEX = &HBBPrivate Sub Command1_Click()
Dim line As Long, col As Long
GetTextCursorPos RichTextBox1.hwnd, line, col
Debug.Print line, col
End Sub' 获得文本框中光标的所在位置
' hwnd 为文本框的句柄, LineNo 为光标所在的行数, ColNo 为光标所在的列数
Sub GetTextCursorPos(ByVal hwnd As Long, ByRef LineNo As Long, ByRef ColNo As Long)
Dim i As Long, j As Long, k As Long
Dim lParam As Long, wParam As Long
i = SendMessage(hwnd, EM_GETSEL, wParam, lParam)
j = i / 2 ^ 16 '取得目前光标前面有多少个字节
LineNo = SendMessage(hwnd, EM_LINEFROMCHAR, j, 0) '取得前面有多少行
LineNo = LineNo + 1
k = SendMessage(hwnd, EM_LINEINDEX, -1, 0) '取得目前光标所在行前面有多少个字节
ColNo = j - k + 1
End Sub
(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 = &HB0Dim iLineX, iLineY As LongSub 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 + 1)
Label2.Caption = "行:" + Str(iLineY + 1)
End Sub
Private Sub Text1_Click()
GetCurPos Text1
End Sub
Private Sub Text1_KeyUp(KeyCode As Integer, Shift As Integer)
GetCurPos Text1
End Sub
form1里面有text1,label1,label2,text1的multiline设为true