tags:

views:

564

answers:

3

I used the owner-drawn strategy on CMyListBox class which derives from CListBox. I only want the DrawItem() method to perform when I insert an item in the listbox. But the method is invoked many times. How can I change to invoke it whenever I need.

A: 

The DrawItem() method is called whenever there is a requirement to draw any given item in the listbox. If you do not respond to it you are likely to get a blank area in your list box, where the drawn data has been erased and you have not refreshed it. If you really do not think the drawing is necessary, you could do something like

void CMyListBox::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
   if (!m_DrawingEnabled)
     return;
}

Where m_DrawingEnabled is a member you maintain to stop unnecessary draws,

Shane MacLaughlin
When exactly would you think that DrawItem would be called and it NOT actually need to be re-rendered?
Aardvark
For example, I just want to draw the new item after I add it into the list box, or remove a certain item in the list box. But I don't want to draw it when I change the size of the list box.
I don't think a flag is going to help, if windows asks to redraw it most likely **needs** drawing. Adding a flag will just render nothing. It won't keep what was previously drawn.
Aardvark
+1  A: 

You could always cache the initial drawing by outputting the content to an in-memory bitmap and then drawing that, it does mean you need to track when something has changed so you can run the actual rending code agaain. It does save running through your render code everytime if there's a lot of it.

Kieron
A: 

I've done exactly what Kieron suggests by caching bitmaps, but only in very expensive rendering code. I actually have to keep multiple cached "states" depending on if an item is highlighted, disabled, normal, etc (this is for toolbar buttons, not listitem - but I think it applies). I only cache the pre-rendered image when I first need it - that way I only cache "states" that I actually need.

My drawing was pure GDI calls. Mostly bitmap manipulations and other drawing that just takes time, plus I was being redrawn much too often (for no good reason - long story).

Changing the fundimetals in the framework I was using (MFC and Stingray) was just not an option. The caching was a last resort after all other optimizations weren't good enough (damn slow virtual machines!!).

Normally drawing is fast enough to do when you're invalidated (DrawItem in this case). I would take a look at what exactly you're doing in DrawItem. I would look into caching data and calculations that are needed by rendering and not the rendering itself (eg the final bitmaps) unless there are no other options.

Also, I read the Vista rending is more optimized, they cache what you've drawn on your window to reduce the contain invalidate/redraw cycle when, for example, a window is moved from behind another.

Aardvark