Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# controls outside of parent's bounds?

I found out that child controls are not drawn outside of their parent's bounds. So if I have a button that is sticking out of the panels right side it's drawn half way to the part where the panel ends.

2 questions:

  • Is there any way to have child controls outside of parents bounds (with some trick maybe) ?
  • What is the reason for that limitation ? (I want to understand that)


Example with 2 buttons: b1 is the big parent, b2 the smaller child:
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);
}

Edit:
It's about controls inside controls not controls inside forms.
No, no fancy UI. I know that I can use regions to create crazy desktop apps. That's not what I want.

Thanks!

like image 230
n4pgamer Avatar asked Jan 19 '14 18:01

n4pgamer


2 Answers

A Form is a control as well, so it behaves very much like other controls.

The rendering limitation comes from the fact that controls are windows in the operating system which just represent a rectangular area of the display. A window cannot draw anything outside of its own bounds so if a child control is placed outside those bounds, it'll not be rendered (or only partially, depending on its position).

There's no easy way around this and the whole concept of child controls revolves around the parent controlling what gets drawn. If you want to draw a child control outside the bounds of its parent, remove the "child" from the parent, since the relationship doesn't really apply.

You can come up with some custom rendering code that would work around this but then controls wouldn't be true children of other containers and you'd have to write a fair amount of rendering code to get it working. There may be some situations where this would be the desired behavior but in most cases the default system behavior is better (and means less work for the programmer).

You can get a visual effect of a button being "outside" the form by custom rendering the form (that is, drawing it smaller than it actually is) and then rendering the button in the empty space. This, however, is a lot of work and I'm not sure you'd want to take that route.

If you're trying to do a fancy UI where some controls are shaped like a blob (not like a rectangle) or they appear floating (detached from the "main" UI), similar to some media players, etc.: those programs do the entire custom-rendering thing; their windows are still rectangular windows but during rendering they use transparent images and regions to render the form.

It'd help if you added more detail to your question as to why do you want to do this.

like image 124
xxbbcc Avatar answered Sep 30 '22 15:09

xxbbcc


You can't draw outside of the controls/parents bounds. However you can place the control in one of the parents ancestors.

This is some code I use to create a drop down menu when this custom control is toggled:

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

    }
}

The dropDownMenu is a control that is setup elsewhere in the constructor of this control.

I start by getting the top most parent, as I check each parent I also get a running x and y value of the controls position relative to the parent.

If this control is toggled then I add it to the top most parent and set its position, otherwise I remove it.

I'm sure there are more complex ways and this may not work in all circumstances however this solution work perfect for me writing a .NET CF menu button.

like image 31
apc Avatar answered Sep 30 '22 14:09

apc