I have a List<Rectangle> myRectangles
that are rendered in a Panel control. If I want to fire an event handler when the mouse is within any of myRectangles, is my best option to do 'foreach'? And then go do whatever myRectangle.OnMouseMove() would do?
views:
100answers:
4You could create a control which has two rectangles one inside another. The outside rectangle's OnMouseMove would be exposed. The outside rectangle would be invisible. This way you could let Windows manage the event calling and not have cluttered code.
This would seem to be a good use for Reactive LINQ, or Rx, but I am more familiar with using the former.
http://tomasp.net/blog/reactive-ii-csevents.aspx
You will want to optimize to determine which rectangles may be possibly intersected, but just use the OnMouseMove and then in your LINQ query you will find whichever rectangles are entered.
This could potentially be a performance hog.
I assume you must be using Winforms? If so, you might want to consider making the rectangles separate child controls (rendering whatever the rectangle looks like in OnPaint
) and use the mouse events provided by Control
.
Don't use controls for your rectangles, they are horribly expensive and can't overlap. You can't make it reliable with just the OnMouseMove() method, you'll miss the mouse moving outside of the panel when the user is moving the mouse fast and/or an edge of a rectangle is close to the panel border. It is easily solved with the Control.Capture property. Some sample code:
public event EventHandler InsideRectangles;
private List<Rectangle> mRectangles = new List<Rectangle>();
private bool mInside;
protected void OnInsideRectangles(EventArgs e) {
EventHandler handler = InsideRectangles;
if (handler != null) handler(this, e);
}
protected override void OnMouseMove(MouseEventArgs e) {
bool inside = false;
foreach (var rc in mRectangles) {
if (rc.Contains(e.Location)) {
inside = true;
break;
}
}
if (inside && !mInside) OnInsideRectangles(EventArgs.Empty);
this.Capture = inside;
mInside = inside;
base.OnMouseMove(e);
}