[英]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.