poll System.Windows.Forms.Control.MouseButtons
// example ignore a scrollbar until it is let go
private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
{
if (System.Windows.Forms.Control.MouseButtons == MouseButtons.Left) return;
ScollBarMoved();
}
When buttons are clicked, they gain a little blue border. They remain selected until something else is clicked. This looks very bad for some applications where it doesn't make sense (i.e., zoom in/out buttons). This has to do with FocusVisualStyle
and it's not easy to remove this behavior.
My workaround is to bind the MouseUp
event with a function which focuses on an invisible button. It's inelegant, but fast and functional.
// when MouseUp event is called, this moves focus to an invisible button
private void Focus_Reset(object sender, MouseEventArgs e)
{
button1.Focus();
}
Bind a function to the MouseMove
event
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
lbl_title.Text = string.Format("({0}, {1})", e.X, e.Y);
}
Point pt = new Point(e.Location); // also works
panel1.Cursor = Cursors.SizeWE;
What if you want to track MouseMove
for Panel1
but the things inside the panel cover up the panel backgruond? The solution is to create a hanlder function and connect the MouseMove
event of the panel and every control inside the panel to the same handler. Some controls contain other controls (i.e., nested panels) so a recursive solution is ideal.
public Form1()
{
InitializeComponent();
mouse_track_this_control(panel_dataView);
}
private void MouseTracker_move(object sender, MouseEventArgs e)
{
richTextBox1.Text = string.Format("MOVE: ({0}, {1})", e.X, e.Y);
}
private void MouseTracker_down(object sender, MouseEventArgs e)
{
richTextBox1.Text = string.Format("DOWN: ({0}, {1})", e.X, e.Y);
}
private void MouseTracker_up(object sender, MouseEventArgs e)
{
richTextBox1.Text = string.Format("UP: ({0}, {1})", e.X, e.Y);
}
private void mouse_track_this_control(Control control)
{
control.MouseMove += MouseTracker_move;
control.MouseDown += MouseTracker_down;
control.MouseUp += MouseTracker_up;
System.Console.WriteLine($"Connecting mouse tracker to {control.Name}");
foreach (Control control_child in control.Controls)
{
mouse_track_this_control(control_child);
}
}
mouse_position_screen = new Point(Cursor.Position.X, Cursor.Position.Y);
// find absolute cusor position on the screen
mouse_position = new Point(Cursor.Position.X, Cursor.Position.Y);
// subtract-out the location of the panel we consider (0, 0)
mouse_position.X -= this.PointToScreen(panel_dataView.Location).X;
mouse_position.Y -= this.PointToScreen(panel_dataView.Location).Y;
The zooming code keeps messing me up! It works well this way though.
shift the axis by the pixel distance dragged times unitsPerPixel
double dX = (mouse_left_down_position.X - mouse_position.X) * mouse_left_down_axis.xAxis.unitsPerPx;
double dY = (mouse_position.Y - mouse_left_down_position.Y) * mouse_left_down_axis.yAxis.unitsPerPx;
axis1 = new FigureAxis(mouse_left_down_axis.xAxis.min + dX, mouse_left_down_axis.xAxis.max + dX,
mouse_left_down_axis.yAxis.min + dY, mouse_left_down_axis.yAxis.max + dY,
mouse_left_down_axis.xAxis.pxSize, mouse_left_down_axis.yAxis.pxSize);
expand the edges by the same distance of the drag when zooming out, or sqrt(distance) when zooming in
double dX = (mouse_right_down_position.X - mouse_position.X) * mouse_right_down_axis.xAxis.unitsPerPx;
double dY = (mouse_position.Y - mouse_right_down_position.Y) * mouse_right_down_axis.yAxis.unitsPerPx;
if (dX < 0) dX = -Math.Sqrt(Math.Abs(dX));
if (dY < 0) dY = -Math.Sqrt(Math.Abs(dY));
axis1 = new FigureAxis(mouse_right_down_axis.xAxis.min - dX, mouse_right_down_axis.xAxis.max + dX,
mouse_right_down_axis.yAxis.min - dY, mouse_right_down_axis.yAxis.max + dY,
mouse_right_down_axis.xAxis.pxSize, mouse_right_down_axis.yAxis.pxSize);
public void Zoom(double zoomFrac)
{
double newSpan = span / zoomFrac;
x1 = center - newSpan / 2;
x2 = center + newSpan / 2;
RecalculateScale();
}
public void ZoomPx(int px)
{
double dX = px * unitsPerPx;
double dXFrac = dX / (Math.Abs(dX) + span);
Zoom(Math.Pow(10, dXFrac));
}
This one feels pretty natural. It gets the dX as a fraction of the original window size (dXunits / axisWidthUnits) then applies the zoom function with 10^dX. That's a magical number that feels really nice, and it automatically slows down at extremes.
double dX = (mouse_right_down_position.X - mouse_position.X) * mouse_right_down_axis.xAxis.unitsPerPx;
double dY = (mouse_position.Y - mouse_right_down_position.Y) * mouse_right_down_axis.yAxis.unitsPerPx;
double dXFrac = dX / (Math.Abs(dX) + (mouse_right_down_axis.xAxis.max - mouse_right_down_axis.xAxis.min));
double dYFrac = dY / (Math.Abs(dY) + (mouse_right_down_axis.yAxis.max - mouse_right_down_axis.yAxis.min));
axis1 = new FigureAxis(mouse_right_down_axis.xAxis.min, mouse_right_down_axis.xAxis.max,
mouse_right_down_axis.yAxis.min, mouse_right_down_axis.yAxis.max,
mouse_right_down_axis.xAxis.pxSize, mouse_right_down_axis.yAxis.pxSize);
axis1.Zoom(Math.Pow(10, dXFrac), Math.Pow(10, dYFrac)); // THE MAGIC HAPPENS HERE
Clear();
RedrawFrame();
This class is helpful to track the mouse for left-click-pan / right-click-zoom applications. I instantiate it at a form level, then call its down/up/move methods from within down/up/move events.
public class MouseTracker
{
Point posDown;
Point posUp;
Point posMove;
Point dragDelta;
Point dropDelta;
bool panning = false;
bool zooming = false;
public void Down()
{
posDown = new Point(Cursor.Position.X, Cursor.Position.Y);
if (Control.MouseButtons == MouseButtons.Left)
{
panning = true;
Console.WriteLine($"pan started at: ({posDown.X}, {posDown.Y})");
}
else if (Control.MouseButtons == MouseButtons.Right)
{
zooming = true;
Console.WriteLine($"zoom started at: ({posDown.X}, {posDown.Y})");
}
}
public void Up()
{
posUp = new Point(Cursor.Position.X, Cursor.Position.Y);
dropDelta = dragDelta;
if (panning)
{
Console.WriteLine($"pan ended at: ({dropDelta.X}, {dropDelta.Y})");
panning = false;
}
if (zooming)
{
Console.WriteLine($"zoom ended at: ({dropDelta.X}, {dropDelta.Y})");
zooming = false;
}
}
public void Move()
{
posMove = new Point(Cursor.Position.X, Cursor.Position.Y);
if (panning || zooming)
Drag();
}
private void Drag()
{
dragDelta = new Point(posMove.X - posDown.X, posMove.Y - posDown.Y);
if (panning)
{
Console.WriteLine($" pan drag: ({dragDelta.X}, {dragDelta.Y})");
}
else if (zooming)
{
Console.WriteLine($"zoom drag: ({dragDelta.X}, {dragDelta.Y})");
}
}
}
private void pb_MouseDown(object sender, MouseEventArgs e) { mouseTracker.Down(); }
private void pb_MouseUp(object sender, MouseEventArgs e) { mouseTracker.Up(); }
private void pb_MouseMove(object sender, MouseEventArgs e) { mouseTracker.Move(); }