Windows 将多个控件合二为一

Windows Forms Multiple Controls In One

想请教一下。我在 windows 表单编程方面没有足够的经验,所以我不知道处理这个任务的合适方法是什么。

我目前正在用四个面板创建一个矩形。 (这些矩形不代表下面的代码,它们使用不同的大小)

private System.Windows.Forms.Panel rectangleLeftVertical;
private System.Windows.Forms.Panel rectangleRightVertical;
private System.Windows.Forms.Panel rectangleTopHorizontal;
private System.Windows.Forms.Panel rectangleBottomHorizontal;

// ...

this.rectangleLeftVertical.Location = new System.Drawing.Point(100, 100);
this.rectangleLeftVertical.Size = new System.Drawing.Size(3, 100);

this.rectangleRightVertical.Location = new System.Drawing.Point(200, 100);
this.rectangleRightVertical.Size = new System.Drawing.Size(3, 100);

this.rectangleTopHorizontal.Location = new System.Drawing.Point(100, 100);
this.rectangleTopHorizontal.Size = new System.Drawing.Size(100, 3);

this.rectangleBottomHorizontal.Location = new System.Drawing.Point(100, 200);
this.rectangleBottomHorizontal.Size = new System.Drawing.Size(103, 3);

它完全按照我想要的方式工作,我只想将所有内容封装到一个 自定义 Windows 控件 中。 自定义组件大小当然应该调整面板的大小。它还将有一个 属性 指示边框大小。

我不想改变任何东西,我不想做不同的绘图(使用 graphics.paint 解决方案)。它不适合我的用例。

我尝试使用 UserControl,但是它不合适,因为它绘制了矩形的整个内部 - 这是我试图避免的。

如果它也可以在 Windows Forms Designer 中使用,那就更好了 - 但这是非常不必要的。不过那真的很不错。

你们建议我如何解决这个问题?任何帮助将非常感激。这可能不是一个难题,我只是缺乏经验。谢谢!

您可以通过创建一个表示您想要 keep/discard 的表单区域的 GraphicsPath 对象来实现此目的。从覆盖整个表单的矩形开始,然后移除面板的中间,只留下边框。然后从该 GraphicsPath 构建一个区域并将其分配给表单的区域 属性。这将导致表单仅存在于边框所在的位置。从 GraphicsPath 中删除的中间区域实际上将不存在于您的表单中,因此叠加层下方的任何内容都会一直显示。

这里有一个简单的例子,它制作了一个四窗格“window”,可以通过窗格的边框来回拖动:

public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
        this.TopMost = true;
        this.BackColor = Color.Red; // just so you can see it better
        this.FormBorderStyle = FormBorderStyle.None;
    }

    private void Form1_Shown(object sender, EventArgs e)
    {
        GraphicsPath path = new GraphicsPath();
        // add the main rectangle:
        path.AddRectangle(new Rectangle(new Point(0, 0), this.Size));
        // punch some holes in our main rectangle
        // this will make a standard "windowpane" with four panes
        // and a border width of ten pixels
        Size sz = new Size((this.Width - (3 * 10))/2, (this.Height - (3 * 10))/2);
        path.FillMode = FillMode.Alternate;
        path.AddRectangle(new Rectangle(new Point(10, 10), sz));
        path.AddRectangle(new Rectangle(new Point(20 + sz.Width, 10), sz));
        path.AddRectangle(new Rectangle(new Point(10, 20 + sz.Height), sz));
        path.AddRectangle(new Rectangle(new Point(20 + sz.Width, 20 + sz.Height), sz));
        // build a region from our path and set the forms region to that:
        this.Region = new Region(path);
    }

    public const int HTCAPTION = 0x2;
    public const int WM_NCHITTEST = 0x84;
    public const int HTCLIENT = 1;
    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);

        if (m.Msg == WM_NCHITTEST)
        {
            if (m.Result.ToInt32() == HTCLIENT)
                m.Result = (IntPtr)HTCAPTION;
        }
    }

}

它的例子 运行 在我编辑它的时候在这个页面的顶部:

如果您的叠加层可以调整大小and/or,只需重建一个新的 GraphicsPath,更改矩形和 re-assign 从新的 GraphicsPath 构建的区域。

您也可以删除主窗体的 .Opacity,这样您就可以部分看到您的边框。