C#控件可以超出父容器的边界吗?

11

我发现子控件不会被绘制在其父控件的边界之外。因此,如果我有一个按钮超出面板右侧,它将只被绘制到面板结束的位置的一半。

2个问题:

  • 有没有任何方法可以让子控件在父控件的范围之外(也许用一些技巧)?
  • 这种限制的原因是什么?(我想理解一下)


示例,带有2个按钮:b1是大的父控件,b2是较小的子控件:

public Form1()
{
    Size = new Size(800, 600);

    Button b1 = new Button();
    b1.Text = "hello world";
    b1.SetBounds(0,0,256,128);
    Controls.Add(b1);

    Button b2 = new Button();
    b2.Text = "abcdefghijklmnopqrstuvwxyz";
    b2.SetBounds(192,32,128,64);
    b1.Controls.Add(b2);
}

编辑:
这是关于控件内的控件,而不是表单内的控件。没有花哨的用户界面。我知道可以使用区域创建炫酷的桌面应用程序,但那不是我想要的。

谢谢!


1
我很好奇:你为什么想这样做? - xxbbcc
3个回答

6

一个Form也是一个控件,因此它的行为非常类似于其他控件。

渲染限制来自于控件是操作系统中的窗口,它只代表显示器的矩形区域。窗口不能在其自身范围之外绘制任何内容,因此如果子控件放置在这些范围之外,则不会被渲染(或者只有部分,取决于其位置)。

没有简单的方法可以解决这个问题,整个子控件的概念都围绕父级控件控制什么被绘制。如果要在父级控件的范围之外绘制子控件,请从父级控件中移除“子项”,因为这种关系实际上并不适用。

您可以想出一些自定义渲染代码来解决这个问题,但是那样的话控件就不是其他容器的真正子控件了,您需要编写大量的渲染代码才能使其工作。可能有一些情况下这是期望的行为,但在大多数情况下,默认的系统行为更好(对程序员来说意味着更少的工作)。

您可以通过自定义渲染表单(即将其绘制为实际大小的较小形式),然后在空白区域中渲染按钮,来获得按钮“超出”表单的视觉效果。但是,这需要大量的工作,我不确定您是否想采用这种方法。

如果您正在尝试创建一个花哨的用户界面,其中一些控件的形状像斑点(而不是矩形),或者它们看起来浮动(与“主”用户界面分离),类似于某些媒体播放器等:这些程序会做整个自定义渲染的事情;它们的窗口仍然是矩形窗口,但在渲染期间,它们使用透明图像和区域来渲染窗体。

如果您能在问题中添加更多详细信息,说明为什么要这样做,那将有助于解决您的问题。


我正在开发一个具有非常复杂功能的控件,需要将其分解成几个子控件以简化开发。您认为是否应该为我的“父控件”和它的子控件创建一个大型父控件,使所有现有控件成为兄弟控件?请注意,不需要过于花哨的 UI 部分 ^^ - n4pgamer
@n4pgamer 对不起,我不太明白,但让我试着回答一下。如果您正在制作一个复杂的自定义控件,那么是的,将较小的块拆分为其他自定义控件,然后将其作为子项包含在主自定义控件中。如果您添加有关控件结构的更多详细信息,我会尝试在答案中添加更多内容。 - xxbbcc

3

您不能在控件/父控件范围之外进行绘制。但是,您可以将控件放置在其中一个父级的祖先中。

这是我使用的一些代码,用于在切换此自定义控件时创建下拉菜单:

private void Me_ToggledChanged(System.Object sender, System.EventArgs e)
{

    if (this.Parent != null) {


        Control topParent = this;
        int x = 0;
        int y = 0;

        while (topParent.Parent != null) {
            x += topParent.Left;
            y += topParent.Top;
            topParent = topParent.Parent;
        }

        if (this.Toggled) {
            if (!topParent.Controls.Contains(dropDownMenu)) {
                topParent.Controls.Add(dropDownMenu);
            }

            dropDownMenu.Location = new Point(x, y);        
            dropDownMenu.Visible = true;
            dropDownMenu.BringToFront();
        } else {
            if (topParent.Controls.Contains(dropDownMenu)) {
                this.Parent.Controls.Remove(dropDownMenu);
            }
            dropDownMenu.Visible = false;
        }

    }
}

下拉菜单是一个控件,它在此控件的构造函数中设置。
我首先获取最顶层的父级,在检查每个父级时,我还获取了相对于父级的控件位置的运行x和y值。
如果此控件被切换,则将其添加到最顶层的父级并设置其位置,否则将其删除。
我相信还有更复杂的方法,而且这种解决方案可能不适用于所有情况,但对我来说编写.NET CF菜单按钮非常完美。

我认为这在WinForms中不起作用,因为活动窗体没有父级。 - Gus
只要您不希望在顶层(即表单)之外绘制,这将起作用。示例的第一部分选择了顶层项目,大多数情况下是表单。 这对于.NET CF在移动设备上非常理想,因为表单通常是全屏的。 - apc

0

在WinForms中,无法在控件的边界之外绘制。

将按钮限制在面板内部的最简单方法是适当使用Anchor属性。通常情况下,按钮是右对齐的。如果您希望在面板调整大小时保持此对齐方式,请将按钮停靠在右侧。如果按钮在底部,则也要将其锚定到底部,否则锚定到顶部。

如果您希望按钮随着面板宽度调整大小,则将其同时停靠在左侧和右侧,并额外停靠在顶部或底部。

enter image description here
图片来源:Windows Forms入门:将按钮锚定到右下角


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接