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
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