繁体   English   中英

如何在其他形式/用户控件中使用相同的鼠标事件?

[英]How can I use same mouse events in another form / user control?

我用多个用户控件创建winforms c#应用程序。 它是没有边界的平面应用程序,因此移动窗口的唯一方法是使用鼠标控件事件。 我在主窗口中使用了这部分代码,但无法将其应用到任何其他用户控件中。 我不想复制并粘贴所有用户控件,所以有什么使用方法吗?

这段代码以我的主要形式工作,但是当我创建用户控件时,我无法访问这些控件,也无法将它们连接到对象上。

    private bool mouseDown;
    private Point lastLocation;

    private void _MouseDown(object sender, MouseEventArgs e)
    {
        mouseDown = true;
        lastLocation = e.Location;
    }

    private void _MouseMove(object sender, MouseEventArgs e)
    {
        if (mouseDown)
        {
            this.Location = new Point((this.Location.X - lastLocation.X) + e.X, (this.Location.Y - lastLocation.Y) + e.Y);
            this.Update();
        }
    }
    private void _MouseUp(object sender, MouseEventArgs e)
    {
        mouseDown = false;
    }

我可以让事件处理程序/委托来解决吗?

您能否解释一下如何将sender参数转换为控件?

当然:

private void _MouseMove(object sender, MouseEventArgs e)
{
    Control source = (Control)sender; // cast "sender" to a control
    if (mouseDown)
    {
        source.Location = new Point((source.Location.X - lastLocation.X) + e.X, (source.Location.Y - lastLocation.Y) + e.Y);
    }
}

现在将对事件的“源”采取任何控制措施(而不是始终以“ this”为形式)。

这是一个帮助程序类,您可以将Form和Control Type传递给它,它将连接所有匹配的控件。 在此示例中,所有按钮均已连接,因此您可以拖动它们。 只需将“按钮”更改为您感兴趣的控件类型:

public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        this.WireControlsOfType<Button>();
    }      

    private void button1_Click(object sender, EventArgs e)
    {
        Form2 f2 = new Form2();
        f2.Show();
        f2.WireControlsOfType<Button>();
    }

}

帮助器类在另一个文件中:

public static class FormHelper
{

    public static void WireUserControl(this UserControl uc)
    {
        uc.MouseDown += _MouseDown;
        uc.MouseMove += _MouseMove;
        uc.MouseUp += _MouseUp;
    }

    public static void WireControlsOfType<T>(this Control sourceControl)
    {
        foreach(var ctl in sourceControl.RecursiveFindControlsByType<T>())
        {
            ctl.MouseDown += _MouseDown;
            ctl.MouseMove += _MouseMove;
            ctl.MouseUp += _MouseUp;
        }
    }

    // Code by Jon Skeet: https://stackoverflow.com/a/2055946/2330053
    public static IEnumerable<Control> RecursiveFindControlsByType<T>(this Control control)
    {
        foreach (Control c in control.Controls)
        {
            if (c is T)
            {
                yield return c;
            }

            if (c.Controls.Count > 0)
            {
                foreach (Control ctl in c.RecursiveFindControlsByType<T>())
                {
                    yield return ctl;
                }
            }
        }
    }

    private static bool mouseDown;
    private static Point lastLocation;

    private static void _MouseDown(object sender, MouseEventArgs e)
    {
        mouseDown = true;
        lastLocation = e.Location;
    }

    private static void _MouseMove(object sender, MouseEventArgs e)
    {
        Control source = (Control)sender;
        if (mouseDown)
        {
            source.Location = new Point((source.Location.X - lastLocation.X) + e.X, (source.Location.Y - lastLocation.Y) + e.Y);
        }
    }

    private static void _MouseUp(object sender, MouseEventArgs e)
    {
         mouseDown = false;
    }

}

请注意,我正在用“ this”连接Load()事件中的Form1,但我还将在Click()处理程序中为Form2的新实例演示它。

基于评论问题的其他帖子

根据您的评论,下面是一个示例,该示例显示将UserControl内部的Button连接起来以允许它们左右移动。 (我将WireControlsOfType<>方法更改为接受通用控件而不是Form。)默认的UserControl属性中未进行任何更改以允许以下操作:

    private void button1_Click(object sender, EventArgs e)
    {
        panel1.Controls.Clear();

        UserControlA ucA = new UserControlA();
        ucA.Dock = DockStyle.Fill;         
        panel1.Controls.Add(ucA);
        ucA.WireControlsOfType<Button>();
    }

静态FormHelper类是允许使用此魔术的原因。 它可以是自己的类,不需要与任何Forms / UserControls复制/关联。 实际上,它独立于它们并且可以在其自己的文件中。

如果您希望整个UserControl本身能够在其容器周围拖动,我在上面的帮助器类中添加了一个名为WireUserControl()帮助器方法。 因此,以下代码段将UserControlA的多个实例添加到panel1中,每个实例都可以分别拖动:

    private void button1_Click(object sender, EventArgs e)
    {
        UserControlA ucA = new UserControlA();        
        panel1.Controls.Add(ucA);
        ucA.WireUserControl();
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM