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.