应用场景是这样的,我需要拖动一个元素在屏幕上移动,注册了被移动元素的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. tornado简单的验证码

    1.html代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  2. 记第一次web前端校招笔试

    是的,我今晚跑到隔壁学校参加某电商公司的宣讲会+现场笔试.只有俩字可以形容:苦笑! 在寝室复习了下以前学习的关于前端方面的知识,重点是JavaScript,javaweb开发技术(jsp+servle ...

  3. mysql颠覆实战笔记(二)-- 用户登录(一):唯一索引的妙用

    版权声明:笔记整理者亡命小卒热爱自由,崇尚分享.但是本笔记源自www.jtthink.com(程序员在囧途)沈逸老师的<web级mysql颠覆实战课程 >.如需转载请尊重老师劳动,保留沈逸 ...

  4. php实现MVC

    在PHP中使用MVC越来越流行了,特别是在一些开源的框架当中.MVC足以应对大多数的情况,但还有一些情况是其不太适合的,如比较简单的个人博客,对于只有几百篇文章量级的博客,使用MVC让人觉得有些太复杂 ...

  5. mysql输出的错误提示是法语

    参考MySQL用户手册 http://dev.mysql.com/doc/refman/5.5/en/error-message-language.html mysql.ini 文件里头有一个参数叫做 ...

  6. hdu 3093 动态规划

    思路:直接引用论文的话. 暂时先不考虑“使剩下的物品都放不下”的条件,那就是求 0-1 背包的所有可行方案. 用 Fi[j]表示前 i 件物品中选若干件总体积为 j 的方案数,初始为 F0[0]=1, ...

  7. nginx实现域名重定向

    一般网站默认的访问端口为80,当多个域名指向同一个服务器IP时,可以nginx进行重定向,分别指向不同的目的地址或其他主机. 在nginx目录下的conf/vhost子目录下建两个conf文件,hos ...

  8. ECharts地图详解 【转】

    $(function() { // 路径配置 require.config({ paths : { // echarts: 'http://echarts.baidu.com/build/dist' ...

  9. reduce + Promise 顺序执行代码

    本文地址: http://www.cnblogs.com/jasonxuli/p/4398742.html 下午的太阳晒得昏昏沉沉,和上周五一样迷糊,看一段代码半天没看明白,刚才不知不觉眯了几分钟,醒 ...

  10. VS2013编译GLUI

    vs自带的OpenGL为1.1版本,太老了. 1,编译glut https://www.opengl.org/resources/libraries/glut/glut37.zip 查看生成路径,可以 ...