应用场景是这样的,我需要拖动一个元素在屏幕上移动,注册了被移动元素的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,在一些鼠标与控件的交互处理上将会体现出很大的作用,因为在你捕获一个控件时,鼠标将无法再操作到其他控件,同时也不会受其他控件的影响;

wpf鼠标捕获与控件交互——UIElement.CaptureMouse的更多相关文章

  1. WPF 使用鼠标拖动一个控件的实现[2018.7.15]

    原文:WPF 使用鼠标拖动一个控件的实现[2018.7.15] Q:已经把一个Shape和一个TextBlock组合起来放到了一个Grid中,现在想要实现用鼠标拖动这个Grid到任意位置的功能,如何做 ...

  2. 在WPF中使用WinForm控件方法

    1.      首先添加对如下两个dll文件的引用:WindowsFormsIntegration.dll,System.Windows.Forms.dll. 2.      在要使用WinForm控 ...

  3. WPF Adorner+附加属性 实现控件友好提示

    标题太空泛,直接上图 无论是在验证啊,还是提示方面等一些右上角的角标之类的效果,我们会怎么做? 这里介绍一种稍微简单一些的方法,利用附加属性和Adorner来完成. 例如WPF自带的控件上要加这样的效 ...

  4. WPF中的ControlTemplate(控件模板)(转)

    原文地址 http://www.cnblogs.com/zhouyinhui/archive/2007/03/28/690993.html WPF中的ControlTemplate(控件模板)     ...

  5. [转]在WPF中使用WinForm控件方法

    本文转自:http://blog.csdn.net/lianchangshuai/article/details/6415241 下面以在Wpf中添加ZedGraph(用于创建任意数据的二维线型.条型 ...

  6. WPF基础篇之控件模板(ControlTemplate)

    WPF中每一个控件都有一个默认的模板,该模板描述了控件的外观以及外观对外界刺激所做出的反应.我们可以自定义一个模板来替换掉控件的默认模板以便打造个性化的控件. 与Style不同,Style只能改变控件 ...

  7. WPF中的ControlTemplate(控件模板)

    原文:WPF中的ControlTemplate(控件模板) WPF中的ControlTemplate(控件模板)                                             ...

  8. 【WPF】DPI对控件定位产生的影响

    原文:[WPF]DPI对控件定位产生的影响 需求 程序界面上是一个Window,当用户点击桌面上除此Window之外的任何地方,都要把这个window隐藏掉.程序有个托盘图标,点击托盘图标不能隐藏wi ...

  9. [转]WPF中的ControlTemplate(控件模板)

    WPF中的ControlTemplate(控件模板)                                                                           ...

随机推荐

  1. VMware系统运维(三 )SQL Server 2008 R2安装

    1. 点击"全新SQL Server 独立安装或向现有安装添加功能" 2.验证通过,点击确定. 3.输入数据库密钥,必须支持正版,不然微软打你屁屁,嘻嘻 4.不接受不让你过,所以不 ...

  2. cx_Oracle安装说明

    简介 cx_Oracle是用python连接oracle的驱动模块,参考文章: [cx_Oracle文档](http://cx-oracle.sourceforge.net/html/index.ht ...

  3. Adobe Edge Animate --使用HTML5实现手机摇一摇功能

    Adobe Edge Animate --使用HTML5实现手机摇一摇功能 版权声明: 本文版权属于 北京联友天下科技发展有限公司. 转载的时候请注明版权和原文地址. HTML5的发展日新月异,其功能 ...

  4. js实现归并排序

    function merge(s_arr, d_arr, start, middle, end){ var s_temp = start; var m_temp = middle+1; var tem ...

  5. fatal error LNK1168: cannot open Debug/opreat.exe for writing

    问题:LINK : fatal error LNK1168: cannot open Debug/opreat.exe for writing           Error executing li ...

  6. nodejs3-事件zepto.js事件

    Event代表事件名,listener代表事件处理函数,括号内的参数代表可选参数: addListener(event,listener):对指定事件绑定事件处理函数 on(同上):addListen ...

  7. Spring(3.2.3) - Beans(7): 延迟实例化

    默认情况下,Spring IoC 容器启动后,在初始化过程中,会以单例模式创建并配置所有使用 singleton 定义的 Bean 的实例.通常情况下,提前实例化 Bean 是可取的,因为这样在配置中 ...

  8. 使用spring+hibernate+atomikos+tomcat构建分布式事务

    本文通过一个demo,介绍如何使用spring+hibernate+atomikos+tomcat构建在一个事务中涉及两个数据源的web应用. demo功能:实现一个能成功提交和回滚的涉及两个数据库数 ...

  9. 程序生成SiteMapPath文件

    //创建站点地图 private void CreateSiteMap(DataSet ds) { XmlDeclaration declareation; declareation = xmlDoc ...

  10. 百度ueditor编辑器背景不显示问题

    网友办法:http://www.hongxuejing.com/hulianwang/ueditor_not_show_background-33.html 官方办法:http://fex-team. ...