Используйте отдельную полосу прокрутки для текстового поля - PullRequest
2 голосов
/ 11 ноября 2008

Я разрабатываю приложение с сенсорным экраном, которое должно отображать возможно большое количество текста. Проблема, с которой я сталкиваюсь, заключается в том, что полоса прокрутки по умолчанию, прикрепленная к текстовым полям, слишком мала, чтобы ее можно было использовать в приложении с сенсорным экраном. Я попытался добавить отдельный элемент управления полосы прокрутки и использовать его для управления прокруткой текстового поля. Пока у меня есть только два способа сделать это.

Первый способ, которым я придумал, - использовать подпрограмму ScrollToCaret (). Однако мне не нравится этот подход, потому что кажется, что должен быть лучший способ привязать полосу прокрутки к текстовому полю без изменения выделения текста

Вот пример:

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

Второй метод, который я придумал, использует вызовы Windows API для установки положения полос прокрутки и получения его текущей позиции. Однако у этого подхода есть и недостатки. Я не могу получить большое значение изменения из информации прокрутки текстовых полей. В большинстве случаев это не имеет значения, но когда полоса прокрутки по умолчанию в текстовом поле становится больше, это означает, что моя полоса прокрутки не масштабируется вместе с ней, давая моей полосе прокрутки эффект прокрутки до нижней части текста, пока на полпути вниз по стойке. Другая проблема с этим подходом, который я обнаружил, заключается в том, что полоса прокрутки по умолчанию для текстового поля должна быть видимой, чтобы я мог получить и установить текущую информацию о прокрутке. Последняя проблема, с которой я столкнулся, - это проблема, которую преследуют оба метода, которые я обнаружил. Я не могу найти подходящее событие для запуска, когда пользователь прокручивает текст чем-либо, кроме моей полосы прокрутки, это означает, что я не могу обновить положение своей полосы прокрутки, даже если текст изменил свою позицию прокрутки.

Вот пример кода:

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

Я знаю, что должен быть лучший способ сделать это, но до сих пор я не смог придумать ничего, что могло бы стать подходящим решением моей проблемы. Любая помощь будет оценена.

Ответы [ 2 ]

1 голос
/ 11 ноября 2008

Думаю, есть способ как изменить размер полосы прокрутки в Win32API. Смотреть на: http://pinvoke.net/search.aspx?search=scrollbar&namespace=[All] http://pinvoke.net/default.aspx/user32/FindWindowEx.html http://pinvoke.net/default.aspx/user32/GetScrollBarInfo.html http://pinvoke.net/default.aspx/user32/ShowScrollBar.html

Вы должны иметь возможность изменять размер полосы прокрутки с помощью Win32API и ручки полосы прокрутки.

0 голосов
/ 16 ноября 2008

Мы использовали WPF в нашем последнем проекте. WPF вариант для вас? Если да, то создается впечатление, что весь интерфейс пользователя можно изменить в приложениях WPF. Мы используем 2 художников UI. Один работает в Adope Photoshop, а затем преобразует вывод в XAML. Вторая работает в Expression Blend, которая изначально создает XAML.

...