tags:

views:

362

answers:

4

How many rows should be in the (main) buffer of a virtual Listview control?

I am witting an application in pure 'c' to the Win32 API. There is an ODBC connection to a database which will retrieve the items (actually rows).

The MSDN sample code implies a fixed size buffer of 30 for the end cache (Which would almost certainly not be optimal). I think the end cache and the main cache should be the same size.

My thinking is that the buffer should be more than the maximum number of items that could be displayed by the list view at one time. I guess this could be re-calculated each time the Listivew was resized?

Or, is it just better to go with a large fixed value. If so what is that value?

+1  A: 

Use the ListView_ApproximateViewRect (or the LVM_APPROXIMATEVIEWRECT message) to get the view rect height.

Use the ListView_GetItemRect (or the LVM_GETITEMRECT message) to get the height of an item.

Divide the view rect height by the height of an item to get the number of items that can fit in your view. Do this calculation on each size event.

Then create your buffer accordingly.

Brian R. Bondy
+1  A: 

The LVN_ODCACHEHINT notification message will let you know how many items it is going to ask. This could help you in deciding how big your cache should be.

Lars Truijens
A: 

@Brian R. Bondy Thanks for the explicit help for how to do get the number of items. In fact I was all ready working my way to understanding that it could be done (for list or report view) with ListView_GetCountPerPage, and I would use you way to get it for for the others, though I don't need the ListView_ApproximateViewRect since I will all ready know the new size of the ListView.

@Lars Truijens I am already using the LVN_ODCACHEHINT and had though about using that to set the buffer size, however I need to read to the end of the SQL data to find the last item to get the number of rows returned from ODBC. Since that would be the best time to fill the 'end cache' I think I have to set up the number of items (and therefore fill the buffer) before we get a call to LVN_ODCACHEHIN.

I guess my real question is one of optimization for which I think Brian hinted at the answer. The amount of overhead in trashing your buffer and reallocating memory is smaller than the overhead of going out to the network and doing an ODBC read, some make the buffer fairly small and change it often rather.

Is this right?

I have done a little more playing around, and it seems that think that LVN_ODCACHEHINT generally fills the main buffer correctly, and only misses if a row (in report mode) is partially visible.

So I think the answer for the size of the cache is: The total number of displayed items, plus one row of displayed items (since in the icons views you have multiple items per row).

You would then re-read the cache with each WM_SIZE and LVN_ODCACHEHINT if either had a different begin and end item number.

David L Morris
A: 

The answer would seem to be: (Or a random collection of notes as I fiddle around with ideas)

As a general answer for buffers: Start with some amount, in this case a screen full (I add an extra row in case the next is partially uncovered), and then every time the screen is scrolled, double the buffer size (up to the point before you run out of memory).

Which would seem to be wrong. As it turns out, most ways of loading data are all ready buffered. ODBC calls of File I/O. Pretty much anything that isn't that I can think off is either in memory or is recalculated on the fly. This means the answer really is: take the values provided in LVN_ODCACHEHINT (and add 1 either side - this just seems to work faster if you don't have an integral height).

David L Morris