c#ovalshape_【原创】C# 实现拖拉控件改变位置与大小(SamWang)(附源代码下载)

前言:

很多时候我们需要在运行时,动态地改变控件的位置以及大小,以获得更好的布局。比如说实际项目中的可自定义的报表、可自定义的单据等诸如此类。它们有个特点就是允许客户或者二次开发人员设计它们需要的界面设置功能。

本人以前也做过可自定义系统,包括界面和功能,主要为了减少开发人员的工作量以及程序的灵活性和健壮性。

本篇主要讨论下,在运行时如何实现拖拉控件,达到改变控件位置与大小。功能将模拟VS设计界面时的拖拉功能。

(本篇暂不涉及多控件同时操作)

一、技术概述

其实实现运行时控件的拖拉并不难,主要是改变控件的Location与Size即可。动态调整时再捕获MouseDown、MouseMove及MouseUp事件来实时修改上述两个属性就可以实现。

二、功能规划

在此之前,我们先来看下.net设计界面,一旦选中某个控件时,将会出现如下图的边框:

7741043ea606b4aafaad89a3f4cb47f3.png

之后就可以通过拖拉出现的边框改变其大小。而改变控件的位置,实际上是当鼠标点击在控件内部拖动时实现的。

所有本例也将功能分为两个部分实现,分别为控件内部拖动改变位置与控件边框拖拉改变大小。

三、具体实现

1.拖动控件改变位置

首先,新建一个项目,然后添加一个类,取名叫MoveControl,该类用来给控件挂载事件实现拖动。

接着在该类中添加字段currentControl,用来保存需要操作的控件,即通过构造函数传递的控件。

接着创建一方法--AddEvents,用来给当前的控件挂载事件。

代码如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngDragControl

1 usingSystem;2 usingSystem.Collections.Generic;3 usingSystem.Text;4 usingSystem.Windows.Forms;5 usingSystem.Drawing;6

7 namespaceDragControl8 {9 public classMoveControl10 {11 #region Constructors

12 publicMoveControl(Control ctrl)13 {14 currentControl =ctrl;15 AddEvents();16 }17 #endregion

18

19 #region Fields

20 private Control currentControl; //传入的控件

21 #endregion

22

23 #region Properties

24

25 #endregion

26

27 #region Methods

28 ///

29 ///挂载事件30 ///

31 private voidAddEvents()32 {33 currentControl.MouseClick += newMouseEventHandler(MouseClick);34 currentControl.MouseDown += newMouseEventHandler(MouseDown);35 currentControl.MouseMove += newMouseEventHandler(MouseMove);36 currentControl.MouseUp += newMouseEventHandler(MouseUp);37 }38 #endregion

39

40 #region Events

41 ///

42 ///鼠标单击事件:用来显示边框43 ///

44 ///

45 ///

46 void MouseClick(objectsender, MouseEventArgs e)47 {48 }49

50 ///

51 ///鼠标按下事件:记录当前鼠标相对窗体的坐标52 ///

53 void MouseDown(objectsender, MouseEventArgs e)54 {55

56 }57

58 ///

59 ///鼠标移动事件:让控件跟着鼠标移动60 ///

61 void MouseMove(objectsender, MouseEventArgs e)62 {63 }64

65 ///

66 ///鼠标弹起事件:让自定义的边框出现67 ///

68 void MouseUp(objectsender, MouseEventArgs e)69 {70 }71 #endregion

72 }73 }

接着我们需要实现MouseDown、MouseMove、MouseUp三个事件。

不过在此之前,我们必须要弄清楚,移动即表示坐标的改变,所以必定要有个起始坐标和终点坐标。

所以我们在MoveControl类中加入两个字段。

private Point pPoint; //上个鼠标坐标

private Point cPoint; //当前鼠标坐标

而且在开始拖动之前,我们肯定需要先单击一次控件。在MouseDown时获取当前光标的位置,保存到pPoint中。

(此处用Cursor获得坐标的好处,就是忽略掉容器的麻烦问题)

1 ///

2 ///鼠标单击事件:用来显示边框3 ///

4 void MouseClick(objectsender, MouseEventArgs e)5 {6 pPoint =Cursor.Position;7 }

接着便实现MouseMove的事件,当鼠标左键按下时,接着移动鼠标后,继续鼠标移动后的坐标,然后与MouseDown时记下的坐标相减,就得到鼠标的位移值,接着控件的Location加上该位移值即可,然后更新pPoint。

1 ///

2 ///鼠标移动事件:让控件跟着鼠标移动3 ///

4 void MouseMove(objectsender, MouseEventArgs e)5 {6 Cursor.Current = Cursors.SizeAll; //当鼠标处于控件内部时,显示光标样式为SizeAll7 //当鼠标左键按下时才触发

8 if (e.Button ==MouseButtons.Left)9 {10 cPoint = Cursor.Position; //获得当前鼠标位置

11 int x = cPoint.X -pPoint.X;12 int y = cPoint.Y -pPoint.Y;13 currentControl.Location = new Point(currentControl.Location.X + x, currentControl.Location.Y +y);14 pPoint =cPoint;15 }16 }

由于此时还没涉及到边框,所以MouseUp暂时不用处理。至此拖动的基本功能已经实现!

目前MoveControl的完整代码如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngMoveControl

1 usingSystem;2 usingSystem.Collections.Generic;3 usingSystem.Text;4 usingSystem.Windows.Forms;5 usingSystem.Drawing;6

7 namespaceDragControl8 {9 public classMoveControl10 {11 #region Constructors

12 publicMoveControl(Control ctrl)13 {14 currentControl =ctrl;15 AddEvents();16 }17 #endregion

18

19 #region Fields

20 private Control currentControl; //传入的控件

21 private Point pPoint; //上个鼠标坐标

22 private Point cPoint; //当前鼠标坐标

23 #endregion

24

25 #region Properties

26

27 #endregion

28

29 #region Methods

30 ///

31 ///挂载事件32 ///

33 private voidAddEvents()34 {35 currentControl.MouseDown += newMouseEventHandler(MouseDown);36 currentControl.MouseMove += newMouseEventHandler(MouseMove);37 currentControl.MouseUp += newMouseEventHandler(MouseUp);38 }39

40 ///

41 ///绘制拖拉时的黑色边框42 ///

43 public static voidDrawDragBound(Control ctrl)44 {45 ctrl.Refresh();46 Graphics g =ctrl.CreateGraphics();47 int width =ctrl.Width;48 int height =ctrl.Height;49 Point[] ps = new Point[5]{new Point(0,0),new Point(width -1,0),50 new Point(width -1,height -1),new Point(0,height-1),new Point(0,0)};51 g.DrawLines(newPen(Color.Black), ps);52 }53 #endregion

54

55 #region Events

56 ///

57 ///鼠标按下事件:记录当前鼠标相对窗体的坐标58 ///

59 void MouseDown(objectsender, MouseEventArgs e)60 {61 pPoint =Cursor.Position;62 }63

64 ///

65 ///鼠标移动事件:让控件跟着鼠标移动66 ///

67 void MouseMove(objectsender, MouseEventArgs e)68 {69 Cursor.Current = Cursors.SizeAll; //当鼠标处于控件内部时,显示光标样式为SizeAll70 //当鼠标左键按下时才触发

71 if (e.Button ==MouseButtons.Left)72 {73 MoveControl.DrawDragBound(this.currentControl);74 cPoint = Cursor.Position; //获得当前鼠标位置

75 int x = cPoint.X -pPoint.X;76 int y = cPoint.Y -pPoint.Y;77 currentControl.Location = new Point(currentControl.Location.X + x, currentControl.Location.Y +y);78 pPoint =cPoint;79 }80 }81

82 ///

83 ///鼠标弹起事件:让自定义的边框出现84 ///

85 void MouseUp(objectsender, MouseEventArgs e)86 {87 this.currentControl.Refresh();88 }89 #endregion

90 }91 }

下面我们来测试下拖动的功能。

创建一个Form窗体,可以再界面上添加你要测试的控件类型,此处我只用TextBox左下测试。在Load的中添加以下代码,将Form中的所有控件挂载上拖拉功能。

1 private void Form1_Load(objectsender, EventArgs e)2 {3 foreach (Control ctrl in this.Controls)4 {5 newMoveControl(ctrl);6 }7 }

此时,有心人可能会发现VS中拖动控件时,将会出现黑色边框,而处于没有。

这也很简单,我们在MouseMove时加上如下代码即可。

1 ///

2 ///绘制拖拉时的黑色边框3 ///

4 public static voidDrawDragBound(Control ctrl)5 {6 ctrl.Refresh();7 Graphics g =ctrl.CreateGraphics();8 int width =ctrl.Width;9 int height =ctrl.Height;10 Point[] ps = new Point[5]{new Point(0,0),new Point(width -1,0),11 new Point(width -1,height -1),new Point(0,height-1),new Point(0,0)};12 g.DrawLines(newPen(Color.Black), ps);13 }14

15

16 ///

17 ///鼠标移动事件:让控件跟着鼠标移动18 ///

19 void MouseMove(objectsender, MouseEventArgs e)20 {21 Cursor.Current = Cursors.SizeAll; //当鼠标处于控件内部时,显示光标样式为SizeAll22 //当鼠标左键按下时才触发

23 if (e.Button ==MouseButtons.Left)24 {25 MoveControl.DrawDragBound(this.currentControl);26 cPoint = Cursor.Position; //获得当前鼠标位置

27 int x = cPoint.X -pPoint.X;28 int y = cPoint.Y -pPoint.Y;29 currentControl.Location = new Point(currentControl.Location.X + x, currentControl.Location.Y +y);30 pPoint =cPoint;31 }32 }

同时要在MoveUp的时候,刷新一下自己,让黑色边框消失掉!

1 ///

2 ///鼠标弹起事件:让自定义的边框出现3 ///

4 void MouseUp(objectsender, MouseEventArgs e)5 {6 this.currentControl.Refresh();7 }

接着用没有边框的控件测试下就会很明显。如下图所示:

cc77c0b5d7062e8587ec261368fb8afb.png

2.通过边框拖拉控件改变大小

此处的主要思路为:点击控件的时候,创建一个自定义的用户控件,该用户控件响应区域就是传入控件的边框区域,同时给它画上虚线与8个小圆圈。

第一、创建用户控件--FrameControl(边框控件),然后增加一个字段用来保存传入的控件,还有加载事件,此处类同前面的MoveControl。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.pngFrameControl

1 usingSystem;2 usingSystem.Collections.Generic;3 usi

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值