0

I have to disable the OnPaintBackground on my TableLayoutPanel to remove flickering caused from the background being drawn first(because I am drawing on the TLP with the paint method, and yes I need a TLP because it contains many controls for a purpose). So my code is as follows:

    public static bool FlickerPanel = false;
    public class FlickerTableLayoutPanel : TableLayoutPanel
    {
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            if (FlickerPanel)
                base.OnPaintBackground(e);
        }
    }

Then in my paint method I have it draw it's own background. So during runtime it is fine.

Edit: I discovered the root of the problem. By overriding the OnPaintBackground it disables whatever code is making the designer draw the background. If I remove the override all together it doesn't have the graphical glitch.

        protected override void OnPaintBackground(PaintEventArgs e)
        {
                base.OnPaintBackground(e);
        }

Even this above code disabled the Design view rendering and causes graphical glitches. Any help much appreciated!

CodeCamper
  • 6,609
  • 6
  • 44
  • 94
  • You can't just skip OnPaintBackground, that's where TLP draws itself. Add the e.Graphics method calls you want to that method after the base call. If that is still too noticeable then add a constructor and set the DoubleBuffered property to true. – Hans Passant Jun 19 '13 at 08:51
  • After a little research I think the DoubleBuffered property suggested by Hans Passant will do the trick. – Romano Zumbé Jun 19 '13 at 09:07
  • @HansPassant Awesome! The DoubleBuffered property does work. So I put `public TLP(){ base.DoubleBuffered = true; }` and it worked! Is this the same thing as overriding the default constructor? Is there something in the original default constructor that I should add here? – CodeCamper Jun 19 '13 at 17:44

4 Answers4

4

I also had problems detecting whether my form was in design mode. I solved it as follows:

Firstly, I had to write an IsDesignMode() method:

public static bool IsDesignMode(Control control)
{
    if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)  // Initial quick check.
    {
        return true;
    }

    while (control != null)
    {
        System.ComponentModel.ISite site = control.Site;

        if ((site != null) && (site.DesignMode))
            return true;

        control = control.Parent;
    }

    return false;
}

I put that method in a shared library assembly (namespace "Windows.Forms.Utilities" in the example below), since I use it in a lot of projects.

Then for each user or custom control where I need to know if it's in design mode, I have to add a private bool _isDesignMode field and override OnHandleCreated() as follows:

protected override void OnHandleCreated(EventArgs e)
{
    base.OnHandleCreated(e);
    _isDesignMode = Windows.Forms.Utilities.IsDesignMode(this);
}

Then I can use _isDesignMode wherever I need to.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • Nice code, definitely will add this to the arsenal. Sadly I have discovered that the problem occurs even if I remove the `if` all together. Just by overriding OnPaintBackground even passing it to the original base it still produces the same graphical glitch. – CodeCamper Jun 19 '13 at 07:55
  • As far as I know every control has a protected property called `DesignMode`, why don't just use that instead? – King King Jun 19 '13 at 07:56
  • @KingKing because it doesn't always work properly for nested controls. [See here for example](http://stackoverflow.com/questions/34664/designmode-with-controls/708594#708594) – Matthew Watson Jun 19 '13 at 08:00
  • @MatthewWatson thanks, I can understand your code, if that's true as you said, this seems not easy to know if don't have any experience with it – King King Jun 19 '13 at 08:07
  • Why would just overriding the BackgroundPaint disable the designer code to display it even if I then proceed with the base original? Can I add the BackGroundPaint designer code to my overridden method? – CodeCamper Jun 19 '13 at 08:23
  • @CodeCamper It doesn't make sense does it? It should make no difference if all you are doing is calling the base method. – Matthew Watson Jun 19 '13 at 08:27
  • @MatthewWatson Shouldn't calling the original base method contain all the same code? As I did in my above code I added to my question on the bottom? I might have to check this tomorrow and come back here maybe it is some sort of caching/updating issue with Visual Studio 2010. – CodeCamper Jun 19 '13 at 08:29
  • @CodeCamper Yes it should. It makes no sense that simply overriding `OnPaintBackground()` and calling the base method would break it. – Matthew Watson Jun 19 '13 at 08:33
  • I am not exactly sure what code is doing what now. Apparently the designer will not update the code unless I actually restart Visual Studio entirely. Some sort of Caching/Updating issue. I'll be back tomorrow hopefully your code will work perfectly. – CodeCamper Jun 19 '13 at 08:35
  • @CodeCamper Try closing the project and then delete the ".suo" file and the "bin" and "obj" folders, then reopen and rebuild. Sometimes the ".suo" file gets corrupted. (It's used to cache things like Form data for the Form Designer) – Matthew Watson Jun 19 '13 at 08:37
1

You could surround the code in the OnPaintBackground method with an if statement to detect if your in design time like this:

if (System.ComponentModel.LicenseManager.UsageMode ==
System.ComponentModel.LicenseUsageMode.Designtime)
Romano Zumbé
  • 7,893
  • 4
  • 33
  • 55
  • This is cool code. Sadly after trying this wonderful code I have discovered this behavior is happening regardless. – CodeCamper Jun 19 '13 at 07:42
  • @CodeCamper It could be because that test doesn't always work for nested controls. – Matthew Watson Jun 19 '13 at 07:52
  • @MatthewWatson but I remove the `if` check all together and just runt the base class as I did in the bottom of my question it still doesn't work. I don't even know where to begin to resolve this as I never made code for the designer before. – CodeCamper Jun 19 '13 at 08:31
1

I just wanted to contribute my slight upgrade to the solution that @matthew-watson provided. As an extension method, the syntax becomes a bit more pleasing to read.

public static partial class ExtensionMethods
{
    public static bool IsInDesignMode(this Control source)
    {
        var result = LicenseManager.UsageMode == LicenseUsageMode.Designtime;

        while (result == false && source != null)
        {
            result = source.Site != null && source.Site.DesignMode;

            source = source.Parent;
        }

        return result;
    }
}

and used like this

protected override void OnPaintBackground(PaintEventArgs pevent)
{
    if (this.IsInDesignMode())
    {
        base.OnPaintBackground(pevent);
    }
}
pjs
  • 2,601
  • 1
  • 20
  • 24
0

just do nothing onPaintBackground() function. Its prevent backgroundImage to be drawn and should fix the flickering.

protected override void OnPaintBackground(PaintEventArgs e)
{
}
Tobia Zambon
  • 7,479
  • 3
  • 37
  • 69
Faruk
  • 5,438
  • 3
  • 30
  • 46