How to remove listbox flashing

A

Andrus

1. Run code
2. Resize window

Observed:

Listbox flashes during resize.

How to remove this flashing ?

Andrus.


using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Drawing;

public class Test
{
static void Main()
{
Application.Run(new ReportDialogForm());
}
}

class ReportDialogForm : Form
{

public ReportDialogForm()
{
tabControl1 = new TabControl();
tabPage1 = new TabPage();
reportListBox = new ListBox();
tabControl1.Anchor = ((AnchorStyles)((((AnchorStyles.Top |
AnchorStyles.Bottom)
| AnchorStyles.Left)
| AnchorStyles.Right)));
tabControl1.Controls.Add(tabPage1);
tabControl1.Location = new Point(0, 0);
tabControl1.Padding = new Point(0, 0);
tabControl1.SelectedIndex = 0;
tabControl1.Size = new Size(591, 296);
tabControl1.TabIndex = 0;
tabPage1.Controls.Add(reportListBox);
tabPage1.Location = new Point(4, 29);
tabPage1.Margin = new Padding(0);
tabPage1.Size = new Size(583, 263);
tabPage1.TabIndex = 0;
tabPage1.Layout += new LayoutEventHandler(tabPage1_Layout);
reportListBox.Anchor = AnchorStyles.None;
reportListBox.Size = new Size(287, 384);
reportListBox.TabIndex = 1000;
ClientSize = new Size(588, 292);
Controls.Add(tabControl1);

for (int i = 0; i < 100; i++)
reportListBox.Items.Add( "MMMMMMMMMMMMMMMMMMMMMM");

Load += new EventHandler(ReportDialogForm_Load);
}

void ReportDialogForm_Load(object sender, EventArgs e)
{
StartPosition = FormStartPosition.Manual;
Location = new Point(10, 10);
ClientSize = new Size(400, 400);
}



void tabPage1_Layout(object sender, LayoutEventArgs e)
{
SuspendLayout();
int height = 100;
reportListBox.Top = height;
reportListBox.Height = tabPage1.Height - height;
reportListBox.Width = tabPage1.Width / 2;
reportListBox.Left = 0;
ResumeLayout();
}

TabControl tabControl1;
TabPage tabPage1;
ListBox reportListBox;
}
 
B

Barry Kelly

Andrus said:
1. Run code
2. Resize window

Observed:

Listbox flashes during resize.

How to remove this flashing ?

A typical solution for this is double buffering.

Try setting 'DoubleBuffered = true;' in your form's constructor or other
initialization event.

DoubleBuffered is a protected property, so you can't e.g. set the
listbox's version.

-- Barry
 
A

Andrus

Barry,
A typical solution for this is double buffering.

Try setting 'DoubleBuffered = true;' in your form's constructor or other
initialization event.

DoubleBuffered is a protected property, so you can't e.g. set the
listbox's version.

thank you.
I added DoubleBuffered = true; as first line in constructor:

public ReportDialogForm()
{
DoubleBuffered = true;

However, listbox still blinks on resize.
Adding Doublebuffered did not make any difference.

Andrus.
 
B

Barry Kelly

Andrus said:
Barry,


thank you.
I added DoubleBuffered = true; as first line in constructor:

public ReportDialogForm()
{
DoubleBuffered = true;

Sorry, I didn't read your post closely enough - the problem is actually
caused by the TabControl; the form's DoubleBuffered won't help you
(actually, the form's DoubleBuffered would have only affected drawing on
the form directly, not child controls, in any case).

There is a new-ish Windows style parameter that can be specified to
CreateWindowEx that eliminated this flicker on Windows XP and up. You
can get .NET to apply this style (WS_EX_COMPOSITED) by overriding the
protected CreateParams property on your form. Try this:

protected override CreateParams CreateParams
{
get
{
CreateParams result = base.CreateParams;
result.ExStyle |= 0x02000000; // WS_EX_COMPOSITED
return result;
}
}

This works because WS_EX_COMPOSITED forces the whole control (the form
in this case) to use double-buffering throughout all its child controls.
You can read more about WS_EX_COMPOSITED here:

http://msdn.microsoft.com/en-us/library/ms632680(VS.85).aspx

-- Barry
 
J

Jeff Gaines

There is a new-ish Windows style parameter that can be specified to
CreateWindowEx that eliminated this flicker on Windows XP and up. You
can get .NET to apply this style (WS_EX_COMPOSITED) by overriding the
protected CreateParams property on your form. Try this:

protected override CreateParams CreateParams
{
get
{
CreateParams result = base.CreateParams;
result.ExStyle |= 0x02000000; // WS_EX_COMPOSITED
return result;
}
}

This works because WS_EX_COMPOSITED forces the whole control (the form
in this case) to use double-buffering throughout all its child controls.
You can read more about WS_EX_COMPOSITED here:

I tried this to avoid the flashing problem but found it stopped the form
loading and seemed to stop some controls being drawn. Instead I tried this:

protected override void WndProc(ref Message m)
{
if (m.Msg == (int)WM.WM_CREATE)
{
this.CreateParams.ExStyle |= 0x02000000;
}
base.WndProc(ref m);
}

This is on XP Pro x64 - it doesn't stop the form loading but it's hard to
tell if it has any effect. Is it a suitable alternative?
 
A

Andrus

Barry,
There is a new-ish Windows style parameter that can be specified to
CreateWindowEx that eliminated this flicker on Windows XP and up. You
can get .NET to apply this style (WS_EX_COMPOSITED) by overriding the
protected CreateParams property on your form.

Thank you.
I added your code to sample and tested with Vista SP1
Flicker has been decreased but it still occurs when running sample and
resizing the form.

How to remove flickering fully ?

Is it safe to add this code to form's base class or is it better to subclass
ListBox and set ListBox DoubleBuffered property ?

Andrus.
 
N

not_a_commie

I think you should move to WPF. The flickering in the listbox there is
hardly noticeable in XP and it's gone in Vista. The double buffering
in the WinForms controls is crap. Just go look at the number of bugs
on it at MS Feedback. I've never got it to work right in any WinForms
control that I didn't paint entirely myself. And of course none of
those bugs will be fixed as WinForms is a very dead project.
 
A

Andrus

I think you should move to WPF. The flickering in the listbox there is
hardly noticeable in XP and it's gone in Vista. The double buffering
in the WinForms controls is crap. Just go look at the number of bugs
on it at MS Feedback. I've never got it to work right in any WinForms
control that I didn't paint entirely myself.

I'm using DataGridView in virtual mode.
I havent found any way how to implement similar thing in WPF.
Also WPF is not supported in MONO.
And of course none of
those bugs will be fixed as WinForms is a very dead project.

For DataGridView VirtualMode column resize bug I reported I got feedback
that they think about fixing it. Unfortunately, this is not fixed is SP1

Andrus.
 
B

Barry Kelly

Jeff said:
On 15/08/2008 in message <[email protected]>
Barry Kelly wrote:
protected override void WndProc(ref Message m)
{
if (m.Msg == (int)WM.WM_CREATE)
{
this.CreateParams.ExStyle |= 0x02000000;
}
base.WndProc(ref m);
}

The above code has no effect. CreateParams is called by the WinForms
library (i.e. an ancestor like Control) when it wants to find out what
to pass to the underlying native API CreateWindowEx. The property plays
no role outside of window creation and recreation. Every time you call
it, you get a new instance, which is not tethered to the control.

I don't know what caused your Window to fail creation, sorry. Have you
tried breaking into it in the debugger, to see what was on the stack?

You could try googling the relevant Windows style combined with
deadlock, hang, etc.

-- Barry
 
B

Barry Kelly

not_a_commie said:
I think you should move to WPF. [...] And of course none of
those bugs will be fixed as WinForms is a very dead project.

Yes, that's probably why the .winfx groups are so active... :)

-- Barry
 
B

Barry Kelly

Andrus said:
Barry,


Thank you.
I added your code to sample and tested with Vista SP1
Flicker has been decreased but it still occurs when running sample and
resizing the form.

It is completely gone for me using your sample with my addition under XP
SP3.

I have a Vista machine here, but it's at the end of a network cable and
I only connect via RDP and ssh, so I can't test the display.
Is it safe to add this code to form's base class or is it better to subclass
ListBox and set ListBox DoubleBuffered property ?

I've told you all I know, sorry!

-- Barry
 
J

Jeff Gaines

The above code has no effect. CreateParams is called by the WinForms
library (i.e. an ancestor like Control) when it wants to find out what
to pass to the underlying native API CreateWindowEx. The property plays
no role outside of window creation and recreation. Every time you call
it, you get a new instance, which is not tethered to the control.

OK, thanks Barry.
I don't know what caused your Window to fail creation, sorry. Have you
tried breaking into it in the debugger, to see what was on the stack?

It has several classes many of which have their own WndProc, seems to be
going round in circles on the WM_Paint command.
You could try googling the relevant Windows style combined with
deadlock, hang, etc.

What I would really like to do is go back to plain old C, life was so much
simpler :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top