WPF:通过捕获鼠标事件来使Canvas中的所有控件都动起来

2023-10-16 14:58

本文主要是介绍WPF:通过捕获鼠标事件来使Canvas中的所有控件都动起来,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文地址:https://www.mgenware.com/blog/wp-content/uploads/2012/03/201203301315305256.png

曾经写过一篇文章:WPF:实现一个很简单的设计器(移动和缩放控件),讲了使用WPF中的Adorner来修饰Canvas中的元素从而使它们可以被移动或者缩放。今天讲通过原始事件的方法来使Canvas中的元素可以被移动。

首先就是定义一个Canvas,然后定义Canvas中的控件。接着使用MouseMove,MouseDown,MouseUp这三个Bubble类型的路由事件。我们将会在之后填充这三个事件。

XAML定义:

<Canvas Name="canvas"PreviewMouseMove="canvas_MouseMove"PreviewMouseDown="canvas_MouseDown"PreviewMouseUp="canvas_MouseUp"><Ellipse Fill="GreenYellow"Width="50"Height="50" Canvas.Left="10"Canvas.Top="10"/><Rectangle Fill="Orange"Width="100"Height="40"Canvas.Left="100"Canvas.Top="50"/><Button Canvas.Left="100"Canvas.Top="10"Content="A"/><TextBox Canvas.Left="130"Canvas.Top="20"Width="100"Text="Mgen"/>
</Canvas>

接下来,我们使用一种最原始的方法,首先在MouseDown事件中通过Mouse.DirectlyOver属性确定鼠标指向的Canvas中的控件,然后存下来控件和鼠标点击位置的偏移量,最后在MouseMove事件中设置控件更新的位置,这样控件就被移动了。当然,由于使用原始的鼠标点击事件,对于某些控件比如:Button、TextBox……由于它们对鼠标事件处理的特殊性,所以下面的代码无法移动上述控件(文章下面会给出更好的处理方式)

如下代码:

//选中控件的鼠标位置偏移量
Point targetPoint;//选中控件
UIElement targetElement;private void canvas_MouseDown(object sender, MouseButtonEventArgs e)
{//确定选中控件,然后设置选中控件targetElement = Mouse.DirectlyOver as UIElement;if (targetElement != null)targetPoint = e.GetPosition(targetElement);
}private void canvas_MouseUp(object sender, MouseButtonEventArgs e)
{//鼠标松开后,将选中控件设置成nulltargetElement = null;
}private void canvas_MouseMove(object sender, MouseEventArgs e)
{//确定鼠标左键处于按下状态并且有元素被选中if (e.LeftButton == MouseButtonState.Pressed && targetElement != null){var pCanvas = e.GetPosition(canvas);//设置最终位置Canvas.SetLeft(targetElement, pCanvas.X - targetPoint.X);Canvas.SetTop(targetElement, pCanvas.Y - targetPoint.Y);}
}

上面讲过,上述代码对于大多数控件都表现良好,但是对于某些对鼠标事件有依赖的控件会无法移动,所以我们使用另一种优化的方法,通过使用捕获鼠标事件来移动控件。

 

捕获鼠标通过UIElement.CaptureMouse方法,捕获鼠标后,即使鼠标不在控件上,相应的鼠标事件仍会被控件接受。取消捕获鼠标可以使用Mouse.Capture(null)方法,或者UIElement.ReleaseMouseCapture方法。

代码:(XAML不变)

//选中控件的鼠标位置偏移量
Point targetPoint;private void canvas_MouseDown(object sender, MouseButtonEventArgs e)
{var targetElement = e.Source as IInputElement;if (targetElement != null){targetPoint = e.GetPosition(targetElement);//开始捕获鼠标targetElement.CaptureMouse();}
}private void canvas_MouseUp(object sender, MouseButtonEventArgs e)
{//取消捕获鼠标Mouse.Capture(null);
}private void canvas_MouseMove(object sender, MouseEventArgs e)
{//确定鼠标左键处于按下状态并且有元素被选中var targetElement = Mouse.Captured as UIElement;if (e.LeftButton == MouseButtonState.Pressed && targetElement != null){var pCanvas = e.GetPosition(canvas);//设置最终位置Canvas.SetLeft(targetElement, pCanvas.X - targetPoint.X);Canvas.SetTop(targetElement, pCanvas.Y - targetPoint.Y);}
}

OK,现在所有控件都可以被移动了:

这篇关于WPF:通过捕获鼠标事件来使Canvas中的所有控件都动起来的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/220237

相关文章

WinForms中主要控件的详细使用教程

《WinForms中主要控件的详细使用教程》WinForms(WindowsForms)是Microsoft提供的用于构建Windows桌面应用程序的框架,它提供了丰富的控件集合,可以满足各种UI设计... 目录一、基础控件1. Button (按钮)2. Label (标签)3. TextBox (文本框

使用WPF实现窗口抖动动画效果

《使用WPF实现窗口抖动动画效果》在用户界面设计中,适当的动画反馈可以提升用户体验,尤其是在错误提示、操作失败等场景下,窗口抖动作为一种常见且直观的视觉反馈方式,常用于提醒用户注意当前状态,本文将详细... 目录前言实现思路概述核心代码实现1、 获取目标窗口2、初始化基础位置值3、创建抖动动画4、动画完成后

Python开发文字版随机事件游戏的项目实例

《Python开发文字版随机事件游戏的项目实例》随机事件游戏是一种通过生成不可预测的事件来增强游戏体验的类型,在这篇博文中,我们将使用Python开发一款文字版随机事件游戏,通过这个项目,读者不仅能够... 目录项目概述2.1 游戏概念2.2 游戏特色2.3 目标玩家群体技术选择与环境准备3.1 开发环境3

Java程序进程起来了但是不打印日志的原因分析

《Java程序进程起来了但是不打印日志的原因分析》:本文主要介绍Java程序进程起来了但是不打印日志的原因分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java程序进程起来了但是不打印日志的原因1、日志配置问题2、日志文件权限问题3、日志文件路径问题4、程序

Qt中QGroupBox控件的实现

《Qt中QGroupBox控件的实现》QGroupBox是Qt框架中一个非常有用的控件,它主要用于组织和管理一组相关的控件,本文主要介绍了Qt中QGroupBox控件的实现,具有一定的参考价值,感兴趣... 目录引言一、基本属性二、常用方法2.1 构造函数 2.2 设置标题2.3 设置复选框模式2.4 是否

Qt中QUndoView控件的具体使用

《Qt中QUndoView控件的具体使用》QUndoView是Qt框架中用于可视化显示QUndoStack内容的控件,本文主要介绍了Qt中QUndoView控件的具体使用,具有一定的参考价值,感兴趣的... 目录引言一、QUndoView 的用途二、工作原理三、 如何与 QUnDOStack 配合使用四、自

MySQL中动态生成SQL语句去掉所有字段的空格的操作方法

《MySQL中动态生成SQL语句去掉所有字段的空格的操作方法》在数据库管理过程中,我们常常会遇到需要对表中字段进行清洗和整理的情况,本文将详细介绍如何在MySQL中动态生成SQL语句来去掉所有字段的空... 目录在mysql中动态生成SQL语句去掉所有字段的空格准备工作原理分析动态生成SQL语句在MySQL

C#如何动态创建Label,及动态label事件

《C#如何动态创建Label,及动态label事件》:本文主要介绍C#如何动态创建Label,及动态label事件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#如何动态创建Label,及动态label事件第一点:switch中的生成我们的label事件接着,

Python实现将MySQL中所有表的数据都导出为CSV文件并压缩

《Python实现将MySQL中所有表的数据都导出为CSV文件并压缩》这篇文章主要为大家详细介绍了如何使用Python将MySQL数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到... python将mysql数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到另一个

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件