-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathMouseCanvas.cs
173 lines (145 loc) · 6.3 KB
/
MouseCanvas.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
Maneubo is an application that provides a virtual maneuvering board and target
motion analysis.
http://www.adammil.net/Maneubo
Copyright (C) 2011-2020 Adam Milazzo
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
using System.Drawing;
using System.Windows.Forms;
namespace Maneubo
{
delegate void MouseDragEventHandler(object sender, MouseDragEventArgs e);
#region MouseDragEventArgs
sealed class MouseDragEventArgs : MouseEventArgs
{
public MouseDragEventArgs(MouseButtons button, Point originalPoint, int x, int y, int offsetX, int offsetY) : base(button, 1, x, y, 0)
{
start = originalPoint;
offset = new Size(offsetX, offsetY);
}
public Point Start
{
get { return start; }
}
public Size Offset
{
get { return offset; }
}
Point start;
Size offset;
}
#endregion
#region MouseCanvas
class MouseCanvas : Control
{
public MouseCanvas()
{
SetStyle(ControlStyles.Selectable, true);
SetStyle(ControlStyles.ContainerControl | ControlStyles.StandardClick | ControlStyles.StandardDoubleClick | ControlStyles.UserMouse,
false);
}
public event MouseEventHandler MouseDragStart;
public event MouseDragEventHandler MouseDrag;
public event MouseDragEventHandler MouseDragEnd;
public void CancelMouseDrag()
{
if(dragButton != MouseButtons.None)
{
mouseDownPos[ButtonToIndex(dragButton)] = new Point(-1, -1); // mark the drag button as released
dragButton = MouseButtons.None; // clear the dragging flag
Capture = false; // stop capturing the mouse
}
}
protected virtual void OnMouseDragStart(MouseEventArgs e)
{
if(MouseDragStart != null) MouseDragStart(this, e);
}
protected virtual void OnMouseDrag(MouseDragEventArgs e)
{
if(MouseDrag != null) MouseDrag(this, e);
}
protected virtual void OnMouseDragEnd(MouseDragEventArgs e)
{
if(MouseDragEnd != null) MouseDragEnd(this, e);
}
/* use low-level mouse events to implement higher-level click and drag events */
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
int button = ButtonToIndex(e.Button);
if(button == -1) return; // ignore unsupported buttons
// when a mouse button is pressed, mark the location. this serves as both an indication that the button is pressed
// and stores the beginning of the drag, if the user drags the mouse
mouseDownPos[button] = e.Location;
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if(dragButton != MouseButtons.None) // if we're currently dragging, fire a drag event
{
int xd = e.X-lastDragPos.X, yd = e.Y-lastDragPos.Y;
if(xd == 0 && yd == 0) return;
OnMouseDrag(new MouseDragEventArgs(dragButton, mouseDownPos[ButtonToIndex(dragButton)], e.X, e.Y, xd, yd));
// update the last drag point so we can send a delta to OnMouseDrag()
lastDragPos = e.Location;
}
else // otherwise, see if we should start dragging.
{
int button = ButtonToIndex(e.Button);
if(button == -1 || !IsMouseDown(button)) return; // ignore unsupported buttons
int xd = e.X-mouseDownPos[button].X, yd = e.Y-mouseDownPos[button].Y;
int dist = xd*xd + yd*yd; // the squared distance
if(dist >= 16) // if the mouse is moved four pixels or more, start a drag event
{
dragButton = e.Button;
lastDragPos = e.Location;
// issue a drag start using the stored location of where the mouse was originally pressed
OnMouseDragStart(new MouseEventArgs(e.Button, e.Clicks, mouseDownPos[button].X, mouseDownPos[button].Y, e.Delta));
if(dragButton != MouseButtons.None) // if the drag wasn't immediately cancelled
{
Capture = true; // capture the mouse so we can be sure to receive the end of the drag
// then issue a drag event because the mouse has since moved. always specify the original drag button.
OnMouseDrag(new MouseDragEventArgs(dragButton, mouseDownPos[ButtonToIndex(dragButton)], e.X, e.Y, xd, yd));
}
}
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
int button = ButtonToIndex(e.Button);
if(button == -1) return; // ignore unsupported buttons
if(dragButton == e.Button) // if we're currently dragging, end the drag
{
OnMouseDragEnd(new MouseDragEventArgs(dragButton, mouseDownPos[ButtonToIndex(dragButton)], e.X, e.Y, 0, 0)); // specify the original drag button
dragButton = MouseButtons.None; // clear our drag button flag
Capture = false; // stop capturing the mouse so other things can use it
}
else if(IsMouseDown(button)) // otherwise we're not currently dragging. was the button pressed over the control?
{
OnMouseClick(e); // yes, so now that it's been released, signal a click event.
}
mouseDownPos[button] = new Point(-1, -1); // in any case, mark the button as released.
}
bool IsMouseDown(int index) { return mouseDownPos[index].X >= 0; }
Point[] mouseDownPos = new Point[3] { new Point(-1, -1), new Point(-1, -1), new Point(-1, -1) };
Point lastDragPos;
MouseButtons dragButton = MouseButtons.None;
static int ButtonToIndex(MouseButtons button)
{
return button == MouseButtons.Left ? 0 : button == MouseButtons.Middle ? 1 : button == MouseButtons.Right ? 2 : -1;
}
}
#endregion
}