custom Listbox double buffering

Posted on 2004-09-11
Last Modified: 2012-06-27
I'm using a custom listbox (which uses System.Windows.Forms.ListBox) and am trying to double buffer it in order to stop the accursed flicker.  My test case uses 4 different items in the list.  In OnDrawItem, I create a new Bitmap of the appropriate size and then create a Graphics from the Bitmap.  Then I "draw" the correct string from the event.  Finally, I draw the Bitmap to the ListBox and then dispose of the graphics objects and bitmap (I've tried without disposing them, with the same results).  Only the first item gets drawn.  Debug.WriteLine code tells me that OnDrawItem is getting called with the appropriate values (text, x & y location, etc.).  As a last ditch effort, I put code into the OnDrawItem that looped through all 4 items, drawing each one.  This resulted in 4 items getting drawn, all with the same, first value (and the expected issues involving improper invalidation... it was just a test, after all).  What have I done wrong?  Who did I wrong in a past life?

protected override void OnDrawItem(DrawItemEventArgs e)
// Verify index is valid before painting
if (e.Index >= 0)
for(int i=0;i<4;i++)
    Bitmap bmp = GetIndexBitmap(i);//e.Index);
    Graphics graphics = CreateGraphics();
    graphics.DrawImage(bmp, e.Bounds.X, e.Bounds.Y);
    //Debug.WriteLine("index:"+e.Index+"  x="+rectItem.X+"  y="+rectItem.Y);

protected Bitmap GetIndexBitmap(int nIndex)
Rectangle r = GetItemRectangle(nIndex);
Bitmap offScreenBmp = new Bitmap(r.Width, r.Height);
Graphics offScreenDC = Graphics.FromImage(offScreenBmp);
string sItemText = (string)Items[nIndex];
Debug.WriteLine("index:"+nIndex+"  Items[index]:"+Items[nIndex]+"  str="+sItemText);

pCurrentBrush = m_NormalTextSolidBrush;

// Clear the background for fresh drawing
//offScreenDC.FillRectangle(m_BackSolidBrush, e.Bounds);

// Draw text
  offScreenDC.DrawString(sItemText, Font, pCurrentBrush, (float)(r.Left + m_nIndentLeft),(float)(r.Top + m_nIndentTop));

Rectangle rectItem = GetItemRectangle(nIndex);
offScreenDC.DrawImage(offScreenBmp, r.X, r.Y);
return offScreenBmp;

Question by:rwinkler
  • 2
LVL 23

Accepted Solution

rama_krishna580 earned 250 total points
ID: 12036793
LVL 10

Assisted Solution

ptmcomp earned 250 total points
ID: 12039784
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;

namespace TestDoubleBuffer
      public class DoubleBufferListView: ListView
            public const int WM_PAINT = 0x000F;
            public const int WM_PRINT = 0x0317;
            public const int WM_PRINTCLIENT = 0x0318;
            public const int WM_ERASEBKGND = 0x0014;

            public const int PRF_CHECKVISIBLE = 0x00000001;
            public const int PRF_NONCLIENT    = 0x00000002;
            public const int PRF_CLIENT       = 0x00000004;
            public const int PRF_ERASEBKGND   = 0x00000008;
            public const int PRF_CHILDREN     = 0x00000010;
            public const int PRF_OWNED        = 0x00000020;

            public static extern int SendMessage(          
                  IntPtr hWnd,
                  uint Msg,
                  IntPtr wParam,
                  IntPtr lParam

            public DoubleBufferListView(): base()
                  SetStyle(ControlStyles.DoubleBuffer, false);
                  SetStyle(ControlStyles.Opaque, true);
                  //SetStyle(ControlStyles.UserPaint, true);

            private Bitmap bufferBmp = null;
            protected Bitmap GetBitmap(Graphics g)
                  if ((bufferBmp == null) || (bufferBmp.Size != ClientRectangle.Size))
                        bufferBmp = new Bitmap(ClientRectangle.Width, ClientRectangle.Height, g);
                  return bufferBmp;

            protected override void WndProc(ref Message m)
                  switch (m.Msg)
                        case WM_PAINT:
                              using(Graphics gWin = Graphics.FromHwnd(m.HWnd))
                                    Bitmap bmp = GetBitmap(gWin);
                                    using (Graphics gBmp = Graphics.FromImage(bmp))
                                          IntPtr hDc;
                                          gBmp.FillRectangle(SystemBrushes.Window, 0, 0, bmp.Width, bmp.Height);
                                          hDc = gBmp.GetHdc();

                                          m.WParam = hDc;
                                          base.WndProc(ref m);
                                          m.WParam = IntPtr.Zero;
                                          //InvokePaint(this, new PaintEventArgs(gBmp, ClientRectangle));
                                          //OnPaint(new PaintEventArgs(gBmp, ClientRectangle));
                                          //Message printMessage = Message.Create(m.HWnd, WM_PRINTCLIENT, gBmp.GetHdc(), new IntPtr(PRF_CLIENT | PRF_ERASEBKGND));
                                          //SendMessage(m.HWnd, WM_PRINTCLIENT, hDc, new IntPtr(PRF_CLIENT | PRF_ERASEBKGND));
                                          //gBmp.FillRectangle(SystemBrushes.Desktop, 0, 0, bmp.Width, bmp.Height);
                                    gWin.DrawImageUnscaled(bmp, 0, 0, bmp.Width, bmp.Height);
                              m.Result = IntPtr.Zero;
                        case WM_ERASEBKGND :
                              m.Result = new IntPtr(1);
                              base.WndProc(ref m);
LVL 10

Expert Comment

ID: 12039794
Oops the commented lines are not necessary... ;o)

Featured Post

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: Ivo
C# And Nullable Types Since 2.0 C# has Nullable(T) Generic Structure. The idea behind is to allow value type objects to have null values just like reference types have. This concerns scenarios where not all data sources have values (like a databa…
Summary: Persistence is the capability of an application to store the state of objects and recover it when necessary. This article compares the two common types of serialization in aspects of data access, readability, and runtime cost. A ready-to…
In a recent question ( here at Experts Exchange, a member asked how to add page numbers to a PDF file using Adobe Acrobat XI Pro. This short video Micro Tutorial sh…
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…

785 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question