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

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

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

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

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

如果左键单击视觉效果与右键单击视觉效果不匹配,这些小图形怪癖将显得粗糙。

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

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

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

感谢我对其他问题的回答 ,这就是我提出的问题 。

似乎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; } } } 

如果你看一下ButtonBase的源代码,你会发现很难轻易地复制OnMouseLeftButtonDownOnMouseLeftButtonUp覆盖中发生的事情。

一个似乎运行得相当好的简单hack是从Button派生如下:

 public class MyButton : Button { protected override void OnMouseRightButtonDown(MouseButtonEventArgs e) { base.OnMouseRightButtonDown(e); // this line probably optional/not required base.OnMouseLeftButtonDown(e); } protected override void OnMouseRightButtonUp(MouseButtonEventArgs e) { base.OnMouseRightButtonUp(e); // this line probably optional/not required base.OnMouseLeftButtonUp(e); } } 

然后使用代替Xaml中的

我无法保证这在所有情况下都能正常工作,但它看起来确实有效,因为右键或左键单击时按钮的视觉行为是相同的。

只需添加我自己的2c。 这是基于@Grant给出的答案,其中包含以下更改:

  1. 这正确地使用_rightButtonDown标志,而不是CaptureMouse属性来确定处理,因为CaptureMouse可能已在其他地方设置(即这符合正确的封装。)

  2. 这支持ClickMode属性,允许Press值。

  3. 这正确地使用了OnRightClick处理程序,该处理程序的名称现在不仅遵循标准约定,而且还处理所有调用以引发RightClick事件而不是复制代码。 它也被标记为virtual以正确支持子类function,如果您覆盖该function,则可以处理/阻止所有RightClick事件。

  4. 我将其命名为EnhancedButton,以防我想添加其他function。

  5. 我已经包含了一个示例,说明如何定义样式以使其正确显示在ToolBar中

注意:在控件上实现RightClick事件的正确方法是作为RoutedEvent,而不是标准CLR事件。 但是,我将把这个留给读者来实现,以保持这个例子的简单。

这是EnhancedButton类的代码:

 public class EnhancedButton : Button { private bool _rightButtonDown = false; public EnhancedButton() { MouseRightButtonDown += RightClickButton_MouseRightButtonDown; MouseRightButtonUp += RightClickButton_MouseRightButtonUp; } #region RightClick Event public event RoutedEventHandler RightClick; protected virtual void OnRightClick(MouseButtonEventArgs e) { RightClick?.Invoke(this, e); } #endregion RightClick Event #region Event Handlers private void RightClickButton_MouseRightButtonDown(object sender, MouseButtonEventArgs e) { IsPressed = true; _rightButtonDown = true; CaptureMouse(); if(ClickMode == ClickMode.Press) OnRightClick(e); } private void RightClickButton_MouseRightButtonUp(object sender, MouseButtonEventArgs e) { if(!_rightButtonDown) return; ReleaseMouseCapture(); IsPressed = false; if(IsMouseOver && ClickMode == ClickMode.Release) OnRightClick(e); _rightButtonDown = false; } #endregion Event Handlers #region Overrides protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if(!_rightButtonDown) return; bool isInside = false; VisualTreeHelper.HitTest(this, d => { if (d == this) isInside = true; return HitTestFilterBehavior.Stop; }, ht => HitTestResultBehavior.Stop, new PointHitTestParameters(e.GetPosition(this))); IsPressed = isInside; } #endregion Overrides } 

以下是如何定义样式以使其与所有其他ToolBar按钮一样。 将其添加到工具栏的资源中,或者更好的是,设置工具栏样式以在样式中设置它,这样您就不必在任何地方手动添加它。

  

现在,它是标准Button控件的更兼容的直接替代品。

当然你可以这样做,为什么不呢?

只需实现Mouse-Up事件的事件,并检查是否按下了鼠标右键 – 如果为true,则调用之前添加的代理/事件,例如OnRightMouseClick。

查看路由事件的MSDN页面 – 是的,您正走在正确的轨道上。

问候,

当然,wpf允许您将命令绑定到控件。 首先连接窗口的命令绑定。

    

然后在按钮上注册右键单击绑定

  

来源: WPF命令绑定 – 鼠标点击

您可以使用PreviewMouseDown事件。 这将是这样的

  private void buttonTest_PreviewMouseDown(object sender, MouseButtonEventArgs e) { if (e.RightButton == MouseButtonState.Pressed) { MessageBox.Show("Right"); } else if (e.LeftButton == MouseButtonState.Pressed) { MessageBox.Show("Left"); } e.Handled = true; }