Распространить событие на все элементы управления - PullRequest
1 голос
/ 19 октября 2019

Я использую следующий фрагмент кода для документации, обработки ошибок и / или ведения журнала. Это сохраняет изображение UserControl или Form, когда я нажимаю на него, нажимая Control + Alt + Shift:

  public Image GetImage()
  {
     Bitmap oBmp = new Bitmap(this.Width, this.Height);
     this.DrawToBitmap(oBmp, new Rectangle(0, 0, oBmp.Width, oBmp.Height));
     return (Image)oBmp;
  }

  protected override void OnMouseDown(MouseEventArgs e)
  {
     base.OnMouseDown(e);

     bool bControl = false;
     bool bShift = false;
     bool bAlt = false;

     bControl = (Control.ModifierKeys & Keys.Control) == Keys.Control;
     bShift = (Control.ModifierKeys & Keys.Shift) == Keys.Shift;
     bAlt = (Control.ModifierKeys & Keys.Alt) == Keys.Alt;

     if (bControl && bShift && bAlt)
     {
        GetImage().Save(this.Name.TimedLocalFileName("png"), ImageFormat.Png);
     }
  }

Прямо сейчас я кодирую его в каждом UserControl, в базовой форме и так далее. Это легко сделать, потому что я использую фрагмент кода. Но у него есть очевидные недостатки.

  1. Один и тот же кусок кода во многих местах (ремонтопригодность);и
  2. Работает только тогда, когда я нажимаю на базовый элемент управления, а не на его дочерние элементы (если UserControl имеет метку, это не работает.

Я был на несколькихдни, анализирующие GlobalHooks (в основном здесь: CodeProject , но моя голова мне не помогает.

Любое предложение будет очень оценено.

Примечание: TimedLocalFileName - метод расширения, который возвращает строку в формате <ControlName>_<Culture>_<YYYYMMDD>_<HHMMSS>.<FileExtension>

Ответы [ 2 ]

1 голос
/ 19 октября 2019

Создайте базу UserControl и назовите ее BaseUserControl и извлеките весь свой пользовательский элемент управления из BaseUserControl, тогда вы можете поместить всю логику в базовый пользовательский элемент управления.

Внутри BaseUserControl, используя рекурсивный метод, обработайте MouseDown событие всех дочерних элементов управления и перенаправьте их на OnMouseDown из this, как этот пост .

Переопределите OnHanldeCrated и вызовите этот рекурсивный метод для подключения событий.

Вот базовый элемент управления:

using System;
using System.Drawing;
using System.Windows.Forms;
public class BaseUserControl : UserControl
{
    void WireMouseEvents(Control container)
    {
        foreach (Control c in container.Controls)
        {
            c.MouseDown += (s, e) =>
            {
                var p = PointToThis((Control)s, e.Location);
                OnMouseDown(new MouseEventArgs(e.Button, e.Clicks, p.X, p.Y, e.Delta));
            };
            WireMouseEvents(c);
        };
    }
    Point PointToThis(Control c, Point p)
    {
        return PointToClient(c.PointToScreen(p));
    }
    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        if (Control.ModifierKeys == (Keys.Control | Keys.Alt | Keys.Shift))
            MessageBox.Show("Handled!");
        // Your custom logic
    }
    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        WireMouseEvents(this);
    }
}
1 голос
/ 19 октября 2019

Ответ на вопрос 1

Один и тот же фрагмент кода во многих местах (ремонтопригодность)

Это не всегда применимо, но если выесли вы часто используете это поведение, вы можете унаследовать от UserControl, чтобы создать BitmapExportUserControl и вместо этого поместить в этот класс Image GetImage() и override void OnMouseDown(MouseEventArgs e), а все пользовательские элементы управления, которым требуется это поведение, наследуются от BitmapExportUserControl.

Другой способ - выполнить экспорт растрового изображения из самого вашего Form, и ваш Form подписывается на все MouseDown события всех его дочерних Control объектов.

Ответ на вопрос 2

Работает только тогда, когда я нажимаю на базовый элемент управления, а не на его дочерние элементы

Насколько я знаю, нет встроенного-вход "вверх" (или всплывание) в WinForms, как, например, в WPF. Решением может быть предоставление события, которое может быть вызвано всеми UserControl в вашем приложении, когда на них есть событие MouseDown. Ваш код будет выглядеть так:

protected override void OnMouseDown(MouseEventArgs e)
{
    GlobalMouseDown.RaiseGlobalMouseDownEvent(this, e);
}

, и ваш основной Form подпишется на этот GlobalMouseDown.GlobalMouseDownEvent и выполнит проверки и экспорт растрового изображения.

Это функционально эквивалентно наличиюоткрытый метод HandleMouseDown в некотором GlobalMouseDown классе, который будет вызываться всеми вашими UserControl MouseDownEventHandlers. Код в каждом UserControl будет иметь вид:

protected override void OnMouseDown(MouseEventArgs e)
{
    GlobalMouseDown.HandleMouseDown(this, e);
}

, и вы будете выполнять свои проверки и экспорт растровых изображений в этом методе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...