I am using variable height owner-drawn ListBox using new Visual Studio 2005
Beta.
It appears to not repaint items in ListBox until I actually select them.
In the constructor of my ListBox I call the following code:

<code>
this.DrawMode = DrawMode.OwnerDrawVariable;
this.DrawItem += new DrawItemEventHandler(HandleDrawItem);
this.MeasureItem += new MeasureItemEventHandler(HandleMeasureItem);
this.HorizontalScrollbar = true;
this.MouseDown += new MouseEventHandler(HandleMouseDown);
this.MouseUp += new MouseEventHandler(HandleMouseUp);
this.SetStyle(ControlStyles.ResizeRedraw |
ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint, true);
this.UpdateStyles();
</code>

Then in the DrawItem and MeasureItem code I do the following:
<code>
public void HandleDrawItem(Object sender,DrawItemEventArgs e)
{
if (e.Index < 0) return;
e.DrawBackground();


//Draw control onto bitmap
Control ctrl = (Control)this.Items[e.Index];
//using (Image tmpImg = new Bitmap(ctrl.Bounds.Width,
ctrl.Bounds.Height))
//{
// using (Graphics g = Graphics.FromImage(tmpImg))
// {
// Utils.ControlPainter.PaintControl(g, ctrl);
// }

// ////map ctrl location to viewport coordinates
// //Point loc = ctrl.Location;
// ////top left of viewport corresponds to
// ////location of topCtrl
// //Control topCtrl = (Control)this.Items[this.TopIndex];
// //loc.Offset(-topCtrl.Location.X, -topCtrl.Location.Y);


// //g.TranslateTransform(loc.X, loc.Y);

// e.Graphics.DrawImage(tmpImg, e.Bounds);
//}
e.Graphics.DrawString("item: " + e.Index, this.Font,
Brushes.Blue, e.Bounds);

e.DrawFocusRectangle();

}

public void HandleMeasureItem(Object sender,MeasureItemEventArgs e)
{
if (e.Index >= this.Items.Count)
{
return;
}
Control ctrl = (Control)this.Items[e.Index];
ctrl.Location = nextLocation;
e.ItemHeight = ctrl.Height;
nextLocation.Y += e.ItemHeight;
e.ItemWidth = ctrl.Width;
HorizontalExtent = Math.Max(e.ItemWidth, HorizontalExtent);
}
</code>

However, the painting doesn't appear to be done until I actually select the
item.
Do I need to invalidate the whole listbox initially and then every time I
scroll?

RE: owner drawn ListBox repaint issues by dlyle

dlyle
Wed Jul 13 16:22:02 CDT 2005

I tried creating a new class called
OwnerDrawnListBoxPanel that contains a ListBox and
as the parent of that ListBox provides DrawItem and MeasureItem callbacks.
The repaint issue then went away. Perhaps this is due to the underlying win32
stuff -- if I remember correctly in win32 you have to have parent window
implement the draw item code unless you have message reflection.

So in short it's probably not recommended to subclass a given control and
attach event callbacks inside the constructor. I.e. don't call

this.DrawItem += ...

from within a ListBox derived class,
instead create a ListBox lb and call

lb.DrawItem += ...


"dlyle" wrote:

> I am using variable height owner-drawn ListBox using new Visual Studio 2005
> Beta.
> It appears to not repaint items in ListBox until I actually select them.
> In the constructor of my ListBox I call the following code:
>
> <code>
> this.DrawMode = DrawMode.OwnerDrawVariable;
> this.DrawItem += new DrawItemEventHandler(HandleDrawItem);
> this.MeasureItem += new MeasureItemEventHandler(HandleMeasureItem);
> this.HorizontalScrollbar = true;
> this.MouseDown += new MouseEventHandler(HandleMouseDown);
> this.MouseUp += new MouseEventHandler(HandleMouseUp);
> this.SetStyle(ControlStyles.ResizeRedraw |
> ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint |
> ControlStyles.AllPaintingInWmPaint, true);
> this.UpdateStyles();
> </code>
>
> Then in the DrawItem and MeasureItem code I do the following:
> <code>
> public void HandleDrawItem(Object sender,DrawItemEventArgs e)
> {
> if (e.Index < 0) return;
> e.DrawBackground();
>
>
> //Draw control onto bitmap
> Control ctrl = (Control)this.Items[e.Index];
> //using (Image tmpImg = new Bitmap(ctrl.Bounds.Width,
> ctrl.Bounds.Height))
> //{
> // using (Graphics g = Graphics.FromImage(tmpImg))
> // {
> // Utils.ControlPainter.PaintControl(g, ctrl);
> // }
>
> // ////map ctrl location to viewport coordinates
> // //Point loc = ctrl.Location;
> // ////top left of viewport corresponds to
> // ////location of topCtrl
> // //Control topCtrl = (Control)this.Items[this.TopIndex];
> // //loc.Offset(-topCtrl.Location.X, -topCtrl.Location.Y);
>
>
> // //g.TranslateTransform(loc.X, loc.Y);
>
> // e.Graphics.DrawImage(tmpImg, e.Bounds);
> //}
> e.Graphics.DrawString("item: " + e.Index, this.Font,
> Brushes.Blue, e.Bounds);
>
> e.DrawFocusRectangle();
>
> }
>
> public void HandleMeasureItem(Object sender,MeasureItemEventArgs e)
> {
> if (e.Index >= this.Items.Count)
> {
> return;
> }
> Control ctrl = (Control)this.Items[e.Index];
> ctrl.Location = nextLocation;
> e.ItemHeight = ctrl.Height;
> nextLocation.Y += e.ItemHeight;
> e.ItemWidth = ctrl.Width;
> HorizontalExtent = Math.Max(e.ItemWidth, HorizontalExtent);
> }
> </code>
>
> However, the painting doesn't appear to be done until I actually select the
> item.
> Do I need to invalidate the whole listbox initially and then every time I
> scroll?
>