开发者

.NET Vertical Scrollbar not Respecting Maximum Property

开发者 https://www.devze.com 2022-12-31 10:25 出处:网络
I have a form and have dropped a vertical scrollbar on it. Whatever I set the \"Maximum\" property to,开发者_运维问答 the scrollbar will only scroll up to that value minus 9.

I have a form and have dropped a vertical scrollbar on it.

Whatever I set the "Maximum" property to,开发者_运维问答 the scrollbar will only scroll up to that value minus 9.

Why is that?

I'm using C# in Visual Studio 2008. (WinForms)


After some research, I've found that a scroll bar can only go up to it's maximum minus the size of the scrollbar's slider.

And the size of the slider appears to be equal to (LargeChange - 1).

Doesn't seem very intuitive to me but there you go.


The default value of LargeChange property is 10. This value is used when scrollbar is incremented by clicking the right arrow. If you want to show all values (assuming 1,2,3,4,...) with mouse clicks, set LargeChange = 1


Thanks to Kevin for explaining this! I made a custom vertical scroll bar in VB .NET that addresses this problem and also:

  1. Maps the Minimum, Maximum, and Value to real-world coordinates RealMaximum, RealMinimum, and RealValue
  2. Adds a SetMaximum property that should be set to the value you would normally set the Maximum property to. Maximum will be rescaled to take the slider width into account.
  3. Inverts the scroll behavior so that scrolling upward returns a higher value and scrolling downward returns a lower value.

Here's the code:

Public Class VScrollBarPlus
Inherits System.Windows.Forms.VScrollBar
' Maps the VScrollbar integer min and max to a double-precision set of minima and maxima '
' RealValue is scaled to RealMaximum and RealMinimum'
' The vertical scrollbar should scroll UP to maximum and DOWN to minimum, not the other way around'
' A VB slider width is LargeChange -1'
' The regular VB scroll bar can only go up to its maximum minus the width of the scrollbar's slider.'
' The SetMaximum property should be set to the maximum value you WANT'
' The Maximum property will be rescaled to take into account the slider width'

' Slope and intercept to calculate actual value'

Private slope As Double = 1
Private intercept As Double = 0

' Internal variables for real max, real min, and real value'

Private rValue As Double
Private rMin As Double
Private rMax As Double
Private sMax As Double
Property SetMaximum As Double ' The value you _want_ to set as maximum'
    ' The actual Maximum will be set to SetMaximum + LargeChange - 1 to allow scrolling to maximum value'
    Get
        SetMaximum = sMax
    End Get
    Set(svalue As Double)
        sMax = svalue
        Maximum = SetMaximum + LargeChange - 1
    End Set
End Property
Property RealMaximum As Double ' Real-world coordinates'
    Get
        RealMaximum = rMax
    End Get
    Set(svalue As Double)
        rMax = svalue
    End Set
End Property
Property RealMinimum As Double ' Real-world coordinates'
    Get
        RealMinimum = rMin
    End Get
    Set(svalue As Double)
        rMin = svalue
    End Set
End Property
Property RealValue As Double ' Real-world coordinates'
    Get
        slope = (rMax - rMin) / (sMax - CDbl(Minimum))
        intercept = rMax - slope * sMax
        ' Use the negative Value to invert slider motion'
        RealValue = slope * CDbl(-Value) + intercept
    End Get
    Set(svalue As Double)
        rValue = svalue
        If slope <> 0 Then
            Value = Math.Min(SetMaximum, -(rValue - intercept) / slope)
        Else
            Value = SetMaximum
        End If
    End Set
End Property

End Class

I made a test form with a VScrollBarPlus control and four text boxes: two to display/set the real-world coordinates and two to display the scrollbar value and the value mapped to real world coordinates. These were names txtMin, txtMax, txtScrollValue and txtValue respectively. In the designer, I set the Minimum and Maximum properties to -1000 and 1000, SetMaximum to 1000, RealMinimum to -1, RealMaximum to 1, RealValue to 1, LargeChange to 10 and SmallChange to 1. The value for SetMaximum must be set in the designer or code before using the scrollbar.

Here is the code for the test form.

Public Class Test_Form
Private Sub txtMin_KeyPress(sender As Object, e As KeyPressEventArgs) Handles txtMin.KeyPress
    If e.KeyChar = Chr(Keys.Enter) Then
        VScrollBarPlus1.RealMinimum = CDbl(txtMin.Text)
    End If
End Sub

Private Sub txtMax_KeyPress(sender As Object, e As KeyPressEventArgs) Handles txtMax.KeyPress
    If e.KeyChar = Chr(Keys.Enter) Then
        VScrollBarPlus1.RealMaximum = CDbl(txtMax.Text)
    End If
End Sub

Private Sub VScrollBarPlus1_Scroll(sender As Object, e As ScrollEventArgs) Handles VScrollBarPlus1.Scroll
    If e.Type = ScrollEventType.EndScroll Then
        txtValue.Text = VScrollBarPlus1.RealValue.ToString
        txtScrollValue.Text = VScrollBarPlus1.Value.ToString
    End If
End Sub
Private Sub Test_Form_Load(sender As Object, e As EventArgs) Handles Me.Load
    VScrollBarPlus1.Maximum = 1000
    VScrollBarPlus1.Minimum = -1000
    txtMax.Text = 9.5
    txtMin.Text = -7
    VScrollBarPlus1.RealMaximum = 9.5
    VScrollBarPlus1.RealMinimum = -7
    VScrollBarPlus1.SetMaximum = VScrollBarPlus1.Maximum ' will resize Maximum '
    VScrollBarPlus1.RealMaximum = CDbl(txtMax.Text)
    VScrollBarPlus1.RealMinimum = CDbl(txtMin.Text)
End Sub

Private Sub txtValue_KeyPress(sender As Object, e As KeyPressEventArgs) Handles txtValue.KeyPress
    If e.KeyChar = Chr(Keys.Enter) Then
        VScrollBarPlus1.RealValue = CDbl(txtValue.Text)
        txtScrollValue.Text = VScrollBarPlus1.Value.ToString
    End If
End Sub
End Class


I like the scroll bar as a quick input device but the bug pointed out here was a problem. Syed is right that you can just reduce the LargeChange property to 1 and the scrollbar will move to its maximum value.

However, if you want to keep the LargeChange property at some larger value, say 10 for quick scrolling, use the ValueChanged event. When the value is below 90 (or below Maximum - LargeChange), leave the LargeChange property at 10. When the value goes to 90 or above, change the LargeChange property to 1.

This allows the scrollbar to behave normally (or very nearly so) while still going to its maximum.

0

精彩评论

暂无评论...
验证码 换一张
取 消