應用場景是這樣的,我需要拖動一個元素在屏幕上移動,注冊了被移動元素的MouseMove事件,但是當鼠標移到被移動元素的外面時,移動失效,且鼠標的手勢變成了普通的箭頭形狀,於是就找到了以下的解決方案。
本例實現了一個鼠標控制控件移動的簡單例子,配合鼠標捕獲達成預想效果:
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>
2.后台cs如下
/// <summary>
/// MainWindow.xaml 的交互邏輯
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
Point pBefore = new Point();//鼠標點擊前坐標
Point eBefore = new Point();//圓移動前坐標
bool isMove = false;//是否需要移動
//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();//鼠標釋放此圓
}
}
//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,在一些鼠標與控件的交互處理上將會體現出很大的作用,因為在你捕獲一個控件時,鼠標將無法再操作到其他控件,同時也不會受其他控件的影響;
