The first everyone seems to run into is IsMouseOver. This is easily detected by syncing the MouseEnter and MouseLeave events and setting your own Boolean. When this changes, you might want to call Invalidate() and in OnPaint draw in a hover effect.
Similar to IsMouseOver is IsMouseDown. When a MouseDown occurs, you set a Boolean flag, when a matching MouseUp or MouseCaptureChanged occurs, you reset. MouseCaptureChanged needs to be taken into account in the case that someone uses ALT+TAB or someone locks the computer or calls manually releases capture.
Finally, there’s BeginDrag. BeginDrag occurs when you have pressed the mouse down and moved it farther away than SystemInformation.DragSize. When MouseDown occurs, you snap the original MouseDownLocation. When subsequent MouseMoves occur, you compare the current location to see if it has moved sufficiently. At the same time as IsMouseDown is set to false, call EndDrag.
Sounds like a drag? It is. And people keep re-writing the same logic over and over again. So here’s a MouseWatch class that does all of that for you.
Sample 1: IsMouseOver
public Form1() {
- InitializeComponent();
_mouseWatch = new MouseWatch(this);
_mouseWatch.PropertyChanged += MouseWatch_PropertyChanged;
this.Paint += new PaintEventHandler(Form1_Paint);
}
/// when IsMouseOver changes, Invalidate so we can
/// draw a different effect in OnPaint
void MouseWatch_PropertyChanged(object sender, PropertyChangedEventArgs e) {
- if (e.PropertyName == "IsMouseOver") {
- this.Invalidate();
}
/// paint an effect based on the IsMouseOver state
void Form1_Paint(object sender, PaintEventArgs e) {
- if (_mouseWatch != null && _mouseWatch.IsMouseOver) {
- e.Graphics.DrawEllipse(Pens.Blue, this.ClientRectangle);
}
}
Sample 2: Databinding IsMouseDown to BackColor
public Form1() {
- InitializeComponent();
_mouseWatch = new MouseWatch(this);
// Databind the BackColor property to IsMouseDown property
Binding binding = this.DataBindings.Add("BackColor",
_mouseWatch, "IsMouseDown", // object and prop to bind from
true // formatting enabled so we can convert bool to color
);
binding.Format += new ConvertEventHandler(BackColorFormat);
}
/// if the mouse is over, turn the background orange, else green
void BackColorFormat(object sender, ConvertEventArgs e) {
- if ((bool)e.Value) {
- BackColor = Color.Orange;
else {
- BackColor = Color.Green;
Sample 3: Drawing a Rubber Band on Drag
public Form1() {
InitializeComponent();
_mouseWatch = new MouseWatch(this);
_mouseWatch.BeginDrag += MouseWatch_BeginDrag;
_mouseWatch.Drag += MouseWatch_Drag;
_mouseWatch.EndDrag += MouseWatch_EndDrag;
}
private Rectangle _lastRect;
/// use ControlPaint to XOR a rubber band to the screen
private void PaintRubberBand(Rectangle rect) {
- ControlPaint.DrawReversibleFrame(_lastRect,
Color.Blue, FrameStyle.Thick);
_lastRect = rect;
ControlPaint.DrawReversibleFrame(_lastRect,
Color.Blue, FrameStyle.Thick);
}
/// use the mouse watch to get the starting and current locations
/// to adjust the size of the rubber band
void MouseWatch_Drag(object sender, EventArgs e) {
if (!_mouseWatch.MouseDownLocation.HasValue) {
- return;
}
Point mouseDownLocation = PointToScreen(_mouseWatch.MouseDownLocation.Value);
Point currentMouseLocation = PointToScreen(_mouseWatch.CurrentMouseLocation);
Rectangle newRect = Rectangle.FromLTRB(
Math.Min(mouseDownLocation.X, currentMouseLocation.X),
Math.Min(mouseDownLocation.Y, currentMouseLocation.Y),
Math.Max(mouseDownLocation.X, currentMouseLocation.X),
Math.Max(mouseDownLocation.Y, currentMouseLocation.Y));
PaintRubberBand(newRect);
}
// erase the rubber band
void MouseWatch_EndDrag(object sender, EventArgs e) {
- PaintRubberBand(Rectangle.Empty);
}
// begin drawing the rubber band
void MouseWatch_BeginDrag(object sender, EventArgs e) {
- MouseWatch_Drag(sender, e);
}
No comments:
Post a Comment