AnotherUser
AnotherUser

Reputation: 1353

Calculating ScrollBar scroll percent; height of ScrollBar "bar"?

I am trying to determine the percentage value of a scroll bar in response to its OnScroll event, though I am having a difficult time determining the actual percentage. I would figure it should be as simple as doing the ratio of the current scroll value divided by the maximum value. Though this produces odd results.

void ThePanel_Scroll(object sender, ScrollEventArgs e)
{
    if (e.ScrollOrientation == ScrollOrientation.VerticalScroll)
    {
        double scrollPercent = (double)e.NewValue / (double)ThePanel.VerticalScroll.Maximum;
        Console.Out.WriteLine("Max: " + ThePanel.VerticalScroll.Maximum + " Min: " + ThePanel.VerticalScroll.Minimum);
        Console.Out.WriteLine("OldVal: " + e.OldValue + " NewVal: " + e.NewValue + " Val: " + ThePanel.VerticalScroll.Value);
        Console.Out.WriteLine("CurPer: " + scrollPercent);
    }
}

When running this code, and scrolling the bar all the way to the maximum position, I might get some output like so

Max: 529 Min: 0
OldVal: 170 NewVal: 170 Val: 170
CurPer: 0.321361058601134

Even though the scroll bar is at a maximum position its Value is not. I assume the reason is that the Value is based off of the top of the scroll bar. My problem is that I cannot determine the height/size of the scroll bar "bar" itself, to calculate a proper percentage.

Is the proper way to determine the percent based on using the height of the bar along with the Value, or am I missing something else? If it is based off the height, how to I determine that? Reading through the VScrollProperties MSDN there is nothing there that would tell me the height of the bar itself.

Upvotes: 1

Views: 2027

Answers (2)

Hans Passant
Hans Passant

Reputation: 941555

There is an inherent ambiguity in the scrollbar position due to the non-zero thumb height. Which side of the thumb do you consider the "active" side? Windows doesn't help you deal with that, it suddenly switches over from one side to another when the thumb gets close to the maximum position. If you don't compensate for that then you'll lose a portion of the range.

The workaround is to take the sting out that flipping behavior and apply your own effective maximum. Like this:

    private void panel1_Scroll(object sender, ScrollEventArgs e) {
        if (e.ScrollOrientation == ScrollOrientation.VerticalScroll) {
            var max = panel1.VerticalScroll.Maximum - panel1.VerticalScroll.LargeChange;
            var pos = Math.Min(max, e.NewValue);
            var percentage = 100.0 * pos / max;
            // etc...
        }
    }

Upvotes: 3

TaW
TaW

Reputation: 54433

You can calculate the vertical scroll position in percent like this:

 int percent_v = (int) Math.Min(100f * container.VerticalScroll.Value / 
                 (content.Height - container.ClientSize.Height), 100);

Here the Container would be the Panel and the content maybe a Picturebox or whatever else you have placed inside.

I looks a bit weird and it is. When scrolled to its maximum, the value is not the real maximum but is reduced by the containing controls's height.

For horizontal scrolling the same applies.

Disclaimer: this is what I found by testing; I never saw it documented anywhere.

Upvotes: 1

Related Questions