Reputation: 1353
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
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
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