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

    勾选 xcode的 CoreDate会帮我们自动创建 CoreData 但是我们通常不那样使用,通常把 CoreDate 在单利类中创建, // // ZYDAO.h // StoryboardTes ...

  2. Mac 10.9 自带apache2虚拟目录设置

    花了好几天时间做这个事,终于成功,把正确的做法记录一下. 如果是第一次使用apache,可以先执行sudo apachectl start,然后在浏览器里打开http://localhost看看效果, ...

  3. 给jdk写注释系列之jdk1.6容器(6)-HashSet源码解析&Map迭代器

    今天的主角是HashSet,Set是什么东东,当然也是一种java容器了.      现在再看到Hash心底里有没有会心一笑呢,这里不再赘述hash的概念原理等一大堆东西了(不懂得需要先回去看下Has ...

  4. nmap命令-----高级用法

    探测主机存活常用方式 (1)-sP :进行ping扫描 打印出对ping扫描做出响应的主机,不做进一步测试(如端口扫描或者操作系统探测):  下面去扫描10.0.3.0/24这个网段的的主机 nmap ...

  5. 随机生成MyEclipse注册码

    package com.registercode; import java.io.BufferedReader;import java.io.IOException;import java.io.In ...

  6. 【转载】Kafka实现篇之消息和日志

    http://blog.csdn.net/honglei915/article/details/37760631 消息格式 日志 一个叫做“my_topic”且有两个分区的的topic,它的日志有两个 ...

  7. Android之ORMLite实现数据持久化的简单使用

    Android中内置了sqlite,但是常用的开发语言java是面向对象的,而数据库是关系型的,二者之间的转化每次都很麻烦.(作为程序员,应该学会偷懒)而Java Web开发中有很多orm框架(其实我 ...

  8. Servlet之初识

    doHeader 用于处理HEADER请求doGet 用于处理GET请求,也可以自动的支持HEADER请求doPost 用于处理POST请求 doPut 用于处理PUT请求 doDelete 用于处理 ...

  9. VR开发中性能问题—OculusWaitForGPU

    http://blog.csdn.net/cartzhang/article/details/50788894 VR开发中性能问题-OculusWaitForGPU 本文章由cartzhang编写,转 ...

  10. ListView onItemClick(AdapterView<?> parent, View view, int position, long id)参数详解

    public void onItemClick(AdapterView<?> parent, View view, int position, long id) { parent.getA ...