Panning a scrollable Panel in a Windows Forms category 'experiment', language C#, created 08-Oct-2011, version V2.0 (10-Oct-2011), by Luc Pattyn |
License: The author hereby grants you a worldwide, non-exclusive license to use and redistribute the files and the source code in the article in any way you see fit, provided you keep the copyright notice in place; when code modifications are applied, the notice must reflect that. The author retains copyright to the article, you may not republish or otherwise make available the article, in whole or in part, without the prior written consent of the author. Disclaimer: This work is provided “as is”, without any express or implied warranties or conditions or guarantees. You, the user, assume all risk in its use. In no event will the author be liable to you on any legal theory for any special, incidental, consequential, punitive or exemplary damages arising out of this license or the use of the work or otherwise. |
The WinForms toolbox offers a number of scrollable Controls, Panel being one of them.
This is how it works: the physical size of the Control is specified by its Size property;
the logical size is determined as the hull of all the visible Controls it contains.
When the logical size exceeds the physical size, i.e. when not all content is visible at once,
a scrollable Control starts showing a horizontal and/or a vertical scrollbar assuming AutoScroll
is set true; those scrollbars have their MinValue and MaxValue set to the appropriate values automatically.
Changing their value within the allowable range would cause the Control to scroll.
In this little experiment, we set out to make the scrollable Panel pan, which means it would also scroll by left-clicking, then moving the cursor around.
The full test program is available here. It has a main Form, showing two auto-scrolling Panels, as well as a ListBox for logging. This is how it looks:
There are two auto-scrolling panels in this experiment, because there could be two very different sets of conditions, and we wanted to try both situations:
AutoScroll=true
that is enough to make the auto-scroll kick in,
as the panel isn't able to show all of its content in a limited space.
Note that all those labels are disabled, so clicking anywhere
inside the top panel actually clicks topPanel itself.AutoScroll=true
.
Once again all labels are disabled, so clicking anywhere in the visible
bottom panel will actually be handled by the innerPanel's event handlers, not by the labels, and certainly
not by the bottomPanel itself as that is covered by innerPanel.And that is where the essential difference lies:
The panning code is located in the mouse handlers. For the top panel, we have:
private int clickX; // coordinates of click point
private int clickY;
private void topPanel_MouseDown(object sender, MouseEventArgs e) {
clickX=topPanel.HorizontalScroll.Value+e.X;
clickY=topPanel.VerticalScroll.Value+e.Y;
...
}
private void topPanel_MouseMove(object sender, MouseEventArgs e) {
if (e.Button==MouseButtons.Left) {
setScrollValue(topPanel.HorizontalScroll, clickX-e.X);
setScrollValue(topPanel.VerticalScroll, clickY-e.Y);
}
}
The setScrollValue()
method merely sets a scrollbar's value, after making sure the value
is inside the allowable range [MinValue, MaxValue]
.
For the bottom panel, it is similar, except for the choice of coordinates:
private void innerPanel_MouseDown(object sender, MouseEventArgs e) {
clickX=bottomPanel.HorizontalScroll.Value+MousePosition.X;
clickY=bottomPanel.VerticalScroll.Value+MousePosition.Y;
...
}
private void innerPanel_MouseMove(object sender, MouseEventArgs e) {
if (e.Button==MouseButtons.Left) {
setScrollValue(bottomPanel.HorizontalScroll, clickX-MousePosition.X);
setScrollValue(bottomPanel.VerticalScroll, clickY-MousePosition.Y);
}
}
This code uses Control.MousePosition to obtain the mouse position using screen coordinates. An alternative would be using control.PointToScreen(e.Location) where control is either bottomPanel or Form1.
Conclusion: it works just fine. Some final remarks:
Perceler |
Copyright © 2012, Luc Pattyn |
Last Modified 02-Sep-2013 |