kmote
kmote

Reputation: 16715

Why does this single line of code cause Visual Studio to crash?

With one line of code, I can cause VS2012 to crash consistently. (By "crash" I mean when I hit Build, Visual Studio hangs indefinitely and I have to kill it from Task Manager.) Here's the code (in a custom user control):

public class TransparentPanel : System.Windows.Forms.Panel
{
    protected override void OnPaintBackground(PaintEventArgs pe)
    {
        this.Invalidate(); //this is the offending line
    }
}

To reproduce the problem, create a control based on the above code and add it to a Windows Form; then try to Build Solution. "Build started..." will be displayed in the Status Bar and then VS will immediately and permanently freeze up. I tried troubleshooting, using devenv /log, but the Activity Log displayed no errors or warnings. So my question is, why is this code fatal to the C# compiler? (It causes problems in the IDE too. For example, after adding this transparent control, the Properties pane becomes frozen whenever the Form Designer is open.)

Side question: should this bug be reported to Microsoft? If so, how? (I tried to submit the bug on the MS Connect site, but apparently they are only accepting bugs for VS2013.)


[If you want to know the background of why I was trying to use that line, read on.]

I created a custom (Windows Forms) control for an application. (I was trying to create a control with a partially transparent image, whose location could be changed through mouse interactions.) I used the following code, which gave me the image (on a panel) with the transparency I was looking for:

public class TransparentPanel : System.Windows.Forms.Panel
{
    public Image Image { get; set; }

    protected override void OnPaint(PaintEventArgs pe)
    {
        Rectangle rect = new Rectangle(this.Location, this.Size);
        if (Image != null)
            pe.Graphics.DrawImage(Image, this.DisplayRectangle);
    }

    protected override void OnPaintBackground(PaintEventArgs pe)
    {
        //this.Invalidate();
        Brush brush = new SolidBrush(Color.FromArgb(0, 0, 0, 0));
        pe.Graphics.FillRectangle(brush, pe.ClipRectangle);
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x20; // WS_EX_TRANSPARENT       
            return cp;
        }
    }
}

However, the transparency doesn't "stick". When the control is relocated, for example with this event handler:

    private void transparentPanel1_MouseClick(object sender, MouseEventArgs e)
    {
        int y = this.transparentPanel1.Location.Y ;
        int x = this.transparentPanel1.Location.X ;
        this.transparentPanel1.Location = new System.Drawing.Point(x-5, y-5);
    }

...the transparent portion of the control retains the same background it had when it was first painted. (This can only be seen if another control is placed behind it. Sorry, hard to describe.) So I was attempting to use the Invalidate() to repaint the control, and therefore, repaint the transparent portion to match whatever was behind the control after the relocation. This is when the VS bug appeared. (Actually I didn't notice the bug right away, so it was rather excruciating to isolate the offending line of code.)

Upvotes: 2

Views: 387

Answers (1)

Ed Swangren
Ed Swangren

Reputation: 124632

public class TransparentPanel : System.Windows.Forms.Panel
{
    protected override void OnPaintBackground(PaintEventArgs pe)
    {
        this.Invalidate(); //this is the offending line
    }
}

That is akin to an infinite loop.

When you panel repaints, your handler is called... and you tell it to invalidate itself... which causes a repaint... which calls your handler... etc.

The designer loses its mind. You don't need or want to invalidate the control from within OnPaintBackground, unless it is conditional (still rare).

Upvotes: 9

Related Questions