3
votes

I am trying to create a custom control that behaves a lot like a GroupBox, but with properties for changing the border color, changing the group label text color, and hiding the group label. The control inherits directly from UserControl, and overrides On_Paint to draw a border rectangle and the label with whatever color the form designer chooses.

The issue I'm having is when trying to dock nested controls inside it. When docking, it uses that entire rectangle of the control, rather than the painted rectangle. I would like it to behave like GroupBox, where docked controls are restricted to a smaller rectangle inside the borders of the control.

Is there a property of UserControl (or perhaps Panel, which I could inherit instead) that allows you to set the rectangle that docked nested controls are docked to?


Thank you, Reza. That was just what I needed. Here is my new control, if anyone wants to use it:

public class LabelledPanel : Panel {

    #region Constructors / Initializers
    public LabelledPanel() : base() {
        InitializeComponent();
    }

    private void InitializeComponent() {
        this.BackColor = System.Drawing.Color.Transparent;
        this.ForeColor = System.Drawing.Color.Red;
        this.Name = "LabelledPanel";
        this.ResumeLayout(false);
        this.PerformLayout();
    }
    #endregion

    #region Private fields
    private String text = "Label";
    private Brush brush;
    private Color foreColor;
    private Boolean showLabel = true;
    private Int32 labelHeight = 13;
    private Int32 pad = 3;
    #endregion

    #region Properties
    [Browsable(true)]
    [Category("Appearance")]
    public override String Text {
        get { return text; }
        set { text = value; }
    }

    [Browsable(true)]
    [Category("Appearance")]
    public override Color ForeColor {
        get { return foreColor; }
        set { 
            foreColor = value;
            brush = new SolidBrush(value);
        }
    }

    [Browsable(true)]
    [Category("Layout")]
    public Boolean ShowLabel {
        get { return showLabel; }
        set { showLabel = value; }
    }

    public override Rectangle DisplayRectangle {
        get {
            var r = GetBorderRect();
            return new Rectangle(
                r.Left + pad,
                r.Top + pad,
                r.Width - (2 * pad),
                r.Height - (2 * pad));
        }
    }        
    #endregion

    protected override void OnPaint(PaintEventArgs p) {            
        base.OnPaint(p);
        ControlPaint.DrawBorder(p.Graphics, GetBorderRect(), foreColor, ButtonBorderStyle.Solid);        
        if (showLabel)
            p.Graphics.DrawString(Text, Font, brush, 0, 0);
    }

    private Rectangle GetBorderRect() {
        Rectangle r = this.ClientRectangle;
        if (showLabel) {
            r.Height -= labelHeight;
            r.Y += labelHeight;
        }
        return r;
    }
}
1
By the way It's better to not post the answer as part of your question. It may be confusing for future readers. You can post the edited part as an answer.Reza Aghaei

1 Answers

1
votes

Controls respect to DisplayRectangle of their container when docking.
So you can override DisplayRectangle property of the container to customize the filled area by docked child controls. As an example, you can take a look at source code of DisplayRectangle property of GroupBox control.

Also instead of overriding display rectangle, you can set Padding property. For container controls, the Padding property gets or sets their DisplayRectangle properties.