• wpf鼠标捕获与控件交互——UIElement.CaptureMouse


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

  • 相关阅读:
    PHP脚本 校验/补全身份证号码
    常用解压缩软件打包速度比拼
    用ffmpeg对视频转码,视频格式转换
    PHP使用readability提取任意网页正文内容
    PHP获取/判断HTML/网页的charset/编码
    缺少HTTPOnly和Secure属性解决方案
    7Zip/7z命令行中英文对照说明
    RSA加解密、签名验签算法,附代码
    WPF 笔记 十 项目资源收集
    WPF 笔记 九 通过UserControl实例说明依赖属性和绑定
  • 原文地址:https://www.cnblogs.com/moonlight-zjb/p/4700196.html
Copyright © 2020-2023  润新知