views:

100

answers:

3

I've written the following (very simple) control for use in an application (comments removed for brevity):

public partial class HorizontalRule : Control
{
    public HorizontalRule()
    {
        InitializeComponent();
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        var g = e.Graphics;

        var rect = new Rectangle(
            this.ClientRectangle.Left,
            this.ClientRectangle.Height / 2 + 1, 
            this.ClientRectangle.Width,
            1);

        ControlPaint.DrawBorder3D(g, rect, Border3DStyle.Etched);

        return;
    }
}

Disclaimer: I'm a newbie at painting my own controls.

I chose to draw the line this way based on the recommendation in the Vista UX guidelines that suggests an etched rectangle of height 1 for separators.

When static, this looks fine, but I've noticed that I get redrawing artifacts if I place this control in a window and resize it (via anchor, e.g.). I'm redrawing my border over my entire client rectangle's width, but it's like it isn't actually being painted. Enabling DoubleBuffered in HorizontalRule's constructor, or in the form that it's embedded in, doesn't seem to make a difference either.

What am I doing wrong?

Update:

Per the suggestion, I tried calling base.OnPaint last instead of first. I don't know what that would have changed, and it doesn't seem to have changed anything either.

Not drawing the background accomplished nothing useful. I still get the artifacting, but then I also don't get the background color so instead I saw image of whatever was underneath the horizontal line.

A: 

I would draw this on a bitmap then draw the bitmap instead of worrying about painting it each time.

Daniel A. White
What do you mean? Paint the border onto a bitmap once the first time the control is shown, then just stretch that bitmap across the width of the control?
Greg D
That could work, what i was referring to was caching it.
Daniel A. White
+1  A: 

Dont call base.OnPaint, or call it last (I cant recall now).

Also, try overriding the background paint method, so it does not call the base.

leppie
Not drawing the background would definitely be a start
Will Dean
Those steps accomplished nothing useful. :(
Greg D
+1  A: 

I can hack a solution that doesn't result in artifacting by overriding OnResize() to invalidate the entire control:

protected override void OnResize(EventArgs e)
{
    base.OnResize(e);

    this.Invalidate();
}

I'm not sure that this is the "right" solution, however.

Greg D
Ah, good spot :)
leppie