c# 自定义控件鼠标事件响应

时间:2022-08-31 08:06:00
我在UserControl里面添加了一个label控件,在程序添加了鼠标移动拖拽事件,但是实现的是只能拖拽UserControl才能进行移动,选中label并不能进行移动,所以label大小是要比UserControl要小的,且只能选中边框才能进行拖动,但这并不是我想要的效果。我想实现选中label就能够进行拖动,并且将这个控件添加到form里面的时候,当拖拽到form之外时不能拖拽出去,因为目前这个拖拽出去之后就找不回来了。。。。求解答。。。。
还有,在以上的基础上,能不能做成我选中边框时进行拖拽可以自行改变label的大小呢?
c# 自定义控件鼠标事件响应

13 个解决方案

#1


你注册label的鼠标事件,然后给label设置背景色(比如透明)。这样Label就能响应鼠标事件了。

#2


引用 1 楼 Libby1984 的回复:
你注册label的鼠标事件,然后给label设置背景色(比如透明)。这样Label就能响应鼠标事件了。

嗯嗯我怎么没有想到呢!现在我有四个需求,能不能尽可能的帮忙提供下思路呢?
1.我想可以选中label的边框进行对label的拉伸和缩放
2.将这个自定义控件生成在picturebox中,对label移动的话不可移出picturebox控件
3.我还想设置个保存按钮,当我生成多个label之后,点击保存,下次打开的时候还能够看到上次的label
4.后退撤销。这个我大致有点思路,如果可以提供帮助感激不尽。。。

#3


关于上面我提出的问题,已解决第二个问题,可不移出父级控件了
还有几个问题请大家帮忙多想想办法啊

c# 自定义控件鼠标事件响应

#4


给你一个参考
c# 自定义控件鼠标事件响应
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            var c = new myLabel();
            c.Text = "左键移动,右键拉伸";
            Controls.Add(c);
        }
    }
    public class myLabel:Label
    {
        public myLabel()
        {
            //AutoSize = true;
            BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
        }
        int ox, oy;
        protected override void OnMouseDown(MouseEventArgs e)
        {
            ox = e.X;
            oy = e.Y;
        }
        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                var rct = Rectangle.Inflate(ClientRectangle, 1, 1);
                rct.Offset(Left + e.X - ox, Top + e.Y - oy);
                if (Parent.ClientRectangle.Contains(rct))
                {
                    Left += e.X - ox;
                    Top += e.Y - oy;
                }
            }
            if (e.Button == MouseButtons.Right)
            {
                Width = e.X;
                Height = e.Y;
            }
        }
    }

#5


引用 4 楼 xuzuning 的回复:
给你一个参考
c# 自定义控件鼠标事件响应
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            var c = new myLabel();
            c.Text = "左键移动,右键拉伸";
            Controls.Add(c);
        }
    }
    public class myLabel:Label
    {
        public myLabel()
        {
            //AutoSize = true;
            BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
        }
        int ox, oy;
        protected override void OnMouseDown(MouseEventArgs e)
        {
            ox = e.X;
            oy = e.Y;
        }
        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                var rct = Rectangle.Inflate(ClientRectangle, 1, 1);
                rct.Offset(Left + e.X - ox, Top + e.Y - oy);
                if (Parent.ClientRectangle.Contains(rct))
                {
                    Left += e.X - ox;
                    Top += e.Y - oy;
                }
            }
            if (e.Button == MouseButtons.Right)
            {
                Width = e.X;
                Height = e.Y;
            }
        }
    }


嗯嗯你这个很有用啊。可有点奇怪的是,我拉伸的是UserControl那个边框,却不是UserControl里面那个label的边框,因此我想点击label变色的时候还只是原来label那个部分变色,拉伸出来的怎么没有用呢?拖动的话也是在原来设定的label区域才能拖动。
我是个新手,还望能够多多指教!!!

#6


private void led_label_MouseMove(object sender, MouseEventArgs e)
        {
            Cursor = Cursors.Hand;
            if (e.Button == MouseButtons.Left)
            {
                Top += e.Y - oy;
                Left += e.X - ox;
            }
            if (e.Button == MouseButtons.Right)
            {
                Width = e.X;
                Height = e.Y;
            }
            Control parent = this.Parent;
            if (this.Location.X + this.Width > parent.Width)
            {
                Left = parent.Width - this.Width;
            }
            else if (this.Location.X < 0)
            {
                Left = 0;
            }
            if (this.Location.Y + this.Height > parent.Height)
            {
                Top = parent.Height - this.Height;
            }
            else if (this.Location.Y < 0)
            {
                Top = 0;
            }
        }

这是我写的移动事件,好奇怪,拉伸之后多出来的部分也可以不移出父窗口,但是为什么多出来的部分不能够进行拖动和变色呢?求教啊~~~

#7


不知道你所谓的“拖动UserControl”是如何设计的。假设如上面那样根据 mousedown、mouseup 和 mousemove 来设计,那么这个思路本身就限制“死了”拖动的概念的范畴。仅仅看这个逻辑,如果说响应 mousedown 等事件的控件才是可拖动的,这就把“可拖动”给限制死了。

你的需求,需要重新表述一下。你的 UserControl 应该可以监听子控件的“拖动”事件而进行联动地改变 Location,而子控件被用户“拖动”时其实是不改变位置的。
public event Action<int, int> Alert;

int ox, oy;
bool drag = false;

private void button1_MouseDown(object sender, MouseEventArgs e)
{
    ox = e.X;
    oy = e.Y;
    drag = true;
}

private void button1_MouseMove(object sender, MouseEventArgs e)
{
    if (!drag)
        return;

    if (Alert != null)
        Alert(e.X - ox, e.Y - oy);
    ox = e.X;
    oy = e.Y;
}

private void button1_MouseUp(object sender, MouseEventArgs e)
{
    drag = false;
}

#8


我用了一下上面的代码,不管那个代码写得好坏,关键不在于此。

在于逻辑设计,在于考虑清楚“用户控件”的内部结构。

#9


引用 6 楼 shmily_19900314 的回复:
这是我写的移动事件,好奇怪,拉伸之后多出来的部分也可以不移出父窗口,但是为什么多出来的部分不能够进行拖动和变色呢?


这种在逻辑中想当然地纠缠上“父窗口”的思路很容易混乱。一个控件它被用户拖动时,它自身不改变坐标,而是只把用户拖动鼠标的偏移量作为参数,触发事件公布。谁爱捕获这个事件,跟控件自身无关。

如果你不纠结混乱的依赖关系,而是使用依赖倒置的逻辑方式,就很少会有纠结。

#10


在你上面#6楼贴出的代码中,你贴出的代码基本上都是不属于这里的职责的代码。一大堆莫名其妙的计算,一些莫名其妙的
this.Parent
这类想当然地代码,就限制了它。稍微复杂一点,那么出各种bug都在所难免。

它本没有这些职责,它应该抛出事件,然后那些真正监听这个事件的部分才去准确地移动。

#11


引用 10 楼 sp1234_maJia 的回复:
在你上面#6楼贴出的代码中,你贴出的代码基本上都是不属于这里的职责的代码。一大堆莫名其妙的计算,一些莫名其妙的
this.Parent
这类想当然地代码,就限制了它。稍微复杂一点,那么出各种bug都在所难免。

它本没有这些职责,它应该抛出事件,然后那些真正监听这个事件的部分才去准确地移动。

我的代码是写的很糟。我是在自定义控件的时候拖放了一个label控件在里面,然后我想进行拖动以及缩放,现在就是label和UserControl 有点混乱,我只想被选中的拖动和缩放的是label。然后关于那个this.parent,因为我是不想让这个控件移出父级控件,就用parent找到他的父级控件。
如果我的思路有问题,可以给点更详细的思路吗?拜托了!

#12


缩放问题已经解决啦!只剩最后一个问题。
如何保存我添加的控件,使得我关闭EXE文件后下次打开依然有上次整理过后的控件?
求帮忙啊!!

#13


还有一个小问题,当右击textbox文本框后会出现一个对话框,如何将这个对话框取消掉啊???

#1


你注册label的鼠标事件,然后给label设置背景色(比如透明)。这样Label就能响应鼠标事件了。

#2


引用 1 楼 Libby1984 的回复:
你注册label的鼠标事件,然后给label设置背景色(比如透明)。这样Label就能响应鼠标事件了。

嗯嗯我怎么没有想到呢!现在我有四个需求,能不能尽可能的帮忙提供下思路呢?
1.我想可以选中label的边框进行对label的拉伸和缩放
2.将这个自定义控件生成在picturebox中,对label移动的话不可移出picturebox控件
3.我还想设置个保存按钮,当我生成多个label之后,点击保存,下次打开的时候还能够看到上次的label
4.后退撤销。这个我大致有点思路,如果可以提供帮助感激不尽。。。

#3


关于上面我提出的问题,已解决第二个问题,可不移出父级控件了
还有几个问题请大家帮忙多想想办法啊

c# 自定义控件鼠标事件响应

#4


给你一个参考
c# 自定义控件鼠标事件响应
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            var c = new myLabel();
            c.Text = "左键移动,右键拉伸";
            Controls.Add(c);
        }
    }
    public class myLabel:Label
    {
        public myLabel()
        {
            //AutoSize = true;
            BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
        }
        int ox, oy;
        protected override void OnMouseDown(MouseEventArgs e)
        {
            ox = e.X;
            oy = e.Y;
        }
        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                var rct = Rectangle.Inflate(ClientRectangle, 1, 1);
                rct.Offset(Left + e.X - ox, Top + e.Y - oy);
                if (Parent.ClientRectangle.Contains(rct))
                {
                    Left += e.X - ox;
                    Top += e.Y - oy;
                }
            }
            if (e.Button == MouseButtons.Right)
            {
                Width = e.X;
                Height = e.Y;
            }
        }
    }

#5


引用 4 楼 xuzuning 的回复:
给你一个参考
c# 自定义控件鼠标事件响应
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            var c = new myLabel();
            c.Text = "左键移动,右键拉伸";
            Controls.Add(c);
        }
    }
    public class myLabel:Label
    {
        public myLabel()
        {
            //AutoSize = true;
            BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
        }
        int ox, oy;
        protected override void OnMouseDown(MouseEventArgs e)
        {
            ox = e.X;
            oy = e.Y;
        }
        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                var rct = Rectangle.Inflate(ClientRectangle, 1, 1);
                rct.Offset(Left + e.X - ox, Top + e.Y - oy);
                if (Parent.ClientRectangle.Contains(rct))
                {
                    Left += e.X - ox;
                    Top += e.Y - oy;
                }
            }
            if (e.Button == MouseButtons.Right)
            {
                Width = e.X;
                Height = e.Y;
            }
        }
    }


嗯嗯你这个很有用啊。可有点奇怪的是,我拉伸的是UserControl那个边框,却不是UserControl里面那个label的边框,因此我想点击label变色的时候还只是原来label那个部分变色,拉伸出来的怎么没有用呢?拖动的话也是在原来设定的label区域才能拖动。
我是个新手,还望能够多多指教!!!

#6


private void led_label_MouseMove(object sender, MouseEventArgs e)
        {
            Cursor = Cursors.Hand;
            if (e.Button == MouseButtons.Left)
            {
                Top += e.Y - oy;
                Left += e.X - ox;
            }
            if (e.Button == MouseButtons.Right)
            {
                Width = e.X;
                Height = e.Y;
            }
            Control parent = this.Parent;
            if (this.Location.X + this.Width > parent.Width)
            {
                Left = parent.Width - this.Width;
            }
            else if (this.Location.X < 0)
            {
                Left = 0;
            }
            if (this.Location.Y + this.Height > parent.Height)
            {
                Top = parent.Height - this.Height;
            }
            else if (this.Location.Y < 0)
            {
                Top = 0;
            }
        }

这是我写的移动事件,好奇怪,拉伸之后多出来的部分也可以不移出父窗口,但是为什么多出来的部分不能够进行拖动和变色呢?求教啊~~~

#7


不知道你所谓的“拖动UserControl”是如何设计的。假设如上面那样根据 mousedown、mouseup 和 mousemove 来设计,那么这个思路本身就限制“死了”拖动的概念的范畴。仅仅看这个逻辑,如果说响应 mousedown 等事件的控件才是可拖动的,这就把“可拖动”给限制死了。

你的需求,需要重新表述一下。你的 UserControl 应该可以监听子控件的“拖动”事件而进行联动地改变 Location,而子控件被用户“拖动”时其实是不改变位置的。
public event Action<int, int> Alert;

int ox, oy;
bool drag = false;

private void button1_MouseDown(object sender, MouseEventArgs e)
{
    ox = e.X;
    oy = e.Y;
    drag = true;
}

private void button1_MouseMove(object sender, MouseEventArgs e)
{
    if (!drag)
        return;

    if (Alert != null)
        Alert(e.X - ox, e.Y - oy);
    ox = e.X;
    oy = e.Y;
}

private void button1_MouseUp(object sender, MouseEventArgs e)
{
    drag = false;
}

#8


我用了一下上面的代码,不管那个代码写得好坏,关键不在于此。

在于逻辑设计,在于考虑清楚“用户控件”的内部结构。

#9


引用 6 楼 shmily_19900314 的回复:
这是我写的移动事件,好奇怪,拉伸之后多出来的部分也可以不移出父窗口,但是为什么多出来的部分不能够进行拖动和变色呢?


这种在逻辑中想当然地纠缠上“父窗口”的思路很容易混乱。一个控件它被用户拖动时,它自身不改变坐标,而是只把用户拖动鼠标的偏移量作为参数,触发事件公布。谁爱捕获这个事件,跟控件自身无关。

如果你不纠结混乱的依赖关系,而是使用依赖倒置的逻辑方式,就很少会有纠结。

#10


在你上面#6楼贴出的代码中,你贴出的代码基本上都是不属于这里的职责的代码。一大堆莫名其妙的计算,一些莫名其妙的
this.Parent
这类想当然地代码,就限制了它。稍微复杂一点,那么出各种bug都在所难免。

它本没有这些职责,它应该抛出事件,然后那些真正监听这个事件的部分才去准确地移动。

#11


引用 10 楼 sp1234_maJia 的回复:
在你上面#6楼贴出的代码中,你贴出的代码基本上都是不属于这里的职责的代码。一大堆莫名其妙的计算,一些莫名其妙的
this.Parent
这类想当然地代码,就限制了它。稍微复杂一点,那么出各种bug都在所难免。

它本没有这些职责,它应该抛出事件,然后那些真正监听这个事件的部分才去准确地移动。

我的代码是写的很糟。我是在自定义控件的时候拖放了一个label控件在里面,然后我想进行拖动以及缩放,现在就是label和UserControl 有点混乱,我只想被选中的拖动和缩放的是label。然后关于那个this.parent,因为我是不想让这个控件移出父级控件,就用parent找到他的父级控件。
如果我的思路有问题,可以给点更详细的思路吗?拜托了!

#12


缩放问题已经解决啦!只剩最后一个问题。
如何保存我添加的控件,使得我关闭EXE文件后下次打开依然有上次整理过后的控件?
求帮忙啊!!

#13


还有一个小问题,当右击textbox文本框后会出现一个对话框,如何将这个对话框取消掉啊???