How to selectively invalidate an owner’s canvas with a TListBox sheet?

I have an owner drawn by a TListBox (lbVirtualOwnerDraw) whose contents are updated dynamically (there can be up to 10 updates per second). The list box can have up to 300 items at a time. Each element can contain about 5 lines of text and an image associated with it. Whenever an item is updated, I have to update (or invalidate) the TListBox so that the ListBoxDrawItem object is called by the VCL base. But this adversely affects overall performance due to excessive repainting. So my question is:

  • Is there a way to invalidate only a small part of the canvas that contains a picture of one element or one of its parts? (for example, a rectangle containing one line of text or a bitmap).

  • How can we handle such a selective invalidator in a Draw Item? If it were possible to pass an integer as part of Refresh or invalidate, I could use this in DrawItem to determine what needs to be updated.

  • Is there a way to find that an element is visible at all on a TListBox (by index)?

Thanks in advance!

+4
source share
1 answer

You can use the InvalidateRect api to invalidate part of the window. To find the area the item is in, you can use the ItemRect method in the ListBox. For example, to invalidate the 4th element:

 var R: TRect; begin R := ListBox1.ItemRect(3); InvalidateRect(ListBox1.Handle, @R, True); end; 

(or "False" as "bErase" from "InvalidateRect", see its documentation). To invalidate only the bitmap or text, change the rectangle accordingly before moving on to InvalidateRect.


You cannot submit an index or any user data for updating or cancellation. In the drawing routine, you must define the subject that you are drawing, depending on the location, or use global variables if absolutely necessary. But you will not need this, if you invalidate a part of only one element, OnDrawItem will be called only for this element. And in any case, don’t worry too much about drawing invalid elements, since there will be no actual drawing outside the update area, you will not have a significant performance improvement (see the third paragraph here ).


To determine if an element is visible, you start from the first visible element at the top and add the heights of consecutive elements to the ClientHeight level of the control. The top element is in TopIndex . If the height of the elements is fixed, you already know how many elements are visible the most. If not, you need to let them down.

+10
source

Source: https://habr.com/ru/post/1346834/


All Articles