通过设置光标形状实现拖拽控件时跟随一张透明图片的效果_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 通过设置光标形状实现拖拽控件时跟随一张透明图片的效果

通过设置光标形状实现拖拽控件时跟随一张透明图片的效果

 2013/7/21 20:40:20  山海  博客园  我要评论(0)
  • 摘要:以前做过一些winform的项目,实现标题描述的效果通常是在鼠标拖拽控件的时候,通常是在拖动过程中生成一个透明的form,把控件放进去,form的位置跟随鼠标一起改变。前几天和几位同事讨论winform的一些心得,正好又谈到这个,有同事提供了一种比较新颖的思路:就是生成一张透明的图片,设置成光标的形状。正好周末有时间试了一下。1usingSystem.Collections.Generic;2usingSystem.Drawing;3usingSystem.Windows.Forms
  • 标签:实现 图片 控件

以前做过一些winform的项目,实现标题描述的效果通常是在鼠标拖拽控件的时候,通常是在拖动过程中生成一个透明的form,把控件放进去,form的位置跟随鼠标一起改变。前几天和几位同事讨论winform的一些心得,正好又谈到这个,有同事提供了一种比较新颖的思路:就是生成一张透明的图片,设置成光标的形状。正好周末有时间试了一下。

class="code_img_closed" src="/Upload/Images/2013072120/0015B68B3C38AA5B.gif" alt="" />logs_code_hide('7fa70255-84ff-4024-9f50-783ed0258304',event)" src="/Upload/Images/2013072120/2B1B950FA3DF188F.gif" alt="" />
  1     using System.Collections.Generic;
  2     using System.Drawing;
  3     using System.Windows.Forms;
  4 
  5     delegate void DropCallBack<in Source, in Target>(Source source, Target target)
  6         where Source : Control
  7         where Target : Control;
  8 
  9     interface IDragDropController<in Source, in Target>
 10         where Source : Control
 11         where Target : Control
 12     {
 13         void EnableDragDrop();
 14         void DisableDragDrop();
 15     }
 16 
 17     sealed class DragDropController<Source, Target> : IDragDropController<Source, Target>
 18         where Source : Control
 19         where Target : Control
 20     {
 21         private IEnumerable<Source> sources;
 22         private IEnumerable<Target> targets;
 23         private bool isMovePrepared;
 24         private Bitmap cursorImage;
 25         private Cursor cursor;
 26         private Cursor defaultCursor;
 27         private DropCallBack<Source, Target> dropCallBack;
 28 
 29         public DragDropController(IEnumerable<Source> sources, IEnumerable<Target> targets, DropCallBack<Source, Target> dropCallBack)
 30         {
 31             this.sources = sources;
 32             this.targets = targets;
 33             this.dropCallBack = dropCallBack;
 34         }
 35 
 36         public void EnableDragDrop()
 37         {
 38             this.DisableDragDrop();
 39             foreach (var source in this.sources)
 40             {
 41                 source.MouseDown += this.OnSourceMouseDown;
 42                 source.MouseMove += this.OnSourceMouseMove;
 43                 source.MouseUp += this.OnSourceMouseUp;                
 44             }
 45         }
 46 
 47         public void DisableDragDrop()
 48         {
 49             foreach (var source in this.sources)
 50             {
 51                 source.MouseDown -= this.OnSourceMouseDown;
 52                 source.MouseMove -= this.OnSourceMouseMove;
 53                 source.MouseUp -= this.OnSourceMouseUp;
 54             }
 55         }
 56 
 57         private void OnSourceMouseDown(object sender, MouseEventArgs e)
 58         {
 59             if (e.Button == MouseButtons.Left)
 60             {
 61                 var source = sender as Source;
 62                 if (source != null)
 63                 {
 64                     source.Capture = true;
 65                     this.isMovePrepared = true;
 66                 }
 67             }
 68         }
 69 
 70         private void OnSourceMouseMove(object sender, MouseEventArgs e)
 71         {
 72             if (this.isMovePrepared)
 73             {
 74                 var source = sender as Source;
 75                 if (source == null)
 76                 {
 77                     return;
 78                 }
 79 
 80                 if (this.cursor == null)
 81                 {
 82                     this.defaultCursor = source.Cursor;
 83                     // Generate an image for cursor
 84                     int cursorWidth = source.Width >= 2 * e.X ? 2 * (source.Width - e.X) : 2 * e.X;
 85                     int cursorHeight = source.Height >= 2 * e.Y ? 2 * (source.Height - e.Y) : 2 * e.Y;
 86                     this.cursorImage = new Bitmap(cursorWidth, cursorHeight);
 87                     Rectangle bounds = new Rectangle(source.Width >= 2 * e.X ? cursorWidth - source.Width : 0, source.Height >= 2 * e.Y ? cursorHeight - source.Height : 0, source.Width, source.Height);
 88                     source.DrawToBitmap(cursorImage, bounds);
 89                     this.defaultCursor.Draw(Graphics.FromImage(this.cursorImage), new Rectangle(bounds.X + e.X, bounds.Y + e.Y, this.defaultCursor.Size.Width, this.defaultCursor.Size.Height));
 90                     this.ChangeAlpha(cursorImage, bounds);
 91                     this.cursor = new Cursor(this.cursorImage.GetHicon());
 92                     source.Cursor = this.cursor;
 93                 }
 94             }
 95         }
 96 
 97         private void OnSourceMouseUp(object sender, MouseEventArgs e)
 98         {
 99             if (this.isMovePrepared)
100             {
101                 var source = sender as Source;
102                 if (source == null)
103                 {
104                     return;
105                 }
106 
107                 if (this.cursor != null)
108                 {
109                     source.Cursor = defaultCursor;
110                     this.cursorImage.Dispose();
111                     this.cursorImage = null;
112                     this.cursor.Dispose();
113                     this.cursor = null;
114                 }
115 
116                 this.isMovePrepared = false;
117                 source.Capture = false;
118                 // find the target control where the source control is dropped by the mouse up location.
119                 Target target = null;
120                 var mouseLocation = source.PointToScreen(e.Location);
121                 foreach (var item in this.targets)
122                 {
123                     Point offset = item.PointToScreen(new Point(0, 0));
124                     Rectangle bounds = new Rectangle(offset, item.Size);
125                     if (bounds.Contains(mouseLocation))
126                     {
127                         target = item;
128                         break;
129                     }
130                 }
131 
132                 if (target != null && this.dropCallBack != null)
133                 {
134                     this.dropCallBack(source, target);
135                 }
136             }
137         }
138 
139         private void ChangeAlpha(Bitmap img, Rectangle bounds)
140         {
141             for (int x = bounds.Left; x < bounds.Right; x++)
142             {
143                 for (int y = bounds.Top; y < bounds.Bottom; y++)
144                 {
145                     Color orgColor = img.GetPixel(x, y);
146                     img.SetPixel(x, y, Color.FromArgb(150, orgColor.R, orgColor.G, orgColor.B));
147                 }
148             }
149         }
150     }
DragDropController

这个类可以实现将拖拽source到targets中任意一个控件过程中,鼠标跟随一张透明的source控件的图片。下面是使用该类的方法:

 1     public partial class Form1 : Form
 2     {
 3         private DragDropController<PictureBox, PictureBox> dragDropTest;
 4 
 5         public Form1()
 6         {
 7             InitializeComponent();
 8             this.dragDropTest = new DragDropController<PictureBox, PictureBox>(new List<PictureBox>() { this.pictureBox1, this.pictureBox2 }, new List<PictureBox>() { this.pictureBox3, this.pictureBox4 }, this.DropCallBack);
 9             this.dragDropTest.EnableDragDrop();
10         }
11 
12         private void DropCallBack(PictureBox source, PictureBox target)
13         {
14             target.Image = source.Image;
15         }
16     }
Demo

该方法实现从pictureBox1拖拽图片到pictureBox2或pictureBox3中的效果。

主要发现一个问题:在开始拖拽的时候,Cursor图片的生成比较复杂,性能似乎比较低,不知是否有优化之法。

发表评论
用户名: 匿名