ComboBoxGadget in Editable ListIconGadget [Windows]

Share your advanced PureBasic knowledge/code with the community.
User avatar
minimy
Enthusiast
Enthusiast
Posts: 552
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by minimy »

wow! thanks RASHAD! Very nice work as allways! :wink:
Thanks for share! +1
If translation=Error: reply="Sorry, Im Spanish": Endif
PBJim
Enthusiast
Enthusiast
Posts: 294
Joined: Fri Jan 19, 2024 11:56 pm

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by PBJim »

minimy wrote: Sat Oct 12, 2024 10:02 pm wow! thanks RASHAD! Very nice work as allways! :wink: Thanks for share! +1
Indeed, thanks likewise Rashad. It works well and is more robust now.

Incidentally, it's necessary to check for row - 1 within Case #WM_LBUTTONDBLCLK because we need to check if the user double-clicks an empty line. It edits the column heading otherwise :

Code: Select all

      If  row = -1                      ; <----- Check for empty line
        editflag = 0
      Else
        editflag = 1
        MoveWindow_(GadgetID(2),r\left+GadgetX(0)+2,r\top+GadgetY(0)+2,r\right-r\left,r\bottom-r\top,1)
        SetGadgetText(2,GetGadgetItemText(0,row,col))
        SetFocus_(GadgetID(2))
      EndIf
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by RASHAD »

@minimy ,PBJim
You are welcome
Previous post updated
Egypt my love
PBJim
Enthusiast
Enthusiast
Posts: 294
Joined: Fri Jan 19, 2024 11:56 pm

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by PBJim »

Hi Rashad,
Hope you might be able to help. I added a new function to the editable ListIconGadget, to create a new empty item in the list. I implemented this as a double-click on the blank line below the last item in the list :

Code: Select all

  If row = -1    ; <------------------   Double-click empty row to create new line
    AddGadgetItem(ListIcon, -1, "")
    editflag = 0
I'm not sure how to get StringGadget to automatically appear at the new line (in column 0 only), to allow the user to input the value. It needs to be calculated at the correct row to make the StringGadget input appear at the right place. I was never really sure how struct 'r' is calculated. Could you possibly help me with it? Many thanks. Jim

Code: Select all

; **
; **  Grid input test routine
; **  Removed ComboBoxGadget
; **
; **  https://www.purebasic.fr/english/viewtopic.php?t=55781
; **

EnableExplicit

Global oldCallback,ListIcon,LIColor,Oldr,Oldc,editflag

Define Quit


Procedure LIcallback(hwnd, msg, wparam, lparam) 
  
  Define result.i
  Define *NMHDR.NMHDR
  Define *phdn.NMHEADER
  Define r.RECT
  Define pInfo.LVHITTESTINFO
  Define col, row
  
  result = CallWindowProc_(oldCallback, hwnd, msg, wparam, lparam)
  Select msg
    Case #WM_NOTIFY 
      *NMHDR.NMHDR = lParam
      If *nmhdr\code = #HDN_ITEMCHANGING And *NMHDR\code = #HDN_FIRST
        *phdn.NMHEADER = lParam                 
        If  editflag = 1
          r.RECT\top = Oldc
          r.RECT\left = #LVIR_BOUNDS
          SendMessage_(GadgetID(ListIcon), #LVM_GETSUBITEMRECT, Oldr, r)
          If Oldc = 0
            r\right = r\left+SendMessage_(GadgetID(ListIcon), #LVM_GETCOLUMNWIDTH, 0, 0)
          EndIf
          MoveWindow_(GadgetID(2),r\left+GadgetX(ListIcon)+2,r\top+GadgetY(ListIcon)+2,r\right-r\left,r\bottom-r\top,1)  
          SetFocus_(GadgetID(2))
        EndIf
      EndIf
      
    Case #WM_LBUTTONDOWN
      SetGadgetState(ListIcon,-1)
      MoveWindow_(GadgetID(2),0,0,0,0,1)
      If editflag = 1 And GetGadgetText(2) <> ""
        SetGadgetItemText(ListIcon, Oldr,GetGadgetText(2),Oldc)
      EndIf
      pInfo.LVHITTESTINFO
      pInfo\pt\x = (lParam & $FFFF) 
      pInfo\pt\y = (lParam>> 16 & $FFFF)                    
      
      SendMessage_(GadgetID(ListIcon),#LVM_SUBITEMHITTEST,0,@pInfo)
      SetGadgetItemColor(ListIcon,OLdr,#PB_Gadget_FrontColor,#Black ,Oldc)
      SetGadgetItemColor(ListIcon,Oldr, #PB_Gadget_BackColor, LIColor,Oldc)
      SetGadgetItemColor(ListIcon,pInfo\iItem,#PB_Gadget_FrontColor,#White ,pInfo\iSubItem)
      SetGadgetItemColor(ListIcon,pInfo\iItem, #PB_Gadget_BackColor,GetSysColor_(#COLOR_HIGHLIGHT),pInfo\iSubItem)

      Oldr = pInfo\iItem
      Oldc = pInfo\iSubItem
      editflag = 0

    Case #WM_LBUTTONDBLCLK      
      r.RECT\top = Oldc
      r.RECT\left = #LVIR_BOUNDS
      SendMessage_(GadgetID(ListIcon), #LVM_GETSUBITEMRECT, Oldr, r)
      SendMessage_(GadgetID(ListIcon), #LVM_GETHOTITEM, 0,0)
      If Oldc = 0
        r\right = r\left+SendMessage_(GadgetID(ListIcon), #LVM_GETCOLUMNWIDTH, 0, 0)
      EndIf        
      pInfo.LVHITTESTINFO
      pInfo\pt\x = (lParam & $FFFF) 
      pInfo\pt\y = (lParam>> 16 & $FFFF)                    
      SendMessage_(GadgetID(ListIcon),#LVM_SUBITEMHITTEST,0,@pInfo)
      row = pInfo\iItem
      col = pinfo\iSubItem

      If row = -1
        AddGadgetItem(ListIcon, -1, "")  ; <------------------   Double-click empty row to create new line
        editflag = 0
      Else
        editflag = 1
        MoveWindow_(GadgetID(2),r\left+GadgetX(ListIcon)+2,r\top+GadgetY(ListIcon)+2,r\right-r\left,r\bottom-r\top,1)
        SetGadgetText(2,GetGadgetItemText(ListIcon,row,col))
        SetFocus_(GadgetID(2))
      EndIf
      
    Case #WM_VSCROLL,#WM_HSCROLL
      MoveWindow_(GadgetID(2),0,0,0,0,1)

      SetGadgetItemColor(ListIcon,OLdr,#PB_Gadget_FrontColor,#Black ,Oldc)
      SetGadgetItemColor(ListIcon,Oldr, #PB_Gadget_BackColor, LIColor,Oldc)

      
  EndSelect
  ProcedureReturn result
EndProcedure

LoadFont(0,"Tahoma",10) 

OpenWindow(0,0,0,840,480,"Test",#PB_Window_SystemMenu| #PB_Window_ScreenCentered| #PB_Window_SizeGadget)
ListIcon = ListIconGadget(#PB_Any,10,10,821,470,"Column 1",200,#PB_ListIcon_GridLines|#WS_CLIPSIBLINGS )
AddGadgetColumn(ListIcon,1,"Column 2",200) 
AddGadgetColumn(ListIcon,2,"Column 3",200) 
AddGadgetColumn(ListIcon,3,"Column 4",200)

AddGadgetItem(ListIcon, -1, "Row 1, Col 1" + Chr(10) +
                         "Row 1, Col 2" + Chr(10) +
                         "Row 1, Col 3" + Chr(10) +
                         "Row 1, Col 4" + Chr(10))

; **
; **  Set colour of grid
; **
SetGadgetColor(ListIcon, #PB_Gadget_BackColor, $F7F7F7)

; **
; **  Grid input string
; **
StringGadget(2,0,0,0,0,"",#ES_MULTILINE|#WS_CLIPSIBLINGS)
SendMessage_(GadgetID(2), #EM_SETMARGINS, #EC_LEFTMARGIN, 3)
BringWindowToTop_(GadgetID(2))
oldCallback = SetWindowLongPtr_(GadgetID(ListIcon), #GWL_WNDPROC, @LIcallback())

SetGadgetFont(ListIcon,FontID(0))
SetGadgetFont(2,FontID(0))
If GetGadgetColor(ListIcon, #PB_Gadget_BackColor) < 0 
  LIColor = #White
Else
  LIColor =  GetGadgetColor(ListIcon, #PB_Gadget_BackColor)
EndIf

AddKeyboardShortcut(0, #PB_Shortcut_Return, 15)
AddKeyboardShortcut(0, #PB_Shortcut_Escape, 20)

Repeat
  Select WaitWindowEvent()
      
    Case #PB_Event_CloseWindow
      Quit = 1
      
    Case #PB_Event_Menu    
      Select EventMenu()
        Case 15
          If GetActiveGadget() = 2
            SetGadgetItemText(ListIcon, Oldr,GetGadgetText(2),Oldc)
            MoveWindow_(GadgetID(2),0,0,0,0,1)
            editflag = 0
          EndIf
        Case 20
          If GetActiveGadget() = 2
            MoveWindow_(GadgetID(2),0,0,0,0,1)
            editflag = 0
          EndIf               
      EndSelect
      
    Case #WM_KEYDOWN
      If GetActiveGadget() = 2 And  EventwParam() = 27
        MoveWindow_(GadgetID(2),0,0,0,0,1)
        editflag = 0
      ElseIf GetActiveGadget() = 2 And  EventwParam() = 13
        SetGadgetItemText(ListIcon, Oldr,GetGadgetText(2),Oldc)
        MoveWindow_(GadgetID(2),0,0,0,0,1)
        editflag = 0
      EndIf      
      
    Case #PB_Event_Gadget
      
  EndSelect 
  
Until Quit = 1
End
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by Michael Vogel »

Hi Rashad, very nice code.
But when using the mouse (select a cell) and the keyboard arrow keys then (cursor down, etc.) two cells seem to be active (blue background).
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by RASHAD »

Hi MV :)
Time to enhance the snippet

Code: Select all

Global oldCallback,ListIcon,LIColor,Oldr,Oldc,editflag

Procedure LIcallback(hwnd, msg, wparam, lparam) 
  result = CallWindowProc_(oldCallback, hwnd, msg, wparam, lparam)
  Select msg
    Case #WM_NOTIFY 
      *NMHDR.NMHDR = lParam
      If *nmhdr\code = #HDN_ITEMCHANGING And *NMHDR\code = #HDN_FIRST
        *phdn.NMHEADER = lParam                 
        If  editflag = 1
          r.RECT\top = Oldc
          r.RECT\left = #LVIR_BOUNDS
          SendMessage_(GadgetID(0), #LVM_GETSUBITEMRECT, Oldr, r)
          If Oldc = 0
            r\right = r\left+SendMessage_(GadgetID(0), #LVM_GETCOLUMNWIDTH, 0, 0)
          EndIf
          MoveWindow_(GadgetID(2),r\left+GadgetX(0)+2,r\top+GadgetY(0)+2,r\right-r\left,r\bottom-r\top,1)  
          SetFocus_(GadgetID(2))
        EndIf
      EndIf
      
    Case #WM_LBUTTONDOWN
      SetGadgetState(0,-1)
      MoveWindow_(GadgetID(2),0,0,0,0,1)
      If editflag = 1 And GetGadgetText(2) <> ""
        SetGadgetItemText(0, Oldr,GetGadgetText(2),Oldc)
        SetGadgetState(0,-1) 
      EndIf
      pInfo.LVHITTESTINFO
      pInfo\pt\x = (lParam & $FFFF) 
      pInfo\pt\y = (lParam>> 16 & $FFFF)                    
      SendMessage_(ListIcon,#LVM_SUBITEMHITTEST,0,@pInfo)
      If  pInfo\iSubItem = 4 And Run =0              
        SendMessage_(GadgetID(0),#WM_HSCROLL,#SB_PAGERIGHT,0)
        Run = 1
        r.RECT 
        r\top  = pInfo\iSubItem 
        r\left = #LVIR_BOUNDS 
        SendMessage_(GadgetID(0), #LVM_GETSUBITEMRECT, pInfo\iItem, r)
        MoveWindow_(GadgetID(5),r\left+GadgetX(0)+2,r\top+GadgetY(0)+2,r\right-r\left,r\bottom-r\top,1)
      Else
        Run =0  
        MoveWindow_(GadgetID(5),0,0,0,0,1)
        SetGadgetItemState(0,pInfo\iItem,#PB_ListIcon_Selected )
      EndIf          
      editflag = 0
      Oldr = pInfo\iItem
      Oldc = pInfo\iSubItem      
      
    Case #WM_LBUTTONDBLCLK
      SetGadgetState(0,-1)
      editflag = 1
      r.RECT\top = Oldc
      r.RECT\left = #LVIR_BOUNDS
      SendMessage_(GadgetID(0), #LVM_GETSUBITEMRECT, Oldr, r)
      SendMessage_(GadgetID(0), #LVM_GETHOTITEM, 0,0)
      If Oldc = 0
        r\right = r\left+SendMessage_(GadgetID(0), #LVM_GETCOLUMNWIDTH, 0, 0)
      EndIf
      SetGadgetText(2,"")
      MoveWindow_(GadgetID(2),r\left+GadgetX(0)+2,r\top+GadgetY(0)+2,r\right-r\left,r\bottom-r\top,1)
      SetFocus_(GadgetID(2))
      
    Case #WM_VSCROLL,#WM_HSCROLL
      MoveWindow_(GadgetID(2),0,0,0,0,1)
      MoveWindow_(GadgetID(5),0,0,0,0,1)      
      
  EndSelect
  ProcedureReturn result
EndProcedure

Procedure sizeCB()
  ResizeGadget(1,10,WindowHeight(0)-30,#PB_Ignore,#PB_Ignore)
  ResizeGadget(0,10,10,WindowWidth(0)-20,WindowHeight(0)-60)
EndProcedure

LoadFont(0,"Tahoma",10) 

OpenWindow(0,0,0,640,480,"Test",#PB_Window_SystemMenu| #PB_Window_ScreenCentered| #PB_Window_SizeGadget)
ListIcon = ListIconGadget(0,10,10,620,450,"Column 0",200,#PB_ListIcon_FullRowSelect |#PB_ListIcon_AlwaysShowSelection|#PB_ListIcon_GridLines|#WS_CLIPSIBLINGS );|#LVS_EDITLABELS) 
AddGadgetColumn(0,1,"Column 1",210) 
AddGadgetColumn(0,2,"Column 2",200) 
AddGadgetColumn(0,3,"Column 3",200)
AddGadgetColumn(0,4,"Column 4",200)
AddGadgetColumn(0,5,"Column 5",100) 

For i = 0 To 16 
  linestr.s = LSet(Str(i),3," ") 
  AddGadgetItem(0, -1, "Text on Line "+linestr+" in Column 1"+Chr(10)+"Text on Line "+linestr+" in Column 2" + Chr(10)+"Text on Line "+linestr+" in Column 3" + Chr(10)+"Text on Line "+linestr+" in Column 3"+ Chr(10)+"") 
Next
SetGadgetColor(0, #PB_Gadget_BackColor,$DFFEFD)
ButtonGadget(1,10,450,150,24,"Add new ROW")
StringGadget(2,0,0,0,0,"",#ES_MULTILINE|#WS_CLIPSIBLINGS);|#PB_String_BorderLess)
SendMessage_(GadgetID(2), #EM_SETMARGINS, #EC_LEFTMARGIN, 3)
BringWindowToTop_(GadgetID(2))
oldCallback = SetWindowLongPtr_(ListIcon, #GWL_WNDPROC, @LIcallback())

SetGadgetFont(0,FontID(0))
SetGadgetFont(2,FontID(0))
If GetGadgetColor(0, #PB_Gadget_BackColor) < 0 
  LIColor = #White
Else
  LIColor =  GetGadgetColor(0, #PB_Gadget_BackColor)
EndIf

ComboBoxGadget(5,0,0,0,0,#WS_CLIPSIBLINGS)
For a = 1 To 5
  AddGadgetItem(5, -1,"ComboBox item " + Str(a))
Next
BringWindowToTop_(GadgetID(5))
BindEvent(#PB_Event_SizeWindow,@sizeCB())
Repeat
  Select WaitWindowEvent()
      
    Case #PB_Event_CloseWindow
      Quit = 1
      
    Case #WM_KEYDOWN
      If GetActiveGadget() = 2 And  EventwParam() = 27
        MoveWindow_(GadgetID(2),0,0,0,0,1)
        editflag = 0
      ElseIf GetActiveGadget() = 2 And  EventwParam() = 13
        SetGadgetItemText(0, Oldr,GetGadgetText(2),Oldc)
        MoveWindow_(GadgetID(2),0,0,0,0,1)
        SetGadgetState(0,-1) 
        editflag = 0
      EndIf
      
    Case #PB_Event_Menu
      Select EventMenu()
        Case 1            
      EndSelect
      
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          sel = GetGadgetState(0)
          linestr.s = LSet(Str(CountGadgetItems(0)),3," ")
          AddGadgetItem(0, -1, "Text on Line "+linestr+" in Column 1"+Chr(10)+"Text on Line "+linestr+" in Column 2" + Chr(10)+"Text on Line "+linestr+" in Column 3" + Chr(10)+"Text on Line "+linestr+" in Column 3"+ Chr(10)+"")
          SetGadgetItemState(0,sel,#PB_ListIcon_Selected)
          SetActiveGadget(0)
        Case 5
          MoveWindow_(GadgetID(5),0,0,0,0,1)
          SetGadgetItemText(0, Oldr,GetGadgetText(5),Oldc)
      EndSelect
      
      
    Case #WM_SIZE
      ResizeGadget(0,10,10,WindowWidth(0)-20,WindowHeight(0)-60)
      
  EndSelect 
  
Until Quit = 1
End
Egypt my love
BarryG
Addict
Addict
Posts: 4122
Joined: Thu Apr 18, 2019 8:17 am

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by BarryG »

That's so good, Rashad! Thanks.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by RASHAD »

Thanks BarryG
Much appreciated
Egypt my love
BarryG
Addict
Addict
Posts: 4122
Joined: Thu Apr 18, 2019 8:17 am

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by BarryG »

Definitely has that Excel feeling (posted this comment for future searches). ;)
PBJim
Enthusiast
Enthusiast
Posts: 294
Joined: Fri Jan 19, 2024 11:56 pm

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by PBJim »

Thanks to Rashad for continuing to update this code. Incidentally, I don't think the latest changes were applied to what was actually the latest version from October 2024, as it does not allow editing of existing cell values — the last refinement made at this link : https://www.purebasic.fr/english/viewto ... 8a#p628938

That version sets the input with the below line :

Code: Select all

SetGadgetText(2,GetGadgetItemText(0,row,col))
For the record, I've been working with this code since last year and refined it further, also removing the combobox function, as it wasn't needed and added unwanted complexity to the code. On the whole it works well, if a little buggy in places, but even so it still offers a great basis for providing a grid input. It wasn't easy to refine — it would benefit from some comments.

But I'd love to see this be developed further and made more robust as it looks quite professional and is suited to business applications — which the 'Said' version is far from suited. A cross-hairs cell pointer in a business application, definitely will not go down well with users. :D
User avatar
a_carignan
User
User
Posts: 98
Joined: Sat Feb 21, 2009 2:01 am
Location: Canada

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by a_carignan »

Hello, I would like an example with an editable combobox on column 5 and why not a dategadget and thus have a complete example of editing a listgadget with all the compatible editing gadgets. Thank you in advance.
Post Reply