I want to have an editable listicongadget. One column in that listicongadget needs to contain a combobox dropdown gadget. I took the 2008 code from Srod and modified this a bit to suits my needs (see code snippet). This part works perfectly as far as direct editing is concerned.
Then I tried to implement comboboxes into this code. I used the 2005 code from Srod.
http://www.purebasic.fr/english/viewtop ... n+listicon
The problem is that this code is too old for the current PureBasic version as a couple of the commands don't work anymore. Also I don't have much (very little) experience in API programming so I really don't know what things to change and where.
Maybe someone could point me in the right direction?
John
Code: Select all
#HDI_ORDER = $80
#EC_RIGHTMARGIN = 2
Structure _LIEdit
listOldProc.i
editHwnd.i
item.i
subitem.i
x.i
y.i
cx.i
cy.i
EndStructure
;Returns zero if an error.
Procedure.i SetListIconEditable(listID)
Protected result, parenthWnd, *mem._LIEdit, hWnd, dlv.DLLVERSIONINFO, func, lib
;Check that listID references a valid listicon.
If IsGadget(listID) And GadgetType(listID)=#PB_GadgetType_ListIcon
hWnd = GadgetID(listID)
;Is the listicon already registered?
If GetProp_(hWnd, "_LIEdit")=0 ;No!
;Allocate enough memory for a _LIEdit structure.
*mem=AllocateMemory(SizeOf(_LIEdit))
If *mem
SetWindowLong_(hWnd, #GWL_STYLE, GetWindowLong_(hWnd, #GWL_STYLE)&~#LVS_EDITLABELS)
;Set the fields of the _LIEedit structure.
*mem\listOldProc = SetWindowLong_(hWnd, #GWL_WNDPROC, @_LIEListProc())
;Store a pointer to this structure in a window property ofthe listicon.
SetProp_(hWnd, "_LIEdit", *mem)
;Subclass the parent window if not already through another listicon.
parenthWnd=GetParent_(hWnd)
If GetProp_(parenthWnd, "_LIEditOldProc")=0 ;No!
SetProp_(parenthWnd, "_LIEditOldProc", SetWindowLong_(parenthWnd, #GWL_WNDPROC, @_LIEwinProc()))
EndIf
result=1
EndIf
EndIf
EndIf
ProcedureReturn result
EndProcedure
;Sets the specified cell to be edited.
Procedure EditCell(listID, item, subitem)
Protected hWnd, *liedit._LIEdit, numrows, numcols
;Check that listID references a valid listicon.
If IsGadget(listID) And GadgetType(listID)=#PB_GadgetType_ListIcon
;Check that the listicon is registered as editable.
hWnd = GadgetID(listID)
*liedit = GetProp_(hWnd, "_LIEdit")
If *liedit
;Check parameters are in range.
numrows = CountGadgetItems(listID)
numcols = SendMessage_(SendMessage_(hWnd,#LVM_GETHEADER,0,0), #HDM_GETITEMCOUNT,0,0)
If item>=0 And item < numrows And subitem>0 And subitem < numcols
*liedit\item = item
*liedit\subitem = subitem
SetActiveGadget(listID)
_LIEEditCell(*liedit, hWnd)
EndIf
EndIf
EndIf
EndProcedure
Procedure _LIEEditCell(*liedit._LIEdit, hWnd)
Protected rc.RECT, clientrc.RECT, numCols, headerWnd
Protected Dim cols.l(0), i, blnFoundZeroColumn
Protected hdi.HDITEM
;Scroll the listicon if the clicked cell is not entirely visible
;*****IF YOU WISH TO RESTRICT WHICH CELLS CAN BE EDITED, THEN PERFORM THE NECESSARY CHECKS HERE
;*****ON THE VALUES OF *liedit\item and *liedit\subitem (WHICH INDICATE WHICH CELL IS ABOUT
;*****TO BE EDITED) AND RUN THE FOLLOWING LINES FOR THOSE CELLS WHICH ARE TO BE EDITED.
rc\top = *liedit\subitem
rc\left = #LVIR_BOUNDS
SendMessage_(hWnd, #LVM_GETSUBITEMRECT, *liedit\item, rc)
GetClientRect_(hWnd, clientrc)
If rc\left < 0 Or (rc\right-rc\left)>=clientrc\right
SendMessage_(hWnd, #LVM_SCROLL,rc\left,0)
Else
If rc\right > clientrc\right
SendMessage_(hWnd, #LVM_SCROLL,rc\right-clientrc\right,0)
EndIf
EndIf
SetWindowLong_(hWnd, #GWL_STYLE, GetWindowLong_(hWnd, #GWL_STYLE)|#LVS_EDITLABELS)
SendMessage_(hWnd, #LVM_EDITLABEL, *liedit\item, 0)
EndProcedure
;New Procedure to implement ComboBox functionality
Procedure _LIEComboCell(*liedit._LIEdit, hWnd)
; need some help with this part
EndProcedure
;Window proc of the ListIcon parent window.
Procedure.i _LIEwinProc(hWnd, uMsg, wParam, lParam)
Protected result, oldwinproc, *nmh. NMHDR, listhWnd, edithWnd, *liedit._LIEdit, *lvd.LV_DISPINFO, rc.RECT
Protected hdi.HDITEM, headerWnd
Static celltext$
;Retrieve the address of the old proc.
oldwinproc = GetProp_(hWnd, "_LIEditOldProc")
Select uMsg
Case #WM_NOTIFY
*nmh=lParam
Select *nmh\code
Case #LVN_BEGINLABELEDIT
listhWnd = *nmh\hwndFrom
;Retrieve the address of the LIEdit structure.
*liedit = GetProp_(listhWnd, "_LIEdit")
If *liedit ;Good to go!
*liedit\editHwnd=0
;Get the handle of the edit control used to edit the label.
edithWnd = SendMessage_(listhWnd, #LVM_GETEDITCONTROL,0,0)
;Subclass the edit control.
SetProp_(edithWnd, "_LIEditOldProc", SetWindowLong_(edithWnd, #GWL_WNDPROC, @_LIEeditProc()))
;Set text.
celltext$=GetGadgetItemText(*nmh\idFrom, *liedit\item, *liedit\subitem)
SendMessage_(edithWnd, #WM_SETTEXT, 0, celltext$)
SetGadgetItemText(*nmh\idFrom, *liedit\item, "",*liedit\subitem)
;Get bounding rectangle.
rc\top = *liedit\subitem
rc\left = #LVIR_BOUNDS
SendMessage_(listhWnd, #LVM_GETSUBITEMRECT, *liedit\item, rc)
*liedit\x=rc\left
*liedit\y=rc\top
*liedit\cx=SendMessage_(listhWnd, #LVM_GETCOLUMNWIDTH, *liedit\subitem,0)
*liedit\cy=rc\bottom-rc\top
EndIf
Case #LVN_ENDLABELEDIT
listhWnd = *nmh\hwndFrom
;Retrieve the address of the LIEdit structure.
*liedit = GetProp_(listhWnd, "_LIEdit")
If *liedit ;Good to go!
*lvd = lParam
If *lvd\item\pszText
SetGadgetItemText(*nmh\idFrom, *liedit\item, PeekS(*lvd\item\pszText), *liedit\subitem)
Else
SetGadgetItemText(*nmh\idFrom, *liedit\item, celltext$, *liedit\subitem)
EndIf
SetWindowLong_(listhWnd, #GWL_STYLE, GetWindowLong_(listhWnd, #GWL_STYLE)&~#LVS_EDITLABELS)
headerWnd = SendMessage_(listhWnd,#LVM_GETHEADER,0,0)
SendMessage_(headerWnd, #HDM_SETITEM, 0, hdi)
EndIf
; Insert new blank line
If *liedit\item=CountGadgetItems(*nmh\idFrom)-1
If Trim(GetGadgetItemText(*nmh\idFrom, *liedit\item, 1))+Trim(GetGadgetItemText(*nmh\idFrom, *liedit\item, 2))+Trim(GetGadgetItemText(*nmh\idFrom, *liedit\item, 3))<>""
AddGadgetItem(*nmh\idFrom, -1, "")
EndIf
EndIf
Default
result=CallWindowProc_(oldwinproc, hWnd, uMsg, wParam, lParam)
EndSelect
Case #WM_NCDESTROY
result=CallWindowProc_(oldwinproc, hWnd, uMsg, wParam, lParam)
RemoveProp_(hWnd, "_LIEditOldProc")
Default
result=CallWindowProc_(oldwinproc, hWnd, uMsg, wParam, lParam)
EndSelect
ProcedureReturn result
EndProcedure
;Window proc of the ListIcon.
Procedure.i _LIEListProc(hWnd, uMsg, wParam, lParam)
Protected result, *liedit._LIEdit, PInfo.LVHITTESTINFO, *nmHEADER.HD_NOTIFY
;Retrieve the address of the LIEdit structure.
*liedit = GetProp_(hWnd, "_LIEdit")
Select uMsg
Case #WM_NOTIFY
*nmHEADER = lParam
Select *nmHEADER\hdr\code
;Case #HDN_BEGINTRACK, #HDN_BEGINTRACKW ;Prevent column 0 from being resized.
; If *nmHEADER\iItem=0
; result=1
; EndIf
Case #HDN_ENDTRACK, #HDN_ENDTRACKW
InvalidateRect_(hWnd,0,1)
Default
result=CallWindowProc_(*liedit\listOldProc, hWnd, uMsg, wParam, lParam)
EndSelect
Case #WM_LBUTTONDBLCLK
;Identify the clicked item
PInfo\pt\x = lParam&$ffff
PInfo\pt\y = (lParam>>16)&$ffff
SendMessage_(hwnd, #LVM_SUBITEMHITTEST, 0, PInfo)
If PInfo\iItem <> -1 ;A valid cell was clicked.
*liedit\item = PInfo\iItem
*liedit\subitem = PInfo\iSubItem
If PInfo\iSubItem=2 ; column 2 should be combobox
_LIEComboCell(*liedit, hWnd)
Else
_LIEEditCell(*liedit, hWnd) ; all other columns can be edited directly
EndIf
EndIf
Case #WM_NCDESTROY
result=CallWindowProc_(*liedit\listOldProc, hWnd, uMsg, wParam, lParam)
RemoveProp_(hWnd, "_LIEdit")
FreeMemory(*liedit)
Default
result=CallWindowProc_(*liedit\listOldProc, hWnd, uMsg, wParam, lParam)
EndSelect
ProcedureReturn result
EndProcedure
;Window proc of the edit control.
Procedure.i _LIEeditProc(hWnd, uMsg, wParam, lParam)
Protected result, oldwinproc, *liedit._LIEdit, *wpos.WINDOWPOS
;Retrieve the address of the old proc.
oldwinproc = GetProp_(hWnd, "_LIEditOldProc")
;Retrieve the address of the LIEdit structure.
*liedit = GetProp_(GetParent_(hWnd), "_LIEdit")
Select uMsg
Case #WM_ERASEBKGND
;A hack in order to clear the default selection of characters.
result=CallWindowProc_(oldwinproc, hWnd, uMsg, wParam, lParam)
If *liedit\editHwnd=0
*liedit\editHwnd = hWnd
;Set margins.
SendMessage_(hWnd, #EM_SETMARGINS, #EC_LEFTMARGIN|#EC_RIGHTMARGIN, 4)
SendMessage_(hWnd, #EM_SETSEL, -1,0)
EndIf
Case #WM_WINDOWPOSCHANGING
*wpos=lParam
*wpos\cx=*liedit\cx ;Comment this line to get an edit control which grows with the text.
*wpos\x=*liedit\x
*wpos\cy=*liedit\cy
*wpos\y=*liedit\y
result=CallWindowProc_(oldwinproc, hWnd, uMsg, wParam, lParam)
Case #WM_NCDESTROY
result=CallWindowProc_(oldwinproc, hWnd, uMsg, wParam, lParam)
RemoveProp_(hWnd, "_LIEditOldProc")
Default
result=CallWindowProc_(oldwinproc, hWnd, uMsg, wParam, lParam)
EndSelect
ProcedureReturn result
EndProcedure