One Unified Global Perspective
Communications with a Global Perspective
Home
Intro
Contact Us
Voice over IP
PBX Solutions
Services
Support
Glossary
Open Source
Blog
Forum

WebMail





2007 Apr 01 - Sun

Stopping Screen Flicker in C#/.NET ListView Controls

The automated trading solution I'm building is starting out being a manual trading affair. I figure that once I can prove the algorithm manually, then I can probably cast the manual rules I use in stone and automate them. As such, I've been putting an user-interface into the software. Part of the interface uses a ListView. The only draw back to using this tool is the amount of flicker it presents.

A number of sites highly ranked on the search sites offer up solutions for resolving the Screen Flicker problem in C#/.NET v2.0 applications. None of them catch a key feature that makes it so simple (or at least it took me a whilei to catch on). Most of the solutions, such as the solution presented by c pound use the technique of inheriting from the basic ListView. Even that is a bit too much like work.

Franceso's Blog does a fairly large song and dance to resolve ListView screen flicker by manually copying stuff back and forth. Nope, that one isn't very good either.

An article called Painting Techniques using Windows Forms for the Microsoft .NET Framework shows up some good manaul ways of using double buffering to provide flicker free drawing. Another related background article is at Jeremy Kuhne's Blog. It offers up some good points, but still not the main point.

A related question at the The Scripts Developer Network was posted by a chap who, coincidentally, is doing some sort of stock ticker ap. The solution also references the technique of derivation and setting 'DoubleBuffered' to true. Nope, not quite what I was looking for. That article did point to a commercial grade ListView replacement called Glacial ListView. Looks good, but I'm looking for a free solution.

And the winner is: a page from the MSDN ControlStyles Enumeration. The secret ingredient for eliminating ListView Screen Flicker is to put the ControlStyle initialization flags in to the form's form_load override.

Here is a sample with all the test stuff in it:

    private void frmTradeFrame_Load( object sender, EventArgs e ) {

      this.SetStyle(
        //ControlStyles.UserPaint | 
        ControlStyles.AllPaintingInWmPaint |
        //ControlStyles.Opaque |
        ControlStyles.OptimizedDoubleBuffer,
        true);
      //this.DoubleBuffered = true;
      this.SetStyle(ControlStyles.EnableNotifyMessage, true);
      SetStyle(ControlStyles.ResizeRedraw, true);
    }

    protected override void OnNotifyMessage( Message m ) {
      if (m.Msg != 0x14) {
        base.OnNotifyMessage(m);
      }
    }

When I'm done, it should all boil down to this:

    private void frmTradeFrame_Load( object sender, EventArgs e ) {

      this.SetStyle(
        ControlStyles.AllPaintingInWmPaint |
        ControlStyles.OptimizedDoubleBuffer,
        true);
      SetStyle(ControlStyles.ResizeRedraw, true);
    }

Or maybe even this:

    private void frmTradeFrame_Load( object sender, EventArgs e ) {

      this.DoubleBuffered = true;
      }
    }

... since one of the documents I referenced indicated that DoubleBuffered sets those ControlStyles flags for you.

After all that ranting and raving, it didn't work. The following mods do. The key requirement is that you do have to override the ListView form, you can can't just override the containing form.

    public frmLV() {

      this.SetStyle(
        ControlStyles.AllPaintingInWmPaint |
        ControlStyles.Opaque |
        ControlStyles.OptimizedDoubleBuffer,
        true);
      this.SetStyle(ControlStyles.EnableNotifyMessage, true);
      SetStyle(ControlStyles.ResizeRedraw, true);
      SetStyle(ControlStyles.ResizeRedraw, true);
    }

    protected override void OnNotifyMessage( Message m ) {

      if (m.Msg == 0x14) m.Msg = 0x00;
      //if (m.Msg != 0x14) {
      base.OnNotifyMessage(m);
      //}
    }

The bonus feature that appears to reduce cpu utilization a bit is:

    // http://msdn.microsoft.com/msdnmag/issues/06/03/WindowsFormsPerformance/
   lvBook.Invalidate(lvi.GetBounds(ItemBoundsPortion.Entire),false);

If you've read this far, the simple solution to the problem, if you get to the low level code, according to a link at a Microsoft MSDN List is to "filter out the erase background message". Therefore, in the main draw code, one needs to paint the background text all in one fell swoop.



Blog Content ©2009
Ray Burkholder
All Rights Reserved
ray@oneunified.net
(441) 505 7293
Available for Contract Work
Resume

RSS: Click to see the XML version of this web page.

twitter
View Ray 
Burkholder's profile on LinkedIn
technorati
Add to Technorati Favorites



April
Su Mo Tu We Th Fr Sa
1
         


Main Links:
Monitoring Server
SSH Tools
QuantDeveloper Code

Special Links:
Frink

Blog Links:
Sergey Solyanik
Marc Andreessen
HotGigs
Micro Persuasion
... Reasonable ...
Chris Donnan
BeyondVC
lifehacker
Trader Mike
Ticker Sense
HeadRush
TraderFeed
Stock Bandit
The Daily WTF
Guy Kawaski
J. Brant Arseneau
Steve Pavlina
Matt Cutts
Kevin Scaldeferri
Joel On Software
Quant Recruiter
Blosxom User Group
Wesner Moise
Julian Dunn
Steve Yegge
Max Dama

2007
Months
Apr




Mason HQ

Disclaimer: This site may include market analysis. All ideas, opinions, and/or forecasts, expressed or implied herein, are for informational purposes only and should not be construed as a recommendation to invest, trade, and/or speculate in the markets. Any investments, trades, and/or speculations made in light of the ideas, opinions, and/or forecasts, expressed or implied herein, are committed at your own risk, financial or otherwise.