[1/2] comctl32: Implement highlighting (marquee) selection support in listview

Nikolay Sivov bunglehead at gmail.com
Mon Sep 14 15:53:52 CDT 2009

Owen Rudge wrote:
> Hi Nikolay,
>> Why do you need this restoring code?
> I tried to replicate the way that Windows did the selections. Testing 
> various manners of selection with Windows Explorer, that code was 
> needed for a relatively specific scenario:
> If you're starting a selection box with some items already selected 
> and Shift is pressed, then the items should, as you say, remain 
> selected. If you then highlight some different items, but then 
> un-highlight them before releasing the mouse button, the original 
> items should remain selected. However, if in that time you highlight 
> some of the already highlighted items, and then unhighlight them, they 
> should not remain highlighted.
Exactly. So why should we deselect everything starting this selecting 
rectangle (when some threshold distance from initial click position 
Why not just let initially selected items as they are and simply alter 
their state when selection touches them?
> Due to the fact that, with this code, I'm deselecting all the items 
> (if neither shift nor ctrl are pressed) whenever the bounding box is 
> altered,
This is a problem. I don't think native does it this way - deselecting 
all already selected items seems quite strange. And this will flicker as 
a side effect I suppose. This could be easily seen cause native doesn't 
send any notification while moving selection rectangle without item change.
You could of course silence notifications in this case as a workaround 
too :), but this approach will turn code in crap in future.

Could we try it this way (just a proposal):

selecting rectangle has only two working sides with and angle at current 
cursor position. Each resize leads to two smaller rectangles resize - 
formed these two sides and previous selection rectangle (that you 
introduced in second patch). Remaining rectangle stays as it was.
What if test for items to change using these two rectangles? Two 
iterator_frameditems() calls will return items to change, next goes rule 
to toggle or select/deselect item depending on keys state.
> we obviously need to keep a record of how the items were highlighted 
> before the selection was started.
> The alternative would be, I believe, to maintain a list of all the 
> items that have become highlighted or de-highlighted during the 
> selection process, so that they can be restored if need. This would 
> probably be more efficient, at least with large numbers of items, but 
> it would be more complex to implement. If need be, of course, I can 
> try to reimplement the code in this manner.
You're speaking about selection ranges here which aren't lists, but an 
efficient in some sense storage for selections.
>> If you're starting selection box with some items selected they should 
>> be deselected if not Shift pressed and
>> leaved untouched if Shift used. I don't see a reason to restore it - 
>> when you want to toggle selected state
>> moving rectangle with Ctrl pressed you could just:
>> LISTVIEW_GetItemState() and place inverted state with following 
>> LISTVIEW_SetItemState().
> The issue with doing it this way is it would result in massive 
> flickering every time you moved the mouse, unless I perhaps 
> misunderstood you.
Why will it flicker? If state didn't change LISTVIEW_SetItemState is 
smart enough to do not any invalidation.
> Otherwise I guess there would have to be some way of tracking that the 
> pointer is still within the hit area of a certain item, and has not 
> moved out from that area, and hence the state should not be inverted 
> again.
Same selection rule applies here, as for all other items called 
iterator_frameditems() - don't know if it's nice to use in this case though,
cause some intersection allowed here while moving selection rectangle 
with mouse. You could tweak this by the way passing a bit altered 
rectangle to this helper (not equally selection rectangle).
>> Also such large cycles shouldn't be used if you could manage not to 
>> use them.
> See above - but that was indeed a concern of mine. I tested with some 
> reasonably large collections of items (in the hundreds), and it did 
> not seem noticeably slow, but I admit to not trying with thousands if 
> items.
It's something like a known const memory amount that should suffice 
everyone needs in future ). If we could avoid this we certainly should.
>> Anyway this part:
> > ...
>> is wrong. You can't do it that way cause selected state could also be 
>> cached at
>> parent side with corresponding callback bit set (look at 
>> LISTVIEW_GetItemT()).
> I'll look into that, thanks.

More information about the wine-devel mailing list