Home > database >  Set the exact position of a Textbox's Scrollbar
Set the exact position of a Textbox's Scrollbar

Time:11-09

I have a multi-line textbox with both its horizontal and vertical scrollbars visible, and WordWrap set to False. I load a large textfile in the textbox to allow the user to edit it.

The editing features automation which requires me to store the value of the entire textbox into a value, process it and then store it back into the textbox. This all is working great, but by setting a string into the textbox, it first clears it and then fills it again. This action sets the scrollbar position to the top-left corner.

I have tried to use Textbox1.scrolltocaret in my update routine which makes the cursor visible again, but it doesn't scroll to the exact position the control was set to before.

Also, I can't find out how to call textbox1.scrolltocaret every time the user moves using the arrowkey.

How can I store and restore the scrollbar locations?

Here's my code:

Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
    If Me.bPauseUpdate = True Then Exit Sub
    Me.bPauseUpdate = True
    Me.CursorLocation = TextBox1.SelectionStart
    Dim aWorkingText() As String = Me.TextBox1.Lines

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Code that changes aWorkingText lives here, but is not relevant for this question
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        
    TextBox1.Lines = aWorkingText
    Me.bPauseUpdate = False
    TextBox1.SelectionStart = Me.CursorLocation
    
    Textbox1.scrolltocaret
End Sub

I looked into using Textbox1.Scrollbars but they are only for controlling whether the scrollbars are visible.

I tried to make it work with the following code, but that does not allow me to actually set the value even though the IDE says I should be able to do so:

Me.ScrollbarX = TextBox1.AutoScrollOffset.X
Me.ScrollbarY = TextBox1.AutoScrollOffset.Y
.
.
.
TextBox1.AutoScrollOffset.X = Me.ScrollbarX
TextBox1.AutoScrollOffset.Y = Me.ScrollbarY

enter image description here enter image description here

I even tried this, but it yields the same result.

TextBox1.AutoScrollOffset.X = New Point(Me.ScrollBarX)
TextBox1.AutoScrollOffset.Y = New Point(Me.ScrollBarY)

CodePudding user response:

You can use the GetScrollPos Win32 API to get the current vertical and horizontal scrollbar position of the TextBox control.

Imports System.Runtime.InteropServices

<DllImport("user32.dll", CharSet:=CharSet.Auto)> Friend Shared Function GetScrollPos(hWnd As IntPtr, nBar As Integer) As Integer
End Function

Friend Enum SBOrientation As Integer

    SB_HORZ = &H0
    SB_VERT = &H1

End Enum

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    'Horizontal scroll position
    GetScrollPos(TextBox1.Handle, SBOrientation.SB_HORZ)

    'Vertical scroll position
    GetScrollPos(TextBox1.Handle, SBOrientation.SB_VERT)

End Sub

Use the SendMessage Win32 API to set the TextBox scroll position

<DllImport("user32.dll")> Friend Shared Function SendMessage(hWnd As IntPtr, msg As UInteger, wParam As UInteger, lParam As UInteger) As IntPtr
End Function

Friend Const SB_THUMBPOSITION As UInteger = 4

Friend Enum WindowMessage As Integer

    WM_HSCROLL = &H114
    WM_VSCROLL = &H115

End Enum

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    'Set Vertical scroll position
    Dim vPos = 16
    Dim wparam1 = CUInt(vPos) << 16 Or (SB_THUMBPOSITION And &HFFFF)
    SendMessage(TextBox1.Handle, CUInt(WindowMessage.WM_VSCROLL), CUInt(wparam1), CUInt(0))

    'Set Horizontal scroll position

    Dim hPos = 100
    Dim wparam2 = CUInt(hPos) << 16 Or (SB_THUMBPOSITION And &HFFFF)
    SendMessage(TextBox1.Handle, CUInt(WindowMessage.WM_HSCROLL), CUInt(wparam2), CUInt(0))

End Sub
  • Related