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

相关文章

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. 文件

Java捕获ThreadPoolExecutor内部线程异常的四种方法

《Java捕获ThreadPoolExecutor内部线程异常的四种方法》这篇文章主要为大家详细介绍了Java捕获ThreadPoolExecutor内部线程异常的四种方法,文中的示例代码讲解详细,感... 目录方案 1方案 2方案 3方案 4结论方案 1使用 execute + try-catch 记录

基于Canvas的Html5多时区动态时钟实战代码

《基于Canvas的Html5多时区动态时钟实战代码》:本文主要介绍了如何使用Canvas在HTML5上实现一个多时区动态时钟的web展示,通过Canvas的API,可以绘制出6个不同城市的时钟,并且这些时钟可以动态转动,每个时钟上都会标注出对应的24小时制时间,详细内容请阅读本文,希望能对你有所帮助...

CSS模拟 html 的 title 属性(鼠标悬浮显示提示文字效果)

《CSS模拟html的title属性(鼠标悬浮显示提示文字效果)》:本文主要介绍了如何使用CSS模拟HTML的title属性,通过鼠标悬浮显示提示文字效果,通过设置`.tipBox`和`.tipBox.tipContent`的样式,实现了提示内容的隐藏和显示,详细内容请阅读本文,希望能对你有所帮助... 效

spring @EventListener 事件与监听的示例详解

《spring@EventListener事件与监听的示例详解》本文介绍了自定义Spring事件和监听器的方法,包括如何发布事件、监听事件以及如何处理异步事件,通过示例代码和日志,展示了事件的顺序... 目录1、自定义Application Event2、自定义监听3、测试4、源代码5、其他5.1 顺序执行