Link to home
Start Free TrialLog in
Avatar of msdnman
msdnman

asked on

row/col positions in textbox?

I need to display the row and column position of the cursor(caret) with a textbox or richtext box as the user moves(with the arrow keys) around within it. Also when the user places the cursor on a row I need to display that positon as well.

I am using VB.net beta 2, but a solution in VB6 will suffice.

Thank you
Avatar of Anthony Perkins
Anthony Perkins
Flag of United States of America image

Private Declare Function SendMessageLong Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Private Function GetCurrCol(hWnd As Long, ByVal Line As Long) As Long
Const EM_LINEINDEX = &HBB

' Zero based
GetCurrCol = SendMessageLong(hWnd, EM_LINEINDEX, Line, 0&)

End Function

Private Sub UpdatePos()
Dim CurrLine As Long
Dim CurrCol As Long

CurrLine = RichTextBox1.GetLineFromChar(RichTextBox1.SelStart)
CurrCol = RichTextBox1.SelStart - GetCurrCol(RichTextox1.hWnd, CurrLine) + 1
   
Debug.Print "Line " & CStr(CurrLine)
Debug.Print "Col " & CStr(CurrCol)

End Sub
Avatar of msdnman
msdnman

ASKER

There is no equivelent, that I can find, to SelStart in the .net RichTextBox control. That said, a VB 6 example will not lead me in the right direction.

How is this done in VB.net or C#?
This is not a .Net solution, but something I was playing with after reading your question.  It may help you or give you some ideas.  If you have any questions let me know.


Option Explicit

Private Const EM_GETSEL = &HB0

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


Private Sub Text1_KeyUp(KeyCode As Integer, Shift As Integer)
    TestRowCol
End Sub

Private Sub Text1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    TestRowCol
End Sub

Private Sub TestRowCol()
    'Assume you have three textboxes
    'Text1 - Where the user types
    'txtRow - Return for the row information
    'txtCol - Return for the column information
    '
    Dim l As Long
    Dim lngEnd As Long
    Dim lngRow As Long
    Dim lngCol As Long
    Dim lngPosLastCrLf As Long

    lngRow = 1

    Call SendMessage(Text1.hwnd, EM_GETSEL, 0&, lngEnd)

    For l = 1 To lngEnd
        If Asc(Mid(Text1.Text, l, 1)) = Asc(vbCrLf) Then
            lngRow = lngRow + 1
            lngPosLastCrLf = l
        End If
    Next l

    lngCol = (lngEnd - lngPosLastCrLf)
    If lngRow = 1 Then lngCol = lngCol + 1

    txtRow.Text = lngRow
    txtCol.Text = lngCol
End Sub
' Form1
' To obtain cursor positions (expressed in terms of characters) in textbox

Option Explicit

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

Private Const EM_GETSEL = &HB0
Private Const EM_SETSEL = &HB1
Private Const EM_GETLINECOUNT = &HBA
Private Const EM_LINEINDEX = &HBB
Private Const EM_LINELENGTH = &HC1
Private Const EM_LINEFROMCHAR = &HC9
   


Private Sub command1_Click()
    Dim lineCount As Long
    Dim currLinePos As Long
    Dim overallCursorPos As Long
    Dim chrsBeforeCurrLine As Long
    Dim CurrLineCursorPos As Long
    Dim currLineLen As Long
   
    On Local Error Resume Next
   
     'total number of lines in the text box
    lineCount = SendMessageLong(Text1.hwnd, EM_GETLINECOUNT, 0, 0&)
    Label2.Caption = "No.of lines count (inc blank line if any) = " & CStr(lineCount)
   
     'cursor position in the text box
    overallCursorPos = SendMessageLong(Text1.hwnd, EM_GETSEL, 0, 0&) \ &H10000
    Label3.Caption = "Overall cursor pos (incl CR and LF if any) = " & CStr(overallCursorPos + 1)
   
    'current line pos (Note: zero-based)
    currLinePos = SendMessageLong(Text1.hwnd, EM_LINEFROMCHAR, overallCursorPos, 0&)
    Label4.Caption = "Current line = " & CStr(currLinePos + 1)
   
     'number of chrs upto but before start of the current line
    chrsBeforeCurrLine = SendMessageLong(Text1.hwnd, EM_LINEINDEX, currLinePos, 0&)
    Label5.Caption = "Chars before current line (incl CR and LF if any) = " & CStr(chrsBeforeCurrLine)

     'cursor position in terms of current line only (Note: zero-based)
    CurrLineCursorPos = overallCursorPos - chrsBeforeCurrLine
    Label6.Caption = "Char pos in current line = " & CStr(CurrLineCursorPos + 1)
   
    'number of characters in current line (Note: with EM_LINELENGTH, the value of the "wParam"
    'parameter specifies the char index of a char in the line. If this parameter is -1, the
    'function returns number of unselected characters on line. "lParam" not used and set to 0).
    currLineLen = SendMessageLong(Text1.hwnd, EM_LINELENGTH, -1, 0&)
    Label7.Caption = "No. of unselected chars in current line = " & CStr(currLineLen)
   
    Text1.SetFocus
End Sub

Avatar of msdnman

ASKER

Neither of the solutions seem to work in .net. It appears that the messages may have changed for the .net controls. If I can find the messages that they can accept I should be able to get one of the examples working.

Any idea where I can find them?

Thanks for your continued help!!!
Avatar of msdnman

ASKER

Neither of the solutions seem to work in .net. It appears that the messages may have changed for the .net controls. If I can find the messages that they can accept I should be able to get one of the examples working.

Any idea where I can find them?

Thanks for your continued help!!!
<ping>.. listening
not sure if this will work in vb.net,worth a try though

Public Declare Function SendMessageLong Lib "USER32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Public Const EM_GETSEL As Long = &HB0
    Public Const EM_SETSEL As Long = &HB1
    Public Const EM_GETLINECOUNT As Long = &HBA
    Public Const EM_LINEINDEX As Long = &HBB
    Public Const EM_LINELENGTH As Long = &HC1
    Public Const EM_LINEFROMCHAR As Long = &HC9
    Public Const EM_SCROLLCARET As Long = &HB7
    Public Const WM_SETREDRAW As Long = &HB

'**************************************
' Name: text object line info
' Description:The first function returns
'     usefull information about text box objec
'     ts. these include :
[Line count] = 0
[Cursor Position] = 1
[Current Line Number] = 2
[Current Line Start] = 3
[Current Line End] = 4
[Current Line Length] = 5
[Current Line Cursor Position] = 6
[Line Start] = 7
[Line End] = 8
[Line Length] = 9
The next function returns the text of a given line of a text box object.
' By: Damien McGivern
'
'
' Inputs:Public Enum LineInfo
[Line count] = 0
[Cursor Position] = 1
[Current Line Number] = 2
[Current Line Start] = 3
[Current Line End] = 4
[Current Line Length] = 5
[Current Line Cursor Position] = 6
[Line Start] = 7
[Line End] = 8
[Line Length] = 9
End Enum


Public Function getLineInfo(txtObj As Object, info As LineInfo, Optional lineNumber As Long) As Long


Public Function GetLineText(txtObj As Object, lineNumber As Long) As String
    '// If lineNumber = 0 then current line'
Option Explicit


Public Declare Function SendMessageLong Lib "USER32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Public Const EM_GETSEL As Long = &HB0
    Public Const EM_SETSEL As Long = &HB1
    Public Const EM_GETLINECOUNT As Long = &HBA
    Public Const EM_LINEINDEX As Long = &HBB
    Public Const EM_LINELENGTH As Long = &HC1
    Public Const EM_LINEFROMCHAR As Long = &HC9
    Public Const EM_SCROLLCARET As Long = &HB7
    Public Const WM_SETREDRAW As Long = &HB


Public Enum LineInfo
    [Line count] = 0
    [Cursor Position] = 1
    [Current Line Number] = 2
    [Current Line Start] = 3
    [Current Line End] = 4
    [Current Line Length] = 5
    [Current Line Cursor Position] = 6
    [Line Start] = 7
    [Line End] = 8
    [Line Length] = 9
End Enum


Public Function getLineInfo(txtObj As Object, info As LineInfo, Optional lineNumber As Long) As Long
    Dim cursorPoint As Long
    '//Record where the cursor is
    cursorPoint = txtObj.SelStart


    Select Case info
        Case Is = 0 ' = "lineCount"
        getLineInfo = SendMessageLong(txtObj.hWnd, EM_GETLINECOUNT, 0, 0&)
        Case Is = 1 ' = "cursorPosition"
        getLineInfo = (SendMessageLong(txtObj.hWnd, EM_GETSEL, 0, 0&) \ &H10000) + 1
        Case Is = 2 ' = "currentLineNumber"
        getLineInfo = (SendMessageLong(txtObj.hWnd, EM_LINEFROMCHAR, -1, 0&)) + 1
        Case Is = 3 ' = "currentLineStart"
        getLineInfo = SendMessageLong(txtObj.hWnd, EM_LINEINDEX, -1, 0&) + 1
        Case Is = 4 ' = "currentLineEnd"
        getLineInfo = SendMessageLong(txtObj.hWnd, EM_LINEINDEX, -1, 0&) + 1 + SendMessageLong(txtObj.hWnd, EM_LINELENGTH, -1, 0&)
        Case Is = 5 ' = "currentLineLength"
        getLineInfo = SendMessageLong(txtObj.hWnd, EM_LINELENGTH, -1, 0&)
        Case Is = 6 ' = "currentLineCursorPosition"
        getLineInfo = (SendMessageLong(txtObj.hWnd, EM_GETSEL, 0, 0&) \ &H10000) + 1 - SendMessageLong(txtObj.hWnd, EM_LINEINDEX, getLineInfo(txtObj, [Current Line Number]) - 1, 0&)
        Case Is = 7 ' = "lineStart"
        getLineInfo = (SendMessageLong(txtObj.hWnd, EM_LINEINDEX, (lineNumber - 1), 0&)) + 1
        Case Is = 8 ' = "lineEnd"
        getLineInfo = SendMessageLong(txtObj.hWnd, EM_LINEINDEX, (lineNumber - 1), 0&) + 1 + SendMessageLong(txtObj.hWnd, EM_LINELENGTH, (lineNumber - 1), 0&)
        Case Is = 9 ' = "lineLength"
        getLineInfo = (SendMessageLong(txtObj.hWnd, EM_LINEINDEX, lineNumber, 0&)) + 1 - (SendMessageLong(txtObj.hWnd, EM_LINEINDEX, (lineNumber - 1), 0&)) - 3
    End Select
End Function


Public Function GetLineText(txtObj As Object, lineNumber As Long) As String
    '// If lineNumber = 0 then current line'
    '     s text is given
    If lineNumber = 0 Then lineNumber = getLineInfo(txtObj, [Current Line Number])
    '// Select text
    Call SendMessageLong(txtObj.hWnd, EM_SETSEL, ((getLineInfo(txtObj, [Line Start], lineNumber)) - 1), ((getLineInfo(txtObj, [Line Start], lineNumber + 1)) - 1))
    GetLineText = txtObj.SelText
End Function


hope it helps
Andy
Avatar of msdnman

ASKER

Anyone have a .net solution for me??
Hi msdnman,
It appears that you have forgotten this question. I will ask Community Support to close it unless you finalize it within 7 days. I will ask a Community Support Moderator to:

    Refund points and save as a 0-pt PAQ.

msdnman, Please DO NOT accept this comment as an answer.
EXPERTS: Post a comment if you are certain that an expert deserves credit.  Explain why.
==========
DanRollins -- EE database cleanup volunteer
ASKER CERTIFIED SOLUTION
Avatar of Netminder
Netminder

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial