C#基础系列:开发自己的窗体设计器(实现控件的拖动)

 

控件移动的关键点就是需要设计一个独立于任何控件的类(UIMoveKnob)来控制控件的移动。我这里实现的方法只针对一个控件,如果需要同时选择多个控件,然后同时移动的话,你需要修改这个类,这里是有点难于控制,我使用的方法严重耦合,所以只在这里给出移动一个控件的办法,具体移动过个控件的方法请各位讨论。

 

要移动某个选定的控件,我们需要实现控件的:

MouseDown

MouseMove

MouseUp

3个事件。

MouseDown的时候,记录鼠标点击的开始位置,并设置开始移动标志为True

MouseMove的时候,把控件移动相应的距离(当前鼠标位置 鼠标点击的开始位置);

MouseUp的时候,释放移动标志为false

 

有了控件移动控制类(UIMoveKnob)以后,我们怎么实现UIMoveKnob和具体控件的关联呢?同样,我们需要在Form中增加一个变量private Hashtable _HashUIMoveKnob用于缓存每个控件对应的UIMoveKnob对象。

 

同时在Form.ControlAdded事件中,通过this._HashUIMoveKnob.Add(e.Control, new UIMoveKnob(e.Control));设置其关联性。

 

UIMoveKnob的代码如下:

  1. public class UIMoveKnob
  2. {
  3.     private System.Windows.Forms.Control _Owner;
  4.     private int _MouseClickAtX;
  5.     private int _MouseClickAtY;
  6.     private bool _BeginDrag;
  7.     public UIMoveKnob(System.Windows.Forms.Control Owner)
  8.     {
  9.         this._Owner = Owner;
  10.         this._Owner.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Owner_MouseDown);
  11.         this._Owner.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Owner_MouseMove);
  12.         this._Owner.MouseUp += new System.Windows.Forms.MouseEventHandler(this.Owner_MouseUp);
  13.     }
  14.     void Owner_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
  15.     {
  16.         this._Owner.Cursor = System.Windows.Forms.Cursors.Default;
  17.         this._MouseClickAtX = e.X;
  18.         this._MouseClickAtY = e.Y;
  19.         this._BeginDrag = true;
  20.     }
  21.     void Owner_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
  22.     {
  23.         try
  24.         {
  25.             if (this._BeginDrag)
  26.             {
  27.                 Rectangle rect;
  28.                 /*
  29.                  * 对于下列控件,是不能拖动的,所以这里也不绘制拖动边框
  30.                  * TabPage,
  31.                  */
  32.                 if (this._Owner is System.Windows.Forms.TabPage)
  33.                 {
  34.                     //
  35.                 }
  36.                 else
  37.                 {
  38.                     this._Owner.Location = new Point(this._Owner.Left + e.X - this._MouseClickAtX, this._Owner.Top + e.Y - this._MouseClickAtY);
  39.                 }
  40.             }
  41.         }
  42.         catch { }
  43.     }
  44.     void Owner_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
  45.     {
  46.         this._BeginDrag = false;
  47.         this._Owner.Parent.Refresh();
  48.     }
  49. }

修改后的Form代码前半部分如下:

  1. private MouseHook _MouseHook;
  2. //我们将所有的已经与具体控件关联了的UISizeKnob缓存在这个HashTable中
  3. private Hashtable _HashUISizeKnob;
  4. //负责控件移动的类
  5. private Hashtable _HashUIMoveKnob;
  6. public Form1()
  7. {
  8.     InitializeComponent();
  9.     this._MouseHook = new MouseHook(this);
  10.     this._HashUISizeKnob = new Hashtable();
  11.     this._HashUIMoveKnob = new Hashtable();
  12.     //为了简洁明了,我们在ControlAdded中来设置具体控件和UISizeKnob的关联
  13.     this.ControlAdded += new ControlEventHandler(Form1_ControlAdded);
  14. }
  15. void Form1_ControlAdded(object sender, ControlEventArgs e)
  16. {
  17.     if (!(e.Control is UISizeDot))
  18.     {
  19.         this._HashUISizeKnob.Add(e.Control, new UISizeKnob(e.Control));
  20.         this._HashUIMoveKnob.Add(e.Control, new UIMoveKnob(e.Control));
  21.         
  22.         //点击控件的时候,显示控件的选择
  23.         e.Control.Click += new EventHandler(Control_Click);
  24.     }
  25. }
  26. void Control_Click(object sender, EventArgs e)
  27. {
  28.     //寿险清除已经选择的控件
  29.     foreach (UISizeKnob knob in this._HashUISizeKnob.Values)
  30.     {
  31.         knob.ShowUISizeDots(false);
  32.     }
  33.     try 
  34.     {
  35.         ((UISizeKnob)this._HashUISizeKnob[sender]).ShowUISizeDots(true);
  36.     }
  37.     catch { }
  38. }

相对来说实现单个控件的拖动比较简单,而实现多个控件的拖动,我们需要首先使用一个全局的变量来缓存我们所选择的控件,然后在此类中。拖动的时候,通过遍历此全局变量,一个个改变所选择控件的位置。

 

相关文章:

C#基础系列:开发自己的窗体设计器(总纲)

C#基础系列:开发自己的窗体设计器(在容器上拖动鼠标增加控件)

C#基础系列:开发自己的窗体设计器(实现控件的选择)

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
实现C#的任意位置拖动效果,可以通过以下步骤进行: 1. 在上添加一个Panel件,并将其Dock属性设置为Top。这个Panel件将作为的标题栏。 2. 在Panel件上添加一个Label或者其他件,用来显示的标题。 3. 在Panel件的MouseDown事件中,获取鼠标当前的位置,并将的Location属性设置为这个位置。同时设置一个变量记录鼠标按下时的位置。 4. 在Panel件的MouseMove事件中,如果鼠标左键被按下,计算鼠标当前位置和按下时位置的偏移量,然后将的Location属性加上这个偏移量。 下面是示例代码: ``` public partial class Form1 : Form { private Point mouseOffset; public Form1() { InitializeComponent(); } private void panelTitle_MouseDown(object sender, MouseEventArgs e) { mouseOffset = new Point(-e.X, -e.Y); this.Cursor = Cursors.SizeAll; } private void panelTitle_MouseMove(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { Point mousePos = Control.MousePosition; mousePos.Offset(mouseOffset.X, mouseOffset.Y); this.Location = mousePos; } } private void panelTitle_MouseUp(object sender, MouseEventArgs e) { this.Cursor = Cursors.Default; } } ``` 在上述代码中,panelTitle是我们添加的Panel件,用来作为的标题栏。在MouseDown事件中,我们记录鼠标按下时的位置,并将鼠标的光标设置为SizeAll,以便用户知道可以被拖动。在MouseMove事件中,如果鼠标左键被按下,我们计算鼠标当前位置和按下时位置的偏移量,并将的Location属性设置为鼠标当前位置加上偏移量。在MouseUp事件中,我们将光标设置回默认状态。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值