gpt4 book ai didi

c# - 将相同的扩展添加到 winform 中的多个控件

转载 作者:太空宇宙 更新时间:2023-11-03 15:13:42 25 4
gpt4 key购买 nike

我想向 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;
}

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

最佳答案

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

您可以将要扩展的控件传递给辅助类的构造函数,并将您的控件句柄分配给 native 窗口。然后覆盖 native 窗口的 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);

关于c# - 将相同的扩展添加到 winform 中的多个控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39948820/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com