wpf鼠標捕獲與控件交互——UIElement.CaptureMouse

應用場景是這樣的,我須要拖動一個元素在屏幕上移動,註冊了被移動元素的MouseMove事件,可是當鼠標移到被移動元素的外面時,移動失效,且鼠標的手勢變成了普通的箭頭形狀,因而就找到了如下的解決方案。this

本例實現了一個鼠標控制控件移動的簡單例子,配合鼠標捕獲達成預想效果:xml

1.新建一個wpf應用程序,爲了演示效果,xaml簡單修改以下:共有兩個圓(綠、黃),下面將要實現如何用鼠標拖動他們移動。事件

<Window x:Class="WpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
  <Canvas x:Name="LayoutRoot" MouseLeftButtonDown="LayoutRoot_MouseLeftButtonDown" MouseLeftButtonUp="LayoutRoot_MouseLeftButtonUp" MouseMove="LayoutRoot_MouseMove"> 
    <Ellipse Canvas.Left="100" Canvas.Top="100" Width="70" Height="70" Fill="Green" />
    <Ellipse Canvas.Left="200" Canvas.Top="30" Width="90" Height="90" Fill="Yellow" />
  </Canvas>
</Window>ip

2.後臺cs以下it

/// <summary>
/// MainWindow.xaml 的交互邏輯
/// </summary>
public partial class MainWindow : Window
{
  public MainWindow()
  {
    InitializeComponent();
  }io

  Point pBefore = new Point();//鼠標點擊前座標
  Point eBefore = new Point();//圓移動前座標
  bool isMove = false;//是否須要移動class

  //Root 鼠標左鍵按下事件
  private void LayoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  {
    if (e.OriginalSource.GetType() == typeof(Ellipse))
    {
      this.pBefore = e.GetPosition(null);//獲取點擊前鼠標座標
      Ellipse el = (Ellipse)e.OriginalSource;
      this.eBefore = new Point(Canvas.GetLeft(el), Canvas.GetTop(el));//獲取點擊前圓的座標
      isMove = true;//開始移動了
      el.CaptureMouse();//鼠標捕獲此圓
    }
  }後臺

  //Root 鼠標左鍵放開事件
  private void LayoutRoot_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  {
    if (e.OriginalSource.GetType() == typeof(Ellipse))
    {
      Ellipse el = (Ellipse)e.OriginalSource;
      isMove = false;//結束移動了
      el.ReleaseMouseCapture();//鼠標釋放此圓
    }
  }object

  //Root 鼠標移動事件
  private void LayoutRoot_MouseMove(object sender, MouseEventArgs e)
  {
    if (e.OriginalSource != null && e.OriginalSource.GetType() == typeof(Ellipse) && isMove)
    {
      Ellipse el = (Ellipse)e.OriginalSource;
      Point p = e.GetPosition(null);//獲取鼠標移動中的座標
      Canvas.SetLeft(el, eBefore.X + (p.X - pBefore.X));
      Canvas.SetTop(el, eBefore.Y + (p.Y - pBefore.Y));
    }
  }程序

}

由於不知道鼠標將會點擊圓的哪個部位,因此須要計算鼠標座標pBefore,設置圓的座標eBefore;
這裏在鼠標左鍵按下點擊圓的時候,設置了CaptureMouse,在鼠標鬆開左鍵時,設置ReleaseMouseCapture,試着註釋掉這兩行,觀察程序運行的不一樣效果:

(1).移動其中一個圓,當碰到其餘圓的時候:

設置了鼠標捕獲的,移動中的圓將穿過其餘圓而不形成影響;

沒有設置鼠標捕獲的,移動中的圓,碰到其餘圓的時候,將會發生跳躍,變成移動其餘的圓;

(2).移動圓至窗口邊緣,甚至是窗口以外:

設置了鼠標捕獲的,圓能夠被移動到窗口以外;

沒有設置鼠標捕獲的,圓將被束縛在窗口以內;

能夠試着只保留CaptureMouse,而註釋掉ReleaseMouseCapture,鼠標在捕獲圓以後將沒法釋放,你甚至將沒法點擊窗口左上角的關閉按鈕;

鼠標捕獲與釋放CaptureMouse與ReleaseMouseCapture,在一些鼠標與控件的交互處理上將會體現出很大的做用,由於在你捕獲一個控件時,鼠標將沒法再操做到其餘控件,同時也不會受其餘控件的影響

相關文章
相關標籤/搜索