views:

100

answers:

4

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?

A: 

You 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.

Yuriy Faktorovich
+2  A: 

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.

James Black
Thanks for that link ! That is very "far out" C# programming !
BillW
@BillW - One advantage to using Reactive LINQ is that you could determine the slope of the direction, and predict which rectangle will be hit next, to improve performance.
James Black
@James Thanks. imho if calculation (prediction) of "slope" would be useful would depend on specific usage scenarios : ui's purpose, modal activities end-user's likely to do. imho in this particuar question we don't know enough, yet, about what the OP's intent/design/use case is. But, I find your comment fascinating, and it is appreciated. I have yet to "jump ship" from WinForms to WPF, but admit to being attracted to WPF's much more robust event control capabilities (bubbling as well as broadcasting). On the other hand I find the idea of round-tripping between C# and XAML real weird :)
BillW
A: 

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.

Zach Johnson
I was considering using/inheriting Control. However, there are performance considerations. First, this GUI needs to be as lightweight as possible. I'm creating reusable panels and as few controls (buttons, etc) as possible. According to MS, sticking to as much GDI+ as possible, will greatly improve performance. I need to reserve resources for where it really matters - I have planned implementations of near real-time monitoring of network communications and a resource expensive network server application.
dboarman
+1  A: 

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);
  }
Hans Passant
Thank you for your assistance. Very helpful, indeed.
dboarman