Control 的DraggerHelper, 拖动控件从此变得很简单。。。

论坛 期权论坛 编程之家     
选择匿名的用户   2021-5-31 15:55   11   0

程序员经常要实现拖动控件的功能,一般实现这个功能,都要注册事件,然后写MouseMove的代码,

Point point = Point.Empty;

control.MouseDown += control_MouseDown;
control.MouseMove += control_MouseMove;
 control.MouseLeave += control_MouseLeave;

如果程序的很多地方都有这个逻辑的话,那么代码就会有一大部分的重复了。

在网上如果你搜索控件拖动的话,大部分代码都是上面的代码,重复的逻辑,重复的故事。

于是我想,能不能写一个帮助类,当需要拖动的时候,只要调用EnableDrag方法就行了,如下:

private void Form1_Load(object sender, EventArgs e)
{
    DraggerHelper.EnableDrag(button1);
    DraggerHelper.EnableDrag(label1);

    DraggerHelper.DisableDrag(button1);
    DraggerHelper.DisableDrag(label1);
}

要实现这个效果,需要一些小技巧,当然,这些已经封装进了DraggerHelper 类。

完整的代码如下:

完整的代码using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ControlDragger
{
    public static class DraggerHelper
    {
        private static DraggerHelperCore helperCore = new DraggerHelperCore();

        public static void EnableDrag(this Control control)
        {
            helperCore.EnableDrag(control);
        }

        public static bool IsControlCanDrag(this Control control)
        {
            return helperCore.IsControlCanDrag(control);
        }

        public static void DisableDrag(this Control control)
        {
            helperCore.DisableDrag(control);
        }
    }

    internal sealed class DraggerHelperCore
    {
        /// <summary>
        /// 光标状态
        /// </summary>
        private enum EnumMousePointPosition
        {
            MouseSizeNone = 0, //'无   
            MouseSizeRight = 1, //'拉伸右边框   
            MouseSizeLeft = 2, //'拉伸左边框   
            MouseSizeBottom = 3, //'拉伸下边框   
            MouseSizeTop = 4, //'拉伸上边框   
            MouseSizeTopLeft = 5, //'拉伸左上角   
            MouseSizeTopRight = 6, //'拉伸右上角   
            MouseSizeBottomLeft = 7, //'拉伸左下角   
            MouseSizeBottomRight = 8, //'拉伸右下角   
            MouseDrag = 9   // '鼠标拖动
        }

        private const int Band = 5;
        private const int MinWidth = 10;
        private const int MinHeight = 10;
        private EnumMousePointPosition m_MousePointPosition;

        internal class DragControlProperty
        {
            public Point PositionMovePoint { get; set; }

            public Point SizeChangeMovePoint { get; set; }
        }

        Dictionary<Control, DragControlProperty> controlPropertyDic = new Dictionary<Control, DragControlProperty>();

        public bool IsControlCanDrag(Control control)
        {
            return controlPropertyDic.ContainsKey(control);
        }

        public void EnableDrag(Control control)
        {
            if (!controlPropertyDic.ContainsKey(control))
            {
                controlPropertyDic.Add(control, new DragControlProperty() { });

                control.MouseDown += control_MouseDown;
                control.MouseMove += control_MouseMove;
                control.MouseLeave += control_MouseLeave;
            }
        }

        public void DisableDrag(Control control)
        {
            if (controlPropertyDic.ContainsKey(control))
            {
                controlPropertyDic.Remove(control);

                control.MouseDown -= control_MouseDown;
                control.MouseMove -= control_MouseMove;
                control.MouseLeave -= control_MouseLeave;
            }
        }

        void control_MouseLeave(object sender, EventArgs e)
        {
            m_MousePointPosition = EnumMousePointPosition.MouseSizeNone;
            Cursor.Current = Cursors.Arrow;
        }

        void control_MouseMove(object sender, MouseEventArgs e)
        {
            Control lCtrl = (sender as Control);
            DragControlProperty property = GetControlProperty(lCtrl);

            if (e.Button == MouseButtons.Left)
            {
                switch (m_MousePointPosition)
                {
                    case EnumMousePointPosition.MouseDrag:
                        lCtrl.Left = lCtrl.Left + e.X - property.PositionMovePoint.X;
                        lCtrl.Top = lCtrl.Top + e.Y - property.PositionMovePoint.Y;
                        break;
                    case EnumMousePointPosition.MouseSizeBottom:
                        lCtrl.Height = lCtrl.Height + e.Y - property.SizeChangeMovePoint.Y;
                        property.SizeChangeMovePoint = e.Location; //'记录光标拖动的当前点   
                        break;
                    case EnumMousePointPosition.MouseSizeBottomRight:
                        lCtrl.Width = lCtrl.Width + e.X - property.SizeChangeMovePoint.X;
                        lCtrl.Height = lCtrl.Height + e.Y - property.SizeChangeMovePoint.Y;
                        property.SizeChangeMovePoint = e.Location; //'记录光标拖动的当前点   
                        break;
                    case EnumMousePointPosition.MouseSizeRight:
                        lCtrl.Width = lCtrl.Width + e.X - property.SizeChangeMovePoint.X;
                        //       lCtrl.Height = lCtrl.Height + e.Y - property.p1.Y;   
                        property.SizeChangeMovePoint = e.Location; //'记录光标拖动的当前点   
                        break;
                    case EnumMousePointPosition.MouseSizeTop:
                        lCtrl.Top = lCtrl.Top + (e.Y - property.PositionMovePoint.Y);
                        lCtrl.Height = lCtrl.Height - (e.Y - property.PositionMovePoint.Y);
                        break;
                    case EnumMousePointPosition.MouseSizeLeft:
                        lCtrl.Left = lCtrl.Left + e.X - property.PositionMovePoint.X;
                        lCtrl.Width = lCtrl.Width - (e.X - property.PositionMovePoint.X);
                        break;
                    case EnumMousePointPosition.MouseSizeBottomLeft:
                        lCtrl.Left = lCtrl.Left + e.X - property.PositionMovePoint.X;
                        lCtrl.Width = lCtrl.Width - (e.X - property.PositionMovePoint.X);
                        lCtrl.Height = lCtrl.Height + e.Y - property.SizeChangeMovePoint.Y;
                        property.SizeChangeMovePoint = e.Location; //'记录光标拖动的当前点   
                        break;
                    case EnumMousePointPosition.MouseSizeTopRight:
                        lCtrl.Top = lCtrl.Top + (e.Y - property.PositionMovePoint.Y);
                        lCtrl.Width = lCtrl.Width + (e.X - property.SizeChangeMovePoint.X);
                        lCtrl.Height = lCtrl.Height - (e.Y - property.PositionMovePoint.Y);
                        property.SizeChangeMovePoint = e.Location; //'记录光标拖动的当前点   
                        break;
                    case EnumMousePointPosition.MouseSizeTopLeft:
                        lCtrl.Left = lCtrl.Left + e.X - property.PositionMovePoint.X;
                        lCtrl.Top = lCtrl.Top + (e.Y - property.PositionMovePoint.Y);
                        lCtrl.Width = lCtrl.Width - (e.X - property.PositionMovePoint.X);
                        lCtrl.Height = lCtrl.Height - (e.Y - property.PositionMovePoint.Y);
                        break;
                    default:
                        break;
                }
                if (lCtrl.Width < MinWidth) lCtrl.Width = MinWidth;
                if (lCtrl.Height < MinHeight) lCtrl.Height = MinHeight;
            }
            else
            {
                m_MousePointPosition = MousePointPosition(lCtrl.Size, e);   //'判断光标的位置状态   
                switch (m_MousePointPosition)   //'改变光标   
                {
                    case EnumMousePointPosition.MouseSizeNone:
                        Cursor.Current = Cursors.Arrow;        //'箭头   
                        break;
                    case EnumMousePointPosition.MouseDrag:
                        Cursor.Current = Cursors.SizeAll;      //'四方向   
                        break;
                    case EnumMousePointPosition.MouseSizeBottom:
                        Cursor.Current = Cursors.SizeNS;       //'南北   
                        break;
                    case EnumMousePointPosition.MouseSizeTop:
                        Cursor.Current = Cursors.SizeNS;       //'南北   
                        break;
                    case EnumMousePointPosition.MouseSizeLeft:
                        Cursor.Current = Cursors.SizeWE;       //'东西   
                        break;
                    case EnumMousePointPosition.MouseSizeRight:
                        Cursor.Current = Cursors.SizeWE;       //'东西   
                        break;
                    case EnumMousePointPosition.MouseSizeBottomLeft:
                        Cursor.Current = Cursors.SizeNESW;     //'东北到南西   
                        break;
                    case EnumMousePointPosition.MouseSizeBottomRight:
                        Cursor.Current = Cursors.SizeNWSE;     //'东南到西北   
                        break;
                    case EnumMousePointPosition.MouseSizeTopLeft:
                        Cursor.Current = Cursors.SizeNWSE;     //'东南到西北   
                        break;
                    case EnumMousePointPosition.MouseSizeTopRight:
                        Cursor.Current = Cursors.SizeNESW;     //'东北到南西   
                        break;
                    default:
                        break;
                }
            }

        }

        void control_MouseDown(object sender, MouseEventArgs e)
        {
            var property = GetControlProperty(sender as Control);

            property.PositionMovePoint = e.Location;
            property.SizeChangeMovePoint = e.Location;
        }

        private DragControlProperty GetControlProperty(Control control)
        {
            return controlPropertyDic[control];
        }

        private EnumMousePointPosition MousePointPosition(Size size, System.Windows.Forms.MouseEventArgs e)
        {

            if ((e.X >= -1 * Band) | (e.X <= size.Width) | (e.Y >= -1 * Band) | (e.Y <= size.Height))
            {
                if (e.X < Band)
                {
                    if (e.Y < Band) { return EnumMousePointPosition.MouseSizeTopLeft; }
                    else
                    {
                        if (e.Y > -1 * Band + size.Height)
                        { return EnumMousePointPosition.MouseSizeBottomLeft; }
                        else
                        { return EnumMousePointPosition.MouseSizeLeft; }
                    }
                }
                else
                {
                    if (e.X > -1 * Band + size.Width)
                    {
                        if (e.Y < Band)
                        { return EnumMousePointPosition.MouseSizeTopRight; }
                        else
                        {
                            if (e.Y > -1 * Band + size.Height)
                            { return EnumMousePointPosition.MouseSizeBottomRight; }
                            else
                            { return EnumMousePointPosition.MouseSizeRight; }
                        }
                    }
                    else
                    {
                        if (e.Y < Band)
                        {
                            return EnumMousePointPosition.MouseSizeTop;
                        }
                        else
                        {
                            if (e.Y > -1 * Band + size.Height)
                            {
                                return EnumMousePointPosition.MouseSizeBottom;
                            }
                            else
                            {
                                return EnumMousePointPosition.MouseDrag;
                            }
                        }
                    }
                }
            }
            else
            {
                return EnumMousePointPosition.MouseSizeNone;
            }
        }

    }

}

这里是如何使用DragHelper的例子:

private void Form1_Load(object sender, EventArgs e)
{
    DraggerHelper.EnableDrag(button1);
    DraggerHelper.EnableDrag(label1);

    DraggerHelper.DisableDrag(button1);
    DraggerHelper.DisableDrag(label1);
}

private void button1_Click(object sender, EventArgs e)
{
    if (label1.IsControlCanDrag())
    {
        label1.DisableDrag();
    }
    else
    {
        label1.EnableDrag();
    }
}

完整的代码:ControlDragger.rar

本文参考了:WCCC的杰出的文章:http://www.cnblogs.com/whc-blog/archive/2011/08/26/2154038.html

另外本文不讨论设计,虽然我知道当前设计不一定是最好的,很多复杂的情况都没有涵盖到,不过基本的情况已经覆盖了,欢迎大家扩展和填充。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP