【问题标题】:Adding same extensions to multiple controls in winforms为winforms中的多个控件添加相同的扩展
【发布时间】:2016-10-09 21:38:28
【问题描述】:

我想向PictureBoxLabelPanel 添加一些扩展,例如移动、调整大小、...,如下所示:

public class LiveControl: PictureBox
{
    private Point cur = new Point(0, 0);
    public LiveControl()
    {
        ResizeRedraw = true;
        MouseDown += (s, e) => { cur = new Point(e.X, e.Y); };
        MouseMove += (s, e) => {
            if (e.Button == MouseButtons.Left)
            {
                Control x = (Control)s;
                x.SuspendLayout();
                x.Location = new Point(x.Left + e.X - cur.X, x.Top + e.Y - cur.Y);
                x.ResumeLayout();
            }
        };
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        var rc = new Rectangle(this.ClientSize.Width - grab, this.ClientSize.Height - grab, grab, grab);
        ControlPaint.DrawSizeGrip(e.Graphics, this.BackColor, rc);
    }
    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (m.Msg == 0x84)
        {  
            var pos = this.PointToClient(new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16));
            if (pos.X >= this.ClientSize.Width - grab && pos.Y >= this.ClientSize.Height - grab)
                m.Result = new IntPtr(17);  
        }
    }
    private const int grab = 16;
}

有没有我把它写成一个类并为所有它们继承它,或者我应该像我为PictureBox写的那样写3个单独的类?

【问题讨论】:

  • 我通常会编写一个控制器类,控件可以注册到该控制器类以获取这些服务。见here for an example of a Drag&Drop controller!
  • @HansPassant 我没明白你的意思
  • 我从别处复制了其中的一部分,我不需要浪费时间写已经写的东西,我也不打算要求代码都是我的,这是举个例子,代码要大得多。
  • 您可能有兴趣FrameControl

标签: c# winforms


【解决方案1】:

您可以将逻辑封装在派生自NativeWindow 类的辅助类中。这样您就可以完成这项工作,而无需为要移动/调整大小的每个控件创建派生类。

您可以将要扩展的控件传递给辅助类的构造函数,并将您的控件句柄分配给本机窗口。然后覆盖原生窗口的WndProc 将处理控件的消息。

通过保持对您在构造函数中传递的控件的引用并分配事件处理程序,也可以简单地处理控件的事件等其他内容。

创建这样的原生窗口助手类后,用法如下:

var h1 = new LiveControlHelper(this.pictureBox1);
var h2 = new LiveControlHelper(this.button1);

或者您可以在循环中使用容器的所有控件的帮助器。

示例

在下面的示例中,我重构了您发布的代码。这样您就可以将代码用于所有控件,而无需继承。

using System;
using System.Drawing;
using System.Windows.Forms;
public class LiveControlHelper : NativeWindow
{
    private Control control;
    private Point cur = new Point(0, 0);
    private const int grab = 16;
    public LiveControlHelper(Control c)
    {
        control = c;
        this.AssignHandle(c.Handle);
        control.MouseDown += (s, e) => { cur = new Point(e.X, e.Y); };
        control.MouseMove += (s, e) => {
            if (e.Button == MouseButtons.Left) {
                Control x = (Control)s;
                x.SuspendLayout();
                x.Location = new Point(x.Left + e.X - cur.X, x.Top + e.Y - cur.Y);
                x.ResumeLayout();
            }
        };
        control.Paint += (s, e) => {
            var rc = new Rectangle(control.ClientSize.Width - grab, 
                control.ClientSize.Height - grab, grab, grab);
            ControlPaint.DrawSizeGrip(e.Graphics, control.BackColor, rc);
        };
        control.Resize += (s, e) => { control.Invalidate(); };
    }
    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (m.Msg == 0x84) {
            var pos = control.PointToClient(new Point(m.LParam.ToInt32() & 0xffff,
                m.LParam.ToInt32() >> 16));
            if (pos.X >= control.ClientSize.Width - grab &&
                pos.Y >= control.ClientSize.Height - grab)
                m.Result = new IntPtr(17);
        }
    }
}

注意

1- 为了能够将控件恢复到其正常状态(不可调整大小的不可移动),最好使用方法而不是使用 lambda 来分配事件处理程序。您需要撤销事件处理程序以将控件恢复到其正常状态。为此,您需要调用帮助类的DestroyHanlde 方法。

2- 我只是重构了发布的代码,使其可重用于控件,而无需实现所有控件的派生版本。但是您可以通过以下方式增强代码:

  • 通过将m.Result 设置为合适的值,启用移动控件并使用控件的曲面、边和角调整其大小。

  • 在控件上绘制抓取边框/处理程序。

3-如果你需要在控制上调用SetStyle,你可以简单地使用this post的扩展方法,这样调用:

control.SetStyle(ControlStyles.OptimizedDoubleBuffer |
    ControlStyles.AllPaintingInWmPaint |
    ControlStyles.ResizeRedraw, true);

【讨论】:

    【解决方案2】:

    我认为使用 T4 文本模板可以解决您的问题。如果您不熟悉,这些链接可能有用: 1.Code Generation and T4 Text Templates 2.Design-Time Code Generation by using T4 Text Templates

    【讨论】:

      猜你喜欢
      • 2018-07-03
      • 2011-05-23
      • 2018-01-14
      • 2016-03-29
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      • 2021-09-28
      • 1970-01-01
      相关资源
      最近更新 更多