1

I want to open a context menu when the user right clicks on an object but I want to pass all other mouse hits through it.

  protected override HitTestResult HitTestCore( PointHitTestParameters hitTestParameters )
  {
     var hitPoint = hitTestParameters.HitPoint;
     if ( ( _xOffset <= hitPoint.X && hitPoint.X <= _xOffset + _width ) &&
          _isRightClick )
     {
        return new PointHitTestResult( this, hitPoint );
     }
     return null;
  }

How do I figure out _isRightClick?

Any better architected solutions are welcome. :)

chrislarson
  • 958
  • 2
  • 10
  • 20

2 Answers2

1

why not override the onmouseclick / onmouseup methods instead? they have a mouseeventargs that includes mousekey info.

    public override void OnMouseUp(EditableGraphicsLayer layer, MouseButtonEventArgs e)
    {
        if (IsRightButtonChanged(e))
        {
            // do stuff
        }
    }

    private bool IsRightButtonChanged(MouseButtonEventArgs args)
    {
        return args.ChangedButton == MouseButton.Right;
    }

EDIT: or, based on your comment, if you cannot override those methods and have to solve this in hittesting alone, maybe you could read the state of the mouse buttons from the static Mouse class like this for example:

Console.WriteLine(Mouse.RightButton);
mtijn
  • 3,610
  • 2
  • 33
  • 55
  • 1
    If my control has IsHitTestVisible=True, I won't be able to click on the controls that are drawn beneath it in z-order. And if I have IsHitTestVisible=False (like I have it now), I won't get those events without overriding HitTestCore like in the example above. But I want to make my decision on whether or not I return a hittestresult based on a right click vs any other hit. Unless I'm missing something. – chrislarson Oct 05 '11 at 14:12
  • well that wasn't apparent from your question.. but I updated my answer accordingly. – mtijn Oct 05 '11 at 14:20
  • Sorry for the confusion. I tried using Mouse.RightButton == MouseButtonState.Pressed. And that failed. I was pulling out my hair. It looks like you have to invalidate the visual so that the hittestinvalidateasync event gets fired by input manager. That's how I got it to work anyway. I posted an answer below. If you edit yours to include the code, I'll mark yours as the answer. – chrislarson Oct 05 '11 at 19:54
  • though that sounds tempting you really did the most important bit on your own and I cannot take credit for that, I'll settle for an upvote and suggest you mark your own answer as the answer ;-) – mtijn Oct 06 '11 at 06:55
0

NOTE: mtjin really helped push me in the right direction.

I got his idea to work by invalidating the visual when the prenotify event gets fired by inputmanager.

  public MyClass()
  {
     InitializeComponent();

     InputManager.Current.PreNotifyInput += InputManagerPreNotifyInput;
  }

  private void InputManagerPreNotifyInput( object sender, NotifyInputEventArgs e )
  {
     var mouseEventArgs = e.StagingItem.Input as MouseEventArgs;
     if ( mouseEventArgs == null )
        return;

     if ( mouseEventArgs.RoutedEvent == PreviewMouseDownEvent )
     {
        InvalidateVisual();
     }
  }

  protected override HitTestResult HitTestCore( PointHitTestParameters hitTestParameters )
  {
     var hitPoint = hitTestParameters.HitPoint;
     if ( ( _xOffset <= hitPoint.X && hitPoint.X <= _xOffset + _width ) &&
          Mouse.RightButton == MouseButtonState.Pressed )
     {
        return new PointHitTestResult( this, hitPoint );
     }

     return null;
  }
chrislarson
  • 958
  • 2
  • 10
  • 20