Как я могу использовать те же события мыши в другой форме / пользовательском элементе управления? - PullRequest
0 голосов
/ 26 мая 2019

Я создаю приложение 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;
    }

Могу ли я сделать обработчик событий /делегат, чтобы решить это?

Ответы [ 2 ]

1 голос
/ 26 мая 2019

Вот вспомогательный класс, в который вы можете передать Form и Control Type, и он соединит все соответствующие элементы управления. В этом примере все кнопки подключены, поэтому вы можете перетаскивать их. Просто измените «Button» на интересующий вас тип управления:

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;
    }

}

Обратите внимание, что я связываю Form1 в событии Load () с "this", но я также демонстрирую это для нового экземпляра Form2 в обработчике Click ().

Дополнительное сообщение на основе вопросов комментариев

Основываясь на ваших комментариях, вот пример, показывающий, что кнопки внутри UserControl подключены, чтобы позволить им перемещаться. (Я изменил метод WireControlsOfType<> для принятия универсального элемента управления вместо формы.) В свойствах 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();
    }
1 голос
/ 26 мая 2019

Не могли бы вы немного объяснить, как привести параметр отправителя к контроль

Sure:

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);
    }
}

Теперь на любой элемент управления, являющийся «источником» события, будет действовать (вместо того, чтобы всегда быть формой с «этим»).

...