Cris McLaughlin
Cris McLaughlin

Reputation: 1211

Children inherit parents appearance

I have created a simple custom panel using ContainerControl as my base. I've added custom properties to create borders and gradient backgrounds. If I override OnPaint and OnPaintBackground all child controls of the parent inherit the gradient and border styles. As a work around I have used the parents BackgroundImage property which works fine but has a few random quirks. There has to be a better way of approaching this issue but I have found no solution. Are there any Window API functions via Interop or other C# methods to fix this? If so please provide an example.

EDIT! Here is the style being copied (ugly example but makes the point):

enter image description here

EDIT 2! Here is a simple hard-coded ContainerControl without all the properties, designer attributes, etc.

public class Container : ContainerControl
{
    protected override void OnPaintBackground( PaintEventArgs e )
    {
        using ( var brush = new LinearGradientBrush( e.ClipRectangle, Color.Red, Color.Blue, LinearGradientMode.Vertical ) )
        {
            e.Graphics.FillRectangle( brush, e.ClipRectangle );
        }
    }
}

Upvotes: 4

Views: 3709

Answers (3)

Frédéric Hamidi
Frédéric Hamidi

Reputation: 262919

If a Label control is created with its BackColor property set to Color.Transparent, it will end up calling its parent's OnPaintBackground() implementation.

If you modify Jon's example like this:

var label = new Label { 
    Text = "Label",
    Location = new Point(20, 50),
    BackColor = Color.Transparent
};

Then you will reproduce the issue.

There is an easy workaround, however. The problem comes from the way you're creating the linear gradient brush. Since you're passing e.ClipRectangle to its constructor, the shape of the gradient will vary depending on the control being rendered (container or label). On the other hand, if you pass the ClientRectangle of the container, then the gradient will always have the same shape and the result should be what you're looking for:

protected override void OnPaintBackground(PaintEventArgs e)
{
    using (var brush = new LinearGradientBrush(ClientRectangle,
           Color.Red, Color.Blue, LinearGradientMode.Vertical)) {
        e.Graphics.FillRectangle(brush, e.ClipRectangle);
    }
}

The result is:

enter image description here

Upvotes: 4

Jon Skeet
Jon Skeet

Reputation: 1499770

I can't reproduce this simply on my Windows 7 machine - which suggests it may be one of the properties you've set in the designer. Short but complete program:

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

public class GradientContainer : ContainerControl
{
    protected override void OnPaintBackground(PaintEventArgs e)
    {
        using (var brush = new LinearGradientBrush(e.ClipRectangle, 
                       Color.Red, Color.Blue, LinearGradientMode.Vertical))
        {
            e.Graphics.FillRectangle(brush, e.ClipRectangle);
        }
    }
}

class Test
{
    static void Main()
    {
        var label = new Label { 
            Text = "Label",
            Location = new Point(20, 50)
        };
        var container = new GradientContainer {
            Size = new Size(200, 200),
            Location = new Point(0, 0),
            Controls = { label }
        };        

        Form form = new Form {
            Controls = { container },
            Size = new Size(300, 300)
        };
        Application.Run(form);
    } 
}

And the result:

Label has no gradient

Upvotes: 0

ullfindsmit
ullfindsmit

Reputation: 300

Initialize the properties on control create/load

Then "INVALIDATE" the control to force a redraw of the control

Upvotes: 0

Related Questions