I have a listview with LVS_EX_CHECKBOXES style. If i select multiple items by holding SHIFT / CTRL, i'd like all the selected checkboxes to change state according to the clicked one.

I was thinking about handling the NM_CLICK message and then somehow use the NMITEMACTIVATE.ptAction point to figure out if a checkbox was clicked. Then check which items have the LVIS_SELECTED state. And finally set the checkboxes.

So my question is, is there some easier way to accomplish this?
Posted on 2003-10-20 16:35:45 by Janne
Hi, Janne.
Perhaps you could try processing LVN_ITEMCHANGED (or LVN_ITEMCHANGING) and set the checkmark accordingly. Though I don't know if this message is sent only when items change due to user input... if not it could be tricky.
Posted on 2003-10-20 16:47:50 by QvasiModo
The trick is to get the check state on LVN_ITEMCHANGING and compare it with the check state on LVN_ITEMCHANGED. If the check state did not change, it means that the checkbox was not clicked (or space was not pressed). I used this "technique" in one of my Delphi applications.
Posted on 2003-10-20 20:01:08 by Morris
QvasiModo, Morris, thanks for the help.

Another question:
how to create that little triangle, which shows the current sort?
Posted on 2003-10-21 04:25:42 by Janne
You must first draw an image list for the up and down arrows, you can use Toolbar Paint to do this. Then you get the handle of the header control and assign the imagelist to it as follows:

invoke SendMessage,hListView,LVM_GETHEADER,0,0

mov hHeader,eax
; this assumes that the background of the image is white (0FFFFFFh)
invoke ImageList_LoadImage,NULL,OFFSET headerimagelist, 16, 0, 0FFFFFFh, \
IMAGE_BITMAP, LR_LOADFROMFILE
invoke SendMessage,hHeader,HDM_SETIMAGELIST,0,eax
mov hdi._mask,HDI_FORMAT or HDI_IMAGE
mov hdi.fmt,HDF_IMAGE or HDF_STRING
mov hdi.iImage,0 ; Up image
invoke SendMessage,hHeader,HDM_SETITEM,1,ADDR hdi


When you want to change the image just send the HDM_SETITEM message with the proper image index. This requires common controls version 4.70 (internet explorer 4)
Posted on 2003-10-21 04:59:24 by donkey
Donkey, thanks for the info.

Checking multiple checkboxes with one click works under win98 with the code below.
But under win2000, only one box changes when clicked, no matter how many items are selected.
What could be the reason for that?

______________________________________________________
Edit:
Had a bug in the code, correction is in red. Now it works on W2K too.
______________________________________________________



.elseif [edi].NMHDR.code==LVN_ITEMCHANGING
invoke SendMessage,hList,LVM_GETITEMSTATE,[edi].NMLISTVIEW.iItem,LVIS_STATEIMAGEMASK
shr eax,12
dec eax
mov OldState,eax

.elseif [edi].NMHDR.code==LVN_ITEMCHANGED
.if InterceptChanges
mov InterceptChanges,FALSE

;get check state
invoke SendMessage,hList,LVM_GETITEMSTATE,[edi].NMLISTVIEW.iItem,LVIS_STATEIMAGEMASK
shr eax,12
dec eax

;if it is not the check state that changed, we do not want to catch this event
.if OldState!=eax
push eax
; check if the clicked item is selected. If not, dont change the others
invoke SendMessage,hList,LVM_GETITEMSTATE,[edi].NMLISTVIEW.iItem,LVIS_SELECTED
and eax,2;zero all bits but bit 1 (the SELECTED bit)
cmp eax,2;was bit 1 set?
.if zero?
pop eax
.if eax
xor ebx,ebx
.while ebx<=errorcount
invoke SendMessage,hList,LVM_GETITEMSTATE,ebx,LVIS_SELECTED
and eax,2;zero all bits but bit 1 (the SELECTED bit)
cmp eax,2;was bit 1 set?
jnz @F
invoke SetItem,hList,LVIF_STATE,ebx,0,(2 SHL 12),LVIS_STATEIMAGEMASK,0,0,0

@@:
inc ebx
.endw
.else
xor ebx,ebx
.while ebx<=errorcount
invoke SendMessage,hList,LVM_GETITEMSTATE,ebx,LVIS_SELECTED
and eax,2;zero all bits but bit 1 (the SELECTED bit)
cmp eax,2;was bit 1 set?
jnz @F
invoke SetItem,hList,LVIF_STATE,ebx,0,(1 SHL 12),LVIS_STATEIMAGEMASK,0,0,0

@@:
inc ebx
.endw
.endif
[color=red]
.else
pop eax
[/color]
.endif
.endif

mov InterceptChanges,TRUE
.endif
.endif
.endif
Posted on 2003-10-28 01:25:09 by Janne