我可以扩展Button以添加RightClick事件,以便保持图形副作用吗?

Gra*_*ier 5 c# wpf button right-click

我正在尝试扩展Button以添加RightClick事件.

我的客户想要一个按钮来执行不同的操作,具体取决于您是左键单击还是右键单击.我希望有一个简单的右键点击事件,但结果却没有.

我更喜欢Button的视觉行为与之前存在的Click事件相同,但事实证明这很难.单击并拖动按钮时,按钮会出现许多图形行为.

  • 单击时,按钮会降低.如果你拖下降低的按钮,它会升起(例如,降低).您拖动的任何其他按钮都会忽略它.
  • 当您向后拖动原始按钮时,它将再次降低.
  • 如果您拖动然后释放,原始按钮的状态应该重置(即您无法重新点击并再次拖动).

如果左键单击视觉效果与右键单击视觉效果不匹配,这些小图形怪癖将看起来很粗糙.

目前我坚持这样:如果右键单击并按住按钮,然后拖动按钮,如何检测用户是否取消点击?我需要知道这一点,所以我知道不要在重新进入时重新按下按钮.

一个更广泛的问题:我是否走上正轨?我以前找不到任何人这样做过的人.我的代码如下.

public class RightClickButton : Button
{
    public event RoutedEventHandler RightClick;

    public RightClickButton()
    {
        this.MouseRightButtonDown += new System.Windows.Input.MouseButtonEventHandler(RightClickButton_MouseRightButtonDown);
        this.MouseRightButtonUp += new System.Windows.Input.MouseButtonEventHandler(RightClickButton_MouseRightButtonUp);
        this.MouseEnter += new System.Windows.Input.MouseEventHandler(RightClickButton_MouseEnter);
        this.MouseLeave += new System.Windows.Input.MouseEventHandler(RightClickButton_MouseLeave);
    }

    void RightClickButton_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        this.IsPressed = true;
    }

    void RightClickButton_MouseRightButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        this.IsPressed = false;
        if (RightClick != null)
            RightClick.Invoke(this, e);
    }

    void RightClickButton_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
    {
        if (this.IsPressed)
            this.IsPressed = false;
    }

    void RightClickButton_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
    {
        if (this.IsFocused && Mouse.RightButton == MouseButtonState.Pressed)
            this.IsPressed = true;
    }
}
Run Code Online (Sandbox Code Playgroud)

Gra*_*ier 3

感谢对我的另一个问题的回答,这就是我想到的。

XP 和 Win7 的行为似乎可能存在一些差异。我需要在 Win7 上进一步测试。

public class RightClickButton : Button
{
    public event RoutedEventHandler RightClick;

    private bool _clicked = false;

    public RightClickButton()
    {
        this.MouseRightButtonDown += new System.Windows.Input.MouseButtonEventHandler(RightClickButton_MouseRightButtonDown);
        this.MouseRightButtonUp += new System.Windows.Input.MouseButtonEventHandler(RightClickButton_MouseRightButtonUp);
    }

    // Subclasses can't invoke this event directly, so supply this method
    protected void TriggerRightClickEvent(System.Windows.Input.MouseButtonEventArgs e)
    {
        if (RightClick != null)
            RightClick(this, e);
    }

    void RightClickButton_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        this.IsPressed = true;
        CaptureMouse();
        _clicked = true;
    }

    void RightClickButton_MouseRightButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        ReleaseMouseCapture();

        if(this.IsMouseOver && _clicked)
        {
            if (RightClick != null)
                RightClick.Invoke(this, e);
        }

        _clicked = false;
        this.IsPressed = false;
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);

        if (this.IsMouseCaptured)
        {
            bool isInside = false;

            VisualTreeHelper.HitTest(
                this,
                d =>
                {
                    if (d == this)
                    {
                        isInside = true;
                    }

                    return HitTestFilterBehavior.Stop;
                },
                ht => HitTestResultBehavior.Stop,
                new PointHitTestParameters(e.GetPosition(this)));

            if (isInside)
                this.IsPressed = true;
            else
                this.IsPressed = false;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)