首页 > 解决方案 > 将事件传播到所有控件

问题描述

我正在使用以下代码,用于文档、错误处理和/或日志记录。当我按下 Control+Alt+Shift 键单击它时,它会保存 UserControl 或 Form 的图像:

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

现在,我在每个用户控件、基本表单等中对其进行编码。这很容易做到,因为我使用的是代码片段。但它有明显的挫折。

  1. 很多地方的同一段代码(可维护性);和
  2. 仅当我单击基本控件而不是其子控件时才有效(如果 UserControl 具有标签,则此方法不起作用。

我已经分析了几天 GlobalHooks(主要是在这里:CodeProject,但我的头脑并没有帮助我。

任何建议将不胜感激。

注意: TimedLocalFileName 是一个扩展方法,它返回一个字符串格式<ControlName>_<Culture>_<YYYYMMDD>_<HHMMSS>.<FileExtension>

标签: c#.netwinformsuser-controls

解决方案


创建一个基础UserControl并命名它BaseUserControl并从中派生所有用户控件,BaseUserControl然后您可以将所有逻辑放在基础用户控件中。

在内部BaseUserControl,使用递归方法,处理MouseDown所有子控件的事件并将它们重定向到OnMouseDownof 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);
    }
}

推荐阅读