I am trying to make a scrollable panel but without the scrollbar and to scroll by dragging with mouse vertically... here is what somebody helped me to do so far.. :
private void panel1_MouseEnter(object sender, EventArgs e)
{
panel1.AutoScroll = false;
}
private int ValidateChange(int change)
{
var padding = -1;
if (change < 0)
{
var max = (from Control control in Controls select control.Top + control.Height + padding).Concat(new[] { int.MinValue }).Max();
if (max < Height + Math.Abs(change))
{
return Height - max;
}
}
else
{
var min = (from Control control in Controls select control.Top).Concat(new[] { int.MaxValue }).Min();
if (min > padding - Math.Abs(change))
{
return padding - min;
}
}
return change;
}
private void HandleDelta(int delta)
{
var change = ValidateChange(delta);
foreach (Control control in Controls)
{
control.Top += change;
}
}
private void panel1_MouseWheel(object sender, MouseEventArgs e)
{
HandleDelta(e.Delta);
base.OnMouseWheel(e);
}
private Point _mouseLastPosition;
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_mouseLastPosition = e.Location;
}
base.OnMouseDown(e);
}
public void panel1_MouseMove(object sender, MouseEventArgs e)
{
if ((MouseButtons & MouseButtons.Left) != 0)
{
var delta = e.Y - _mouseLastPosition.Y;
HandleDelta(delta);
_mouseLastPosition = e.Location;
}
base.OnMouseMove(e);
}
but it goes just too fast..
EDIT: the dragging by mouse looks a little bit weird i dont know why and when I try to use mouse wheel it bugs and gives me this error: An unhandled exception of type 'System.StackOverflowException' occurred in System.Core.dll at this line var max = (from Control control in Controls select control.Top + control.Height + padding).Concat(new[] { int.MinValue }).Max();
Scroll: Place two fingers on the touchpad and slide horizontally or vertically. Zoom in or out: Place two fingers on the touchpad and pinch in or stretch out.
Move your fingers between the top and bottom of your touchpad to scroll up and down, or move your fingers across the touchpad to scroll sideways. Be careful to space your fingers a bit apart. If your fingers are too close together, they just look like one big finger to your touchpad.
Scroll horizontally using a keyboard and mousePress and hold SHIFT. Scroll up or down using your mouse wheel (or another vertical scrolling function of your mouse).
The scroll-snap-type CSS property sets how strictly snap points are enforced on the scroll container in case there is one.
The posted code only 'scrolls' or rather moves the Panel horizontally. For a vertical scrolling effect change this:
Panel pa = ss as Panel; pa.Left = pa.Left + ee.X - pPt.X;
to this:
Panel pa = ss as Panel; pa.Top = pa.Top + ee.Y - pPt.Y;
To make any sense the 'scrolled' or 'moved' panel also should be higher than the enclosing form, so change the sizes, maybe like this:
f2.Size = new Size(400, 300);
..
pan.Size = new Size(400, 600);
And the Buttons should be placed vertically as well, so change:
b.Left = (b.Width + 12) * (i - 1);
to
b.Top= (b.Height + 12) * (i - 1);
You also nmade a mistake when copying from the comments: This:
pan.Parent = f2;
should be the last line in the loop. Adding event handlers in the loops means that also the MouseMove
is called 10 times distance of the movement is also tenfold.
Here is what is looks like, when coded correctly:
To make the MouseWheel
work you can code it maybe like this:
pan.MouseWheel += (ss, ee) =>
{
Panel pa = ss as Panel;
pa.Top += ee.Delta > 0 ? 10 : -10;
};
Update Looks like you also want to limit the scrolling so that neither top nor bottom can move into the display area. Here is a check to achieve that; the trick is to first do the check and only then do the moving:
if (ee.Button.HasFlag(MouseButtons.Left))
{
Panel pa = ss as Panel;
int newTop = pa.Top + ee.Y - pPt.Y;
if ((newTop <= pan.Top && newTop + pan.Height > f2.ClientSize.Height) ||
(newTop >= pan.Top && newTop <= 0))
{
if (newTop <= pan.Top && newTop + pan.Height > f2.ClientSize.Height)
newTop = f2.ClientSize.Height - pan.Height;
pa.Top = newTop;
}
}
The MouseWheel
code should be checked and limited in a similar way!
Note: The correct panel height is of the essence here. My original example didn't take care of that, as no scroll limit was asked for. You could get it like this dynamically:
int panHeight = pan.Controls.Cast<Control>().Select(x => x.Bottom).Max();
pan.Height = panHeight; // maybe add a small gap here..?
This works for me. It keeps a padding of 10 pixels on all controls. Try it out and just modify it to your needs.
Let me know if something is missing that you needed.
public class ScrollablePanel : Panel {
private Point _mouseLastPosition;
protected override void OnMouseDown(MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
_mouseLastPosition = e.Location;
}
base.OnMouseDown(e);
}
private int ValidateChange(int change) {
var padding = -1;
if (change < 0) {
var max = (from Control control in Controls select control.Top + control.Height + padding).Concat(new[] { int.MinValue }).Max();
if (max < Height + Math.Abs(change)) {
return Height - max;
}
}
else {
var min = (from Control control in Controls select control.Top).Concat(new[] { int.MaxValue }).Min();
if (min > padding - Math.Abs(change)) {
return padding - min;
}
}
return change;
}
private void HandleDelta(int delta) {
var change = ValidateChange(delta);
foreach (Control control in Controls) {
control.Top += change;
}
}
protected override void OnMouseMove(MouseEventArgs e) {
if((MouseButtons & MouseButtons.Left) != 0) {
var delta = e.Y - _mouseLastPosition.Y;
HandleDelta(delta);
_mouseLastPosition = e.Location;
}
base.OnMouseMove(e);
}
protected override void OnMouseWheel(MouseEventArgs e) {
HandleDelta(e.Delta);
base.OnMouseWheel(e);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With