C# Windows在一个窗口中形成多个控件

C# Windows在一个窗口中形成多个控件,c#,windows,forms,winforms,panel,C#,Windows,Forms,Winforms,Panel,我想征求一些意见。我没有足够的windows窗体编程经验,因此我不知道处理此任务的适当方法 我目前正在从四个面板创建一个矩形。(这些矩形不代表下面的代码,它们使用不同的大小) 它完全按照我的要求工作,我只想将所有内容封装到一个自定义Windows控件中。 自定义组件大小当然应该调整面板的大小。它还将具有一个指定边框大小的属性 我不想更改任何内容,我不想以不同的方式绘制(使用graphics.paint解决方案)。它不适合我的用例 我尝试使用UserControl,但是,这不合适,因为它绘制了矩

我想征求一些意见。我没有足够的windows窗体编程经验,因此我不知道处理此任务的适当方法

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

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

我不想更改任何内容,我不想以不同的方式绘制(使用graphics.paint解决方案)。它不适合我的用例

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

如果它也可以在Windows窗体设计器中使用,那就更好了,但这是非常不必要的。不过那真的很好


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

可以通过创建一个GraphicsPath对象来实现这一点,该对象表示要保留/放弃的表单区域。从覆盖整个表单的矩形开始,然后删除面板的中间部分,只留下边框。然后从该图形SPATH构建一个区域,并将其指定给窗体的Region属性。这将导致一个只存在于边界所在位置的表单。从GraphicsPath中删除的中间区域实际上不存在于您的表单中,因此覆盖层下方的任何内容都将直接显示出来

下面是一个制作四窗格“窗口”的快速示例,该窗口可以通过窗格的边框拖动:

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

}
当我编辑它时,它在页面顶部运行的示例:

如果覆盖可以调整大小和/或调整,只需重新生成一个新的GraphicsPath,更改矩形,然后重新指定从新GraphicsPath生成的区域


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

当您说“绘制”时,您的意思是面板会根据调整大小事件重新绘制吗?如果需要不同颜色的线条,您会怎么做?像你这样画线效率很低,我怀疑你是否有理由支持你的“用户案例”,你在处理背景方面已经遇到了问题。@RossBush我不确定你指的是什么。我需要矩形的内部完全透明,因为我有另一个进程停靠在它下面的面板上-因此使用任何颜色。透明将不起作用(它将隐藏边框内的内容)。控件使用完全相同的“缓慢且非常闪烁”技术重新绘制自己。换句话说,您不是在快速绘制线条,而是在创建另一个窗口,将所有开销(事件循环、内存、资源)都用于。。画线。无意冒犯,我试图说服您编写自定义控件(就像我之前评论中的那个),为其添加属性并正确执行。这个问题可能会导致一个精彩的解决方案!这比我想要的还要好。非常感谢你!我在UserControl中使用它,而不是单独的表单,当然也可以使用相同的逻辑。竖起大拇指
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;
        }
    }

}