?
Solved

custom Listbox double buffering

Posted on 2004-09-11
3
Medium Priority
?
609 Views
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)
{
base.OnDrawItem(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);
    graphics.Dispose();
    bmp.Dispose();
  }
}
}


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);
offScreenDC.Dispose();
return offScreenBmp;
}

}
}
0
Comment
Question by:rwinkler
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
3 Comments
 
LVL 23

Accepted Solution

by:
rama_krishna580 earned 1000 total points
ID: 12036793
0
 
LVL 10

Assisted Solution

by:ptmcomp
ptmcomp earned 1000 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;

            [DllImport("User32.DLL")]
            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.ReleaseHdc(hDc);
                                          //gBmp.FillRectangle(SystemBrushes.Desktop, 0, 0, bmp.Width, bmp.Height);
                                    }
                                    gWin.DrawImageUnscaled(bmp, 0, 0, bmp.Width, bmp.Height);
                              }
                              m.Result = IntPtr.Zero;
                              break;
                        case WM_ERASEBKGND :
                              m.Result = new IntPtr(1);
                              break;
                        default:
                              base.WndProc(ref m);
                              break;
                  }
            }
      }
}
0
 
LVL 10

Expert Comment

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

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Introduction Although it is an old technology, serial ports are still being used by many hardware manufacturers. If you develop applications in C#, Microsoft .NET framework has SerialPort class to communicate with the serial ports.  I needed to…
Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …
Suggested Courses

800 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