I am developing a touch screen application that has to display a possibly large amount of text. The problem I am having is that the default scroll bar attached to text boxes is just too small to be practically used in a touch screen application. I have tried adding a separate scroll bar control and using it to control the scrolling of the text box. So far I have only come up with two ways of doing this.
The first way I came up with was to use the ScrollToCaret() subroutine. However I do not like this approach because it feels as if there should be a better way to tie in a scroll bar to a text box without changing the text selection
Here is an example:
Dim oSelectionStart As Integer = CInt((TextBox1.Text.Length \ (VScrollBar1.Maximum - VScrollBar1.LargeChange - 1)) * VScrollBar1.Value)
If oSelectionStart >= TextBox1.Text.Length - 10 Then
oSelectionStart = TextBox1.Text.Length
End If
If oSelectionStart <= 10 Or VScrollBar1.Value < 2 Then
oSelectionStart = 0
End If
If Not TextBox1.SelectionStart = oSelectionStart Then
TextBox1.SelectionStart = oSelectionStart
TextBox1.ScrollToCaret()
End If
The second method I came up with uses windows API calls to set the scroll bars position and to get its current position. There are however some flaws to this approach as well. I am unable to get the large change value from the textboxes scrolling info. Most of the time this doesn't matter but when the default scroll bar on the textbox gets bigger it means that my scroll bar does not scale properly with it, giving my scroll bar the effect of scrolling to the bottom of the text while only being half way down the bar. Another problem with this approach that I found is that the default scroll bar for the textbox must be visible in order for me to be able to retrieve and set the current scrolling info. The last problem I have is one that plagues both methods I have discovered. I am unable to find an appropriate event to fire for when the user scrolls the text with anything other than my scroll bar, this means that I cannot update the position of my scroll bar even though the text has changed its scrolled position.
Heres the example code:
Private Sub VScrollBar1_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs)
Dim minPos As Integer = 0
Dim maxPos As Integer = 0
Dim newPos As Integer = 0
GetScrollRange(TextBox1.Handle, SBS_VERT, minPos, maxPos)
Dim vScrollPerc As Double = ((100 / (VScrollBar1.Maximum - (VScrollBar1.LargeChange - 1))) * VScrollBar1.Value) * 0.01
newPos = CInt(((maxPos - minPos) * vScrollPerc) + minPos)
SetScrollPos(TextBox1.Handle, SBS_VERT, newPos, True)
PostMessageA(TextBox1.Handle, WM_VSCROLL, SB_THUMBPOSITION + &H10000 * newPos, Nothing)
End Sub
'Scrollbar direction
Const SBS_HORZ = 0
Const SBS_VERT = 1
'Windows Messages
Const WM_VSCROLL = &H115
Const WM_HSCROLL = &H114
Const SB_THUMBPOSITION = 4
<Runtime.InteropServices.StructLayout(Runtime.InteropServices.LayoutKind.Sequential)> Private Structure SCROLLINFO
Public cbSize As Integer
Public fMask As Integer
Public nMin As Integer
Public nMax As Integer
Public nPage As Integer
Public nPos As Integer
Public nTrackPos As Integer
End Structure
Private Enum ScrollBarDirection
SB_HORZ = 0
SB_VERT = 1
SB_CTL = 2
SB_BOTH = 3
End Enum
Private Enum ScrollInfoMask
SIF_RANGE = &H1
SIF_PAGE = &H2
SIF_POS = &H4
SIF_DISABLENOSCROLL = &H8
SIF_TRACKPOS = &H10
SIF_ALL = (SIF_RANGE Or SIF_PAGE Or SIF_POS Or SIF_TRACKPOS)
End Enum
Private Declare Function GetScrollPos Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal nBar As Integer) As Integer
Private Declare Function SetScrollPos Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal nBar As Integer, ByVal nPos As Integer, ByVal bRedraw As Boolean) As Integer
Private Declare Function PostMessageA Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Boolean
Private Declare Function GetScrollRange Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal nBar As Integer, ByRef lpMinPos As Integer, ByRef lpMaxPos As Integer) As Integer
Private Declare Function GetScrollInfo Lib "user32" (ByVal hWnd As IntPtr, ByVal fnBar As ScrollBarDirection, ByRef lpsi As SCROLLINFO) As Integer
I know there must be a better way out there to do this, but so far I have not been able to come up with anything that would be an appropriate solution to my problem. Any help would be appreciated.