c# - 我可以扩展 Button 以添加 Right Click 事件,同时保持图形副作用吗?

标签 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;
    }
}

最佳答案

感谢对 my other question 的回答,这就是我想出的。

看来 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;
        }
    }
}

关于c# - 我可以扩展 Button 以添加 Right Click 事件,同时保持图形副作用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9951361/

相关文章:

wpf - Caliburn.Micro 和自定义依赖属性不起作用

按钮的 Windows 加速器,在双符号后

wpf - 从隐藏到全尺寸动画控制的最简单方法?

带整数的 C# 按位运算符

c# - Actor 模型 (Akka.net) 中存储的状态在哪里?

c# - 在构造函数中分配类值?

c# - WPF .xaml 设计器异常

c# - 如何为 C# 中的按钮提供新位置?

javascript - CRM 2011 - Javascript 按钮 - 更改所有实体记录上的字段

c# - 内部 .Net Framework 数据提供程序错误 1