WPF DragDrop事件元素跟随
前一段时间项目里面要实现一个鼠标拖动一个元素到另外一个元素上面并且赋值的功能,由于要在surface上运行,拖动的时候手指会挡住系统默认的拖动图标,导致用户意识不到自己是不是在拖动着东西,所以要解决这个问题。
初始想法
一开始在的设想是,拖动开始时新建一个元素要拖动的元素,然后设置次元素跟随鼠标移动,这里遇到个问题就是,当使用DoDragDrop事件的时候,捕捉不到鼠标的坐标变动,以至于无法让新建的元素跟随移动。要实现功能必须放弃DoDragDrop事件,但是当时很多已经写好的功能都是围绕这个事件的,不想再改,于是开始探索新的方式,虽然一开始浪费了一点时间,但是好处也不是没有,比如发现了GiveFeedback事件,于是就想到了第二种方案。
由于本来就是没有实现的方法,所以在此就不上代码了。
第二种方案
ButtonDown触发的时候,给元素添加MouseMove事件,当MouseMove触发的时候,获取到当前元素并生成图像转换为Cursor格式,在GiveFeedback中用以改变鼠标样式,添加GiveFeedback事件并启动DoDrapDrop。
public void ViewElemenMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var viewElement = sender as ViewElement;
if (viewElemen == null) return;
viewElemen.MouseMove += ViewElemenOnPreviewMouseMove;
} private void PatientTitleOnPreviewMouseMove(object sender, MouseEventArgs mouseEventArgs)
{
var viewElement = sender as ViewElement;
if (viewElement == null) return;
HoloCursor = FormUtility.CreateCursor(viewElement);
viewElemen.RockStart();
viewElemen.GiveFeedback += DragSource_GiveFeedback;
DragDrop.DoDragDrop(viewElemen, Model, DragDropEffects.Copy);
viewElemen.MouseMove -= ViewElemenOnPreviewMouseMove;
viewElemen.GiveFeedback -= DragSource_GiveFeedback;
Mouse.SetCursor(Cursors.Arrow);
} void DragSource_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
var viewElement = sender as ViewElement;
if (viewElemen == null) return;
Mouse.SetCursor(HoloCursor);
e.UseDefaultCursors = false;
e.Handled = true;
}
之所以把这么麻烦是因为,鼠标点击事件还要有其他的业务操作,所以只能加在mousemove里面。
根据元素生成鼠标 FormUtility.CreateCursor:
public static Cursor CreateCursor(UIElement element)
{
element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
element.Arrange(new Rect(new Point(), element.DesiredSize)); var rtb =
new RenderTargetBitmap(
(int)element.DesiredSize.Width,
(int)element.DesiredSize.Height,
96, 96, PixelFormats.Pbgra32); rtb.Render(element); var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtb)); using (var ms = new MemoryStream())
{
encoder.Save(ms);
using (var bmp = new System.Drawing.Bitmap(ms))
{
return InternalCreateCursor(bmp);
}
}
}
private static Cursor InternalCreateCursor(System.Drawing.Bitmap bmp)
{
var iconInfo = new NativeMethods.IconInfo();
NativeMethods.GetIconInfo(bmp.GetHicon(), ref iconInfo); iconInfo.xHotspot = 125;
iconInfo.yHotspot = 65;
iconInfo.fIcon = false; SafeIconHandle cursorHandle = NativeMethods.CreateIconIndirect(ref iconInfo);
return CursorInteropHelper.Create(cursorHandle);
}
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
private class SafeIconHandle : SafeHandleZeroOrMinusOneIsInvalid
{
public SafeIconHandle()
: base(true)
{
} override protected bool ReleaseHandle()
{
return NativeMethods.DestroyIcon(handle);
}
}
private static class NativeMethods
{
public struct IconInfo
{
public bool fIcon;
public int xHotspot;
public int yHotspot;
public IntPtr hbmMask;
public IntPtr hbmColor;
} [DllImport("user32.dll")]
public static extern SafeIconHandle CreateIconIndirect(ref IconInfo icon); [DllImport("user32.dll")]
public static extern bool DestroyIcon(IntPtr hIcon); [DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);
}
RockStart是一个元素效果,即开始拖动的时候,该元素会左右摇晃,让用户更清楚的知道,自己拖动的是哪个元素。
private Storyboard _sb = new Storyboard(){ FillBehavior = FillBehavior.Stop };
public ViewElement()
{
InitializeComponent();
_sb.AutoReverse = true;
var dbAscending1 = new DoubleAnimation(0, 3, new Duration(TimeSpan.FromMilliseconds(100)));
_sb.Children.Add(dbAscending1);
Storyboard.SetTarget(dbAscending1, Border);
Storyboard.SetTargetProperty(dbAscending1, new PropertyPath("(Rectangle.RenderTransform).(RotateTransform.Angle)"));
var dbAscending2 = new DoubleAnimation(3, -3, new Duration(TimeSpan.FromMilliseconds(200)));
_sb.Children.Add(dbAscending2);
Storyboard.SetTarget(dbAscending2, Border);
Storyboard.SetTargetProperty(dbAscending2, new PropertyPath("(Rectangle.RenderTransform).(RotateTransform.Angle)"));
}
public void RockStart()
{
Dispatcher.InvokeAsync(() => _sb.Begin(), DispatcherPriority.Background);
}
至此,功能完成。
WPF DragDrop事件元素跟随的更多相关文章
- WPF 在事件中绑定命令(不可以在模版中绑定命令)
其实这也不属于MVVMLight系列中的东东了,没兴趣的朋友可以跳过这篇文章,本文主要介绍如何在WPF中实现将命令绑定到事件中. 上一篇中我们介绍了MVVMLight中的命令的用法,那么仅仅知道命令是 ...
- WPF自学入门(三)WPF路由事件之内置路由事件
有没有想过在.NET中已经有了事件机制,为什么在WPF中不直接使用.NET事件要加入路由事件来取代事件呢?最直观的原因就是典型的WPF应用程序使用很多元素关联和组合起来,是否还记得在WPF自学入门(一 ...
- WPF路由事件二:路由事件的三种策略
一.什么是路由事件 路由事件是一种可以针对元素树中的多个侦听器而不是仅仅针对引发该事件的对象调用处理程序的事件.路由事件是一个CLR事件. 路由事件与一般事件的区别在于:路由事件是一种用于元素树的事件 ...
- WPF 在事件中绑定命令
导航:MVVMLight系列文章目录:<关于 MVVMLight 设计模式系列> 其实这也不属于MVVMLight系列中的东东了,没兴趣的朋友可以跳过这篇文章,本文主要介绍如何在WPF中实 ...
- js进阶 12-3 如何实现元素跟随鼠标移动
js进阶 12-3 如何实现元素跟随鼠标移动 一.总结 一句话总结:获取鼠标位置,将鼠标位置设置为元素偏移即可. 1.用什么事件获取鼠标位置? 用mousemove可以获取鼠标移动的时候的位置 $(d ...
- WPF 路由事件 Event Routing
原文:WPF 路由事件 Event Routing 1.路由事件介绍 之前介绍了WPF的新的依赖属性系统,本篇将介绍更高级的路由事件,替换了之前的.net普通事件.相比.net的事件,路由事件具有更强 ...
- Win7/Win8/Win8.1/Win10下的DragEnter DragDrop事件不触发
Win7/Win8/Win8.1/Win10下的DragDrop事件不触发 2011-02-02 来自:博客园 字体大小:[大 中 小] 摘要:你的应用程序需要从windows资源管理器拖动文件到 ...
- Win7下的DragEnter、DragDrop事件不触发的解决方案
Win7与原来的XP和Win2003相比,安全控制方面更严格.比如,当我们以administrator登陆XP或Win2003时,运行所有的程序即是以管理员的身份启动的.但当以administrato ...
- javascript元素跟随鼠标在指定区域运动
元素跟随鼠标在指定区域运动通常是用在商城图片的放大镜中,下面是完整的Demo: <!DOCTYPE html> <html lang="en"> <h ...
随机推荐
- LoadRunner界面分析(一)
1.Virtual User Generator 2.新建脚本的方式 3.Task模式 4.Recording Options选项 5.Run-Time setting选项
- vb 随机获取6个1-33的数
Private Sub random(ByVal num As Integer, ByVal min As Integer, ByVal max As Integer) Dim i As Intege ...
- OSGI.NET 学习笔记--应用篇
关于osgi.net ,想必大家也听说过,以下是自己在学习osgi.net 过程中整理出来的内容,供大家学习参与使用. 1. OSGI.NET 与UIOSP OSGi是Open Service Ga ...
- python其中一个子线程,则退出全部线程,再退出进程
import threading, signal is_exit = False def write_login(self): global is_exit write_log('login rsyn ...
- [前端 3]纯Js制作俄罗斯方块游戏
导读:在别人文章里看到了,然后写了一遍.结果出错了,然后调出来了,然后理解了一下,加了点注释,有一些想法.忘了在 哪一篇上面看的了,就贴不出来链接地址.原谅.呃,真没自己的东西,权当练打字了吧.其实, ...
- Duilib学习笔记《06》— 窗体基类WindowImpBase
在前面的例子中我们发现,窗口都是继承CWindowWnd.INotifyUI,然后重载相关函数去实现.显然,我们发现窗口的创建流程实际上都是差不多的,主要只是在OnCreate加载的配置文件不同等等… ...
- 【IHttpHandler】HttpModule,HttpHandler,HttpHandlerFactory简单使用
这三个对象我们在开发Asp.net程序时经常会用到,似乎很熟悉,但有时候又不太确定.本文通过一个简单的例子来直观的比较一下这三个对象的使用. HttpModule:Http模块,可以在页面处理前后.应 ...
- Oracle 查询字段在什么表
-- 查询字段在什么表 select * from all_tab_cols t where t.column_name='ABC'; -- 查询字段在什么表并且 判断是否是主键 select * f ...
- SQL笔记-第一章,数据库入门
DBMS的分类DB2.Oracle.Microsoft SQL Server.Sybase SQLServer.Informix.MySQL数据库的结构元素库 database表 table列 col ...
- 2_2数据类型与C#部分语法[wp8特色开发与编程技巧]
2_2数据类型 -5min 类型介绍 在上个视频中我们构建了我们第一个应用.这一次我们要来了解下c#的数据类型 众所周知,在我们已认知的世界里,我们把文字分为数字与字符.在程序的世界里面我们把数据分为 ...