So, I’m working up a slick little WinForms application for a client and in the process, creating a custom UI to make things “pretty”.  I’m swapping out images in a picture box, based on if the mouse is entering or leaving, up or down, etc, etc.

Strange thing happened with one of my picture boxes however… when the user clicks on the picture box, it opens up a dialog.  The user interacts with the dialog, and the image isn’t correct based on the supposed position of the mouse in relation to the picture box.

I had attached my image manipulation routines to the following events:

  • Mouse Enter – Load Mouse Over image
  • Mouse Leave – Load Mouse Out image
  • Mouse Down – Load Mouse Down Image
  • Mouse Up – Load Mouse Over Image

That all worked out well.. then I attached a dialog to the Click event of the picture box.. here’s what happened:

  • Mouse Enter – Load Mouse Over Image
  • Mouse Down – Load Mouse Down Image
  • Mouse Click – Load the dialog
  • User interacts with the dialog
  • Mouse Up – Load Mouse Over Image

The problem here is.. the mouse is no longer over the picture box.  The showing of the dialog suspends the control events fired while that dialog is active.. once the dialog goes away, the control events continue to fire, thus loading the mouse over image, even though the mouse is no longer over the picture box (cause it was moved while the user interacted with the dialog)

I needed a simple way to test to see if the mouse pointer was over the picture box.  This would allow me to check and see if I need to change an image during an event or not (or default to the “normal mouse out” image).

MousePosition

The MousePosition property returns a Point that represents the mouse cursor position at the time the property was referenced. The coordinates indicate the position on the screen, not relative to the control, and are returned regardless of whether the cursor is positioned over the control. The coordinates of the upper-left corner of the screen are 0,0.

That’s all well and good.. but that controls top, left, width and height are relative to the container (or containing form)…

PointToScreen()

Simply put, PointToScreen takes a given Point, and translates that point into screen coordinates.

Putting it all together

So now we can take what we’ve learned.. and create a simple little helper method to check if the mouse is currently over any control we want:

private static bool IsMouseOver(Control ctl)
{
if (MousePosition.IsEmpty) return false;
var frmOrigin = new Point(0, 0);
var ctlRect = new Rectangle(ctl.PointToScreen(frmOrigin), ctl.Size);
return ctlRect.Contains(MousePosition);
}

Let’s take it a step further and create an extension method for control to test if the control’s rectangle contains a given point..

public static class ControlExtensions
{
/// <summary>
/// Determines whether the specified point exists within the given controls Rectangle
/// </summary>
/// <param name="ctl">The Control.</param>
/// <param name="point">The point.</param>
/// <returns>
/// <c>true</c> if the specified CTL contains point; otherwise, <c>false</c>.
/// </returns>
public static bool ContainsPoint(this Control ctl, Point point)
{
if (point.IsEmpty) return false;
var origin = new Point(0, 0);
var ctlRect = new Rectangle(ctl.PointToScreen(origin), ctl.Size);
return ctlRect.Contains(point);
}
}


Which makes our final event code, very tight :)

private void picBoxFolder_MouseUp(object sender, MouseEventArgs e)
{
if (picBoxFolder.ContainsPoint(MousePosition))
picBoxFolder.Image = GetFolderImage(FolderButtons.Up);
}