游戏中有各种各样的拖拽需求,大到窗口,小到图标,在游戏界面操作中,点击和拖拽占据了用户操作的大部分行为,如何做好一个拖拽控件至关重要,做一个可重用的拖拽控件更加重要,我的这些实现方法可能比较另类,但只要有效就行,在这个基础上,你可以扩展很多的做法。

可能有朋友已经写了这方面的文章,但是本篇介绍的方法是一个可以一劳永逸的重用控件,只需要一个基类代码就可以完成所有的需求——图标、窗体、自定义的目标,所以,本片没有放在小技巧里而是游戏开发分类里。

最先,需要了解一下拖拽原理,即当鼠标按下做一个标识,在鼠标移动时实时修改目标坐标信息,鼠标抬起的时候,释放掉鼠标操作,当然了,为了更好的操作坐标,我们一般将父容器改成Canvas。

将围绕这个做后面的工作,请了解之前有关基类和容器的概念,这样后面看起来就容易很多,考虑它的重用性,创建一个基本控件让后面的控件继承,将一些通用逻辑写在这个基类里,让其他的类去继承重用,这也就是游戏引擎的基本做法之一。

那么,在Blend或者Visual Studio里创建一个名为MovableObject的控件,然后将控件xaml修改成下面的样子:

  1. <UserControl
  2. 02 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. 03 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. 04 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5. 05 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6. 06 mc:Ignorable="d"
  7. 07 x:Class="DragObject.MovableObject"
  8. 08 d:DesignWidth="640" d:DesignHeight="480" Width="Auto" Height="Auto">
  9. 09 <Grid x:Name="LayoutRoot">
  10. 10 <Rectangle Stroke="Black" RadiusX="5" RadiusY="5">
  11. 11 <Rectangle.Fill>
  12. 12 <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
  13. 13 <GradientStop Color="Transparent"/>
  14. 14 <GradientStop Color="Black" Offset="1"/>
  15. 15 </LinearGradientBrush>
  16. 16 </Rectangle.Fill>
  17. 17 </Rectangle>
  18. 18 <Image x:Name="ShowImage" Stretch="Fill"/>
  19. 19 <Rectangle x:Name="Sel_Rectangle" Stroke="White" StrokeThickness="2" Visibility="Collapsed" RadiusX="5" RadiusY="5"/>
  20. 20 </Grid>
  21. 21 </UserControl>
即便使用代码实现并不难,但是为了方便理解,就直接使用XAML较为简便,浏览它的结构图就可以看到。

上面的表示方法分别是带了一个底,和一个要显示图像的Image,以及一个当鼠标移入时候需要表示选择标识。

那么下面就是Coding阶段,打开MovableObject类,代码设计如下:

  1. public partial class MovableObject : UserControl
  2. 02 {
  3. 03 //鼠标点的保存,同时还承担是否点击的判定
  4. 04 Point ? mousePoint = null;
  5. 05 public MovableObject()
  6. 06 {
  7. 07 InitializeComponent();
  8. 08 //选择框隐蔽掉
  9. 09 Sel_Rectangle.Visibility = System.Windows.Visibility.Collapsed;
  10. 10 }
  11. 11 //鼠标移动的方法重载
  12. 12 protected override void OnMouseMove(MouseEventArgs e)
  13. 13 {
  14. 14 //判定是否按下鼠标左键
  15. 15 if (mousePoint!=null)
  16. 16 {
  17. 17 //计算新的位置
  18. 18 double newTop = e.GetPosition(null).Y - mousePoint.Value.Y + Canvas.GetTop(this);
  19. 19 double newLeft = e.GetPosition(null).X - mousePoint.Value.X + Canvas.GetLeft(this);
  20. 20 Canvas.SetTop(this, newTop);
  21. 21 Canvas.SetLeft(this, newLeft);
  22. 22 mousePoint = e.GetPosition(null);
  23. 23 }
  24. 24 base.OnMouseMove(e);
  25. 25 }
  26. 26 //鼠标抬起的方法重载
  27. 27 protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
  28. 28 {
  29. 29 mousePoint = null;
  30. 30 //释放鼠标设备
  31. 31 this.ReleaseMouseCapture();
  32. 32 base.OnMouseLeftButtonDown(e);
  33. 33 }
  34. 34 //鼠标按下的方法重载
  35. 35 protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
  36. 36 {
  37. 37 mousePoint = e.GetPosition(null);
  38. 38 //捕获鼠标设备
  39. 39 this.CaptureMouse();
  40. 40 //下面三行是用来保证当前控件为最顶层的做法
  41. 41 var parent = this.Parent as Panel;
  42. 42 parent.Children.Remove(this);
  43. 43 parent.Children.Add(this);
  44. 44 base.OnMouseLeftButtonUp(e);
  45. 45 }
  46. 46 //鼠标进入的方法重载
  47. 47 protected override void OnMouseEnter(MouseEventArgs e)
  48. 48 {
  49. 49 Sel_Rectangle.Visibility = System.Windows.Visibility.Visible;
  50. 50 base.OnMouseEnter(e);
  51. 51 }
  52. 52 //鼠标移出的方法重载
  53. 53 protected override void OnMouseLeave(MouseEventArgs e)
  54. 54 {
  55. 55 Sel_Rectangle.Visibility = System.Windows.Visibility.Collapsed;
  56. 56 base.OnMouseLeave(e);
  57. 57 }
  58. 58 }
我做了一些注释,可以很明确的得知这个基类的作用,现在可以新建类继承于这个类,来实现扩展的目的。

为此,我准备三种不同的目标效果——图标(MyIcon)、大图片(MyFace)、自定义控件(MyCard)

图标和图片只需要用上原有控件的Image即可,而自定义控件则是通过Blend或其他方式设计制作出来的独立控件,那么如何实现这三个效果呢?请往下看:

我们先创建三个类,他们都继承于MovableObject

public class MyIcon : MovableObject

public class MyFace : MovableObject

public class MyCard : MovableObject

下面在各自的构造函数中填入对应的操作逻辑即可,下面给出了完整代码:

  1. public class MyIcon : MovableObject
  2. 02 {
  3. 03 public MyIcon()
  4. 04 {
  5. 05 IconIndex = 1;
  6. 06 }
  7. 07 private int _Iconindex = -1;
  8. 08 public int IconIndex
  9. 09 {
  10. 10 get { return _Iconindex; }
  11. 11 set
  12. 12 {
  13. 13 _Iconindex = value;
  14. 14 var uri = new Uri("/DragObject;component/Res/image" + value + ".png", UriKind.Relative);
  15. 15 ShowImage.Source = new System.Windows.Media.Imaging.BitmapImage(uri);
  16. 16 }
  17. 17 }
  18. 18 }
  19. 19 public class MyFace : MovableObject
  20. 20 {
  21. 21 public MyFace()
  22. 22 {
  23. 23 var uri = new Uri("/DragObject;component/Res/nowpaper.jpg", UriKind.Relative);
  24. 24 ShowImage.Source = new System.Windows.Media.Imaging.BitmapImage(uri);
  25. 01 }
  26. 02 }
  27. 03 public class MyCard : MovableObject
  28. 04 {
  29. 05 public MyCard()
  30. 06 {
  31. 07 LayoutRoot.Children.Insert(LayoutRoot.Children.IndexOf(ShowImage), new Card());
  32. 08 LayoutRoot.Children.Remove(ShowImage);
  33. 09 }
  34. 10 }
MyFace是直接修改ShowImage的Source,MyIcon里写了一个索引属性,这样可以在外面控制ShowImage,显示需要显示的图片,而MyCard里new出来一个控件,并替换掉了原有的ShowImage,MyCard使用了前面制作的一个控件。

好了,现在在MainPage的构造函数中编写其他的代码,但是LayoutRoot需要变成Canvas,这样才能更好的控制图像位置。

  1. public MainPage()
  2. 02 {
  3. 03 InitializeComponent();
  4. 04 //添加自定义的拖拽目标
  5. 05 var icon = new MyIcon();
  6. 06 LayoutRoot.Children.Add(icon);
  7. 07 Canvas.SetLeft(icon, 20);
  8. 08 Canvas.SetTop(icon, 50);
  9. 09 icon = new MyIcon() { IconIndex = 3 };
  10. 10 LayoutRoot.Children.Add(icon);
  11. 11 Canvas.SetLeft(icon, 20);
  12. 12 Canvas.SetTop(icon, 150);
  13. 13 var face = new MyFace();
  14. 14 LayoutRoot.Children.Add(face);
  15. 15 Canvas.SetLeft(face, 100);
  16. 16 Canvas.SetTop(face, 50);
  17. 17 var card = new MyCard();
  18. 18 LayoutRoot.Children.Add(card);
  19. 19 Canvas.SetLeft(card, 270);
  20. 20 Canvas.SetTop(card, 50);
  21. 21 }
现在运行看看效果吧,在这个基础上,可以制作窗口或需要拖拽的物体只需要继承修改一下,在下一篇,将会制作一个窗口并使用技巧完成拖入等操作,放心吧绝对不复杂。

本篇工程源代码下载地址如下:点击直接下载

本文转自nowpaper 51CTO博客,原文链接:http://blog.51cto.com/nowpaper/712743

Silverlight 游戏开发:可重用的拖拽控件相关推荐

  1. Flutter拖拽控件Draggable

    Draggable 最近做了一个Flutter项目,其中有一个需求是做出三个可以互相拖拽的任务列表,平时在做Android项目时,拖动的控件基本上都是自定义View来实现的,想看看在Fluter上大家 ...

  2. winform窗体自由拖拽控件

    源码地址:https://download.csdn.net/download/horseroll/10906640 以上链接是用积分下载的,如果没有积分,可以用以下链接付费下载:https://do ...

  3. .net中实现拖拽控件

    在.net中实现拖拽控件主要用到以下函数: MouseDown(object sender, MouseEventArgs e) MouseUp(object sender, MouseEventAr ...

  4. js 拖拽生成html,js拖拽插件 js 拖拽控件生成自定义表单 怎么实现

    想请教一个js的问题,拖拽控件 js 拖拽控件生成自定义表单 怎么实现 说说步骤吧 监听mousedown事件 - 获取鼠标点击元素,判断是否可拖拽 - 设置flag做标记 - 建一个tempDOM, ...

  5. vue拖拽控件生成界面代码_Blue HMI人机界面开发平台

          随着信息技术在军工.制造业等领域的不断普及和快速发展,各行业信息系统软件的研制正在由传统的重复.烟囱式开发模式向以系统顶层设计为指导,以标准化.组件化.集成化软件开发为重点的模式逐步转变. ...

  6. android 嵌套分组拖动_GitHub - Mosect/DragLayout: Android拖拽控件,支持上下左右滑动、折叠或者嵌套ListView、RecyclerView等...

    DragLayout Android拖拽布局,包括以下布局: DragLayout 基础布局类 FlowLayout 可折叠布局,继承DragLayout DragRefreshLayout 拖拽刷新 ...

  7. H5实现多图片预览上传,可点击可拖拽控件介绍

    在做图片上传时发现一个蛮好用的控件,支持多张图片同时上传,可以点击选择图片,也可以将图片拖拽到上传框直接上传,方便,好用,接口也简单,基本可以直接放到项目里使用. 先看看他的样式: 选择图片后: $( ...

  8. C# Winform平台下实现自由拖拽控件

    C#控件拖动 1.场景需求 有时候,我们在编写PC上位机软件的时候,不免需要将所定义的控件可以自由的拖拽到任意地方.为了实现此一需求,我尝试了很多种方法,比如使用Mouse_Leave,Mouse_D ...

  9. Java拖拽控件数据库_java实现鼠标拖放功能代码实例

    java实现鼠标拖放功能代码实例 利用鼠标的拖放来交换程序的数据,即所谓的鼠标拖放功能.鼠标的拖放功能在图形化系统中非常常用,Java 提供了java.awt.dnd 和java.awt.datatr ...

最新文章

  1. Leetcode 107.二叉树的层序遍历 II (每日一题 20210628 同类型题)
  2. JavaScript 类型的隐式转换
  3. Redis基本数据类型、应用场景、操作指令
  4. cgroup代码浅析(1)
  5. 利用WhiteHose一步步建立分布式系统的框架(七)--添加组件的操作并实现分布式系统...
  6. VS2017:无法安装Win10SDK_10.0.15063.UWP.Native、无法安装Microsoft.VisualC.Redist.12
  7. java 工作流框架_java工作流是什么?哪些工作流框架比较好?
  8. html改excel,怎么把html文件转成excel:html表格如何转换excel
  9. 《区块链+》读书感想
  10. 蜘蛛:请求头、响应头、响应码
  11. linux can远程帧,【值得收藏】详解Linux的CAN接口编程技巧
  12. 【学习打卡 Free-Excel 】Task4 表合并
  13. speedoffice表格中如何隐藏网络线
  14. ant-design-vue 1.7.8版本使用报错
  15. oracle 结果集已耗尽_java.sql.SQLException: 结果集已耗尽,该怎么解决
  16. 汽车网络安全标准UN Regulation No.155和No.156汇总介绍
  17. 解决:win10一开机,内存占用过高,有的达到70%的办法
  18. Android6.0boot解锁,Lenovo手机fastboot命令 解锁Bootloade 教程
  19. OJ 1199 堆积木
  20. Android应用开发-小巫CSDN博客客户端之获取评论列表

热门文章

  1. php和python交互-python与php的比较
  2. python使用手册-Python参考手册(第4版)
  3. windows上报错:Could not find a version that satisfies the requirement torch==0.4.1
  4. Placements(连接)
  5. CheckBox的使用(一):onCheckedChanged事件
  6. Django的路由分发与名称空间
  7. 给Android Studio设置代码字体大小与界面字体样式
  8. js动态给当前点击元素添加css类
  9. 关于湖北工业大学图书馆联网配置的方法
  10. HDU 4279 占坑先。。。