I hope that the subject was descriptive enough. :)

I'd like to implement a combobox within a listview. I'm not sure how to phrase this though, so my searches haven't really pulled up much results. The only example that I can think of is Microsoft Access. Maybe it's not actually a combobox but just a listbox, edit control, and a button?

Does anyone know how to do this?


Posted on 2004-02-20 13:53:59 by Will
Just see how Access does this :) - when you click on a cell, it creates a new combo-box controls (CreateWindowEx), and fills in the data from it.
It probably starts a GetMessage/TranslateMessage/DispatchMessage loop right after creating the control, and exits that loop when the control is destoyed.
Posted on 2004-02-20 15:00:33 by Ultrano
Hiya, I did that recently in my UpdateManager project. It is a bit complicated, basically what you do is this:

On an NM_DBLCLK notification you check to see which item/sub item has been clicked using LVM_SUBITEMHITTEST

You then get the bounding rectangle for the item using LVM_GETSUBITEMRECT

At that point you create a combobox of that size and at that position that is a child of the ListView

Fill the combobox with what you want and you're all done.

You will have to take care to watch for mouse clicks outside of the area of the combo box and destroy it when necessary. This is the code to create it in GoAsm syntax, note that my combo was owner draw so it needs a bit more handling. Also the text in the subitem starts with a single digit (1. item) so I use that to keep track of where to initialize the combo box...


cmp D[edi+NMHDR.code],NM_DBLCLK
invoke SendDlgItemMessage,[hListView],999,WM_CLOSE,0,0
invoke GetMessagePos
movzx ecx,ax
mov [lvhi.pt.x],ecx
shr eax,16
movzx ecx,ax
mov [lvhi.pt.y],ecx
invoke ScreenToClient,[hListView],OFFSET lvhi.pt
invoke SendMessage,[hListView], LVM_SUBITEMHITTEST, 0, OFFSET lvhi
; returns the column and item that was clicked in lvhi
cmp D[lvhi.iItem],-1
je >>.WMN_DONE
cmp D[lvhi.iSubItem],4
jne >>D1
; Display the update type combo box
mov eax,[lvhi.iSubItem]
mov [rect.top],eax
mov D[rect.left],LVIR_LABEL
invoke SendMessage,[hListView],LVM_GETSUBITEMRECT,[lvhi.iItem],OFFSET rect

; Get the current selection number
mov D[lvi.imask],LVIF_TEXT
mov eax,[lvhi.iItem]
mov [lvi.iItem],eax
mov eax,[lvhi.iSubItem]
mov [lvi.iSubItem],eax
mov D[lvi.pszText],OFFSET cbstring
mov D[lvi.cchTextMax],255
invoke SendMessage,[hListView],LVM_GETITEMTEXT,[lvhi.iItem],OFFSET lvi
mov eax,OFFSET cbstring
mov B[cbstring+1],0
invoke asciitodword,OFFSET cbstring
mov D[iCBItem],eax

mov eax,[rect.bottom]
sub eax,[rect.top]
push eax
mov ecx,[rect.right]
sub ecx,[rect.left]
sub D[rect.top],1
invoke CreateWindowEx,NULL,"COMBOBOX",NULL,\

mov ebx,eax
invoke SendMessage,ebx,WM_SETFONT,[hCBFont],TRUE
CB_SetContent(ebx,OFFSET szaComboBox)
invoke SendMessage,ebx,CB_SETCURSEL,[iCBItem],0
pop eax
; less the borders
sub eax,4
invoke SendMessage,ebx,CB_SETITEMHEIGHT,-1,eax
invoke SetFocus,ebx

EXE only to show you that it works :)
Posted on 2004-02-20 15:38:13 by donkey
Posted on 2004-02-20 16:02:00 by Anonymous
Thanks donkey! :)

that's perfect,
Posted on 2004-02-20 18:05:25 by Will