ComboBoxGadget in Editable ListIconGadget [Windows]

Share your advanced PureBasic knowledge/code with the community.
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 morosh
I was lately a Corona victim so excuse me for any bugs I am not quite well
Usually column 0 in ListIcon has it's icon and case a lot of troubles
Next snippet no column 0 so *nmhdr\code = #HDN_ITEMCHANGING to prevent using the header to activate column 0
With taking KCC notifications into consideration

Code: Select all

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

Procedure sizeCB()
  ResizeGadget(0,10,10,WindowWidth(0)-20,WindowHeight(0)-60)
EndProcedure

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  *phdn\iItem = 0 
                ProcedureReturn 1
          EndIf                 
          r.RECT\top = Oldc
          r.RECT\left = #LVIR_BOUNDS
          SendMessage_(GadgetID(0), #LVM_GETSUBITEMRECT, Oldr, r)
          If editflag = 1
              MoveWindow_(GadgetID(2),r\left,r\top,r\right-r\left,r\bottom-r\top,1)  
              SetFocus_(GadgetID(2))
          ElseIf Oldc = 4 And Run =0
              Run = 1
              MoveWindow_(GadgetID(5),r\left,r\top,r\right-r\left,r\bottom-r\top,1)
          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)
          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
              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,r\top,r\right-r\left,r\bottom-r\top,1)
          Else
              Run =0  
              MoveWindow_(GadgetID(5),0,0,0,0,1)
              SetGadgetItemColor(0,OLdr,#PB_Gadget_FrontColor,#Black ,Oldc)
              SetGadgetItemColor(0,Oldr, #PB_Gadget_BackColor, LIColor,Oldc)
              SetGadgetItemColor(0,pInfo\iItem,#PB_Gadget_FrontColor,#White ,pInfo\iSubItem)
              SetGadgetItemColor(0,pInfo\iItem, #PB_Gadget_BackColor,GetSysColor_(#COLOR_HIGHLIGHT),pInfo\iSubItem)
          EndIf          
          editflag = 0
          Oldr = pInfo\iItem
          Oldc = pInfo\iSubItem
        
    
    Case #WM_LBUTTONDBLCLK
          editflag = 1
          r.RECT\top = Oldc
          r.RECT\left = #LVIR_BOUNDS
          SendMessage_(GadgetID(0), #LVM_GETSUBITEMRECT, Oldr, r)
          SetGadgetText(2,"")
          MoveWindow_(GadgetID(2),r\left,r\top,r\right-r\left,r\bottom-r\top,1)
          SetFocus_(GadgetID(2))
          
    Case #WM_VSCROLL,#WM_HSCROLL
          r.RECT\top = Oldc
          r.RECT\left = #LVIR_BOUNDS
          SendMessage_(GadgetID(0), #LVM_GETSUBITEMRECT, Oldr, r)
          If editflag = 1
              MoveWindow_(GadgetID(2),r\left,r\top,r\right-r\left,r\bottom-r\top,1)  
              SetFocus_(GadgetID(2))
          ElseIf Oldc = 4 And Run =0
              Run = 1
              MoveWindow_(GadgetID(5),r\left,r\top,r\right-r\left,r\bottom-r\top,1)
          EndIf
          InvalidateRect_(GadgetID(2),0,1)   

  EndSelect
  ProcedureReturn result
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,460,"Column 0",0,#PB_ListIcon_GridLines)
AddGadgetColumn(0,1,"Column 1",200) 
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, Chr(10)+"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)+"") 
Next
SetGadgetColor(0, #PB_Gadget_BackColor,$DFFEFD)
StringGadget(2,0,0,0,0,"",#ES_MULTILINE)
SendMessage_(GadgetID(2), #EM_SETMARGINS, #EC_LEFTMARGIN, 3)
SetParent_(GadgetID(2),GadgetID(0))
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)
For a = 1 To 5
  AddGadgetItem(5, -1,"ComboBox item " + Str(a))
Next
SetParent_(GadgetID(5),GadgetID(0))

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)
               editflag = 0
           EndIf
      
      Case #PB_Event_Menu
          Select EventMenu()
           Case 1            
          EndSelect
      
      Case #PB_Event_Gadget
          Select EventGadget()
           Case 5
               MoveWindow_(GadgetID(5),0,0,0,0,1)
               SetGadgetItemText(0, Oldr,GetGadgetText(5),Oldc)             
          EndSelect            
            
  EndSelect 

Until Quit = 1
End

Egypt my love
morosh
Enthusiast
Enthusiast
Posts: 329
Joined: Wed Aug 03, 2011 4:52 am
Location: Beirut, Lebanon

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by morosh »

Thanks Rashad:
Can the sound notification after editing a cell and pressing Enter, be removed ?
PureBasic: Surprisingly simple, diabolically powerful
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by RASHAD »

Replace

Code: Select all

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(0, 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
Egypt my love
morosh
Enthusiast
Enthusiast
Posts: 329
Joined: Wed Aug 03, 2011 4:52 am
Location: Beirut, Lebanon

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by morosh »

Perfect as always !!!
Thank you very much
PureBasic: Surprisingly simple, diabolically powerful
PBJim
Enthusiast
Enthusiast
Posts: 294
Joined: Fri Jan 19, 2024 11:56 pm

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by PBJim »

jassing wrote: Mon Aug 05, 2013 2:20 am Nice; but it should leave the text in there when you edit and response as 'cancel' to escape.
RASHAD wrote: Mon Aug 05, 2013 4:53 am Hi jassing
Previous post updated
I've been trying this code, RASHAD. If I double-click a cell, it doesn't seem to preserve the existing content. The input is blank. The comments above suggest a change was made to be able to edit existing contents.

The feature is certainly in demand though — someone's youtube video shows another attempt : https://www.youtube.com/watch?v=Yq9bZChB7ls
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 PBJim

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)
      EndIf
      pInfo.LVHITTESTINFO
      pInfo\pt\x = (lParam & $FFFF) 
      pInfo\pt\y = (lParam>> 16 & $FFFF)                    
      SendMessage_(ListIcon,#LVM_SUBITEMHITTEST,0,@pInfo)
      row = pInfo\iItem
      If pInfo\iItem < 0      	
        SetGadgetItemColor(0,OLdr,#PB_Gadget_FrontColor,#Black ,Oldc)
        SetGadgetItemColor(0,Oldr, #PB_Gadget_BackColor, LIColor,Oldc) 
        MessageRequester("Error","Empty ROW",#MB_OK|#MB_ICONERROR)        
      Else
        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)
          SetGadgetItemColor(0,OLdr,#PB_Gadget_FrontColor,#Black ,Oldc)
          SetGadgetItemColor(0,Oldr, #PB_Gadget_BackColor, LIColor,Oldc)
          SetGadgetItemColor(0,pInfo\iItem,#PB_Gadget_FrontColor,#White ,pInfo\iSubItem)
          SetGadgetItemColor(0,pInfo\iItem, #PB_Gadget_BackColor,GetSysColor_(#COLOR_HIGHLIGHT),pInfo\iSubItem)
        EndIf    
        Oldr = pInfo\iItem
        Oldc = pInfo\iSubItem
        editflag = 0 
      EndIf      
      
    Case #WM_LBUTTONDBLCLK      
      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        
      pInfo.LVHITTESTINFO
      pInfo\pt\x = (lParam & $FFFF) 
      pInfo\pt\y = (lParam>> 16 & $FFFF)                    
      SendMessage_(ListIcon,#LVM_SUBITEMHITTEST,0,@pInfo)
      row = pInfo\iItem
      col = pinfo\iSubItem
      If  row = 0 Or row = 4 Or (row = 2 And col = 2)
        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
      
    Case #WM_VSCROLL,#WM_HSCROLL
      MoveWindow_(GadgetID(2),0,0,0,0,1)
      MoveWindow_(GadgetID(5),0,0,0,0,1)
      SetGadgetItemColor(0,OLdr,#PB_Gadget_FrontColor,#Black ,Oldc)
      SetGadgetItemColor(0,Oldr, #PB_Gadget_BackColor, LIColor,Oldc)
      
      
  EndSelect
  ProcedureReturn result
EndProcedure

Procedure sizeCB()
  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,460,"Column 0",200,#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)
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))
AddKeyboardShortcut(0, #PB_Shortcut_Return, 15)
AddKeyboardShortcut(0, #PB_Shortcut_Escape, 20)
BindEvent(#PB_Event_SizeWindow ,@sizeCB())
Repeat
  Select WaitWindowEvent()
      
    Case #PB_Event_CloseWindow
      Quit = 1
      
    Case #PB_Event_Menu    
      Select EventMenu()
        Case 15
          If GetActiveGadget() = 2
            SetGadgetItemText(0, 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(0, Oldr,GetGadgetText(2),Oldc)
        MoveWindow_(GadgetID(2),0,0,0,0,1)
        editflag = 0
      EndIf      
      
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 5
          MoveWindow_(GadgetID(5),0,0,0,0,1)
          SetGadgetItemText(0, Oldr,GetGadgetText(5),Oldc)             
      EndSelect          
      
  EndSelect 
  
Until Quit = 1
End
Edit : Updated
Last edited by RASHAD on Sun Oct 13, 2024 8:28 am, edited 5 times in total.
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,

Thanks, it works well. I see there are quite a lot of changes made.

I need to prevent a user from modifying input values in some cases, such as if an order line has been despatched. I'll play with it further.

Best, Jim
PBJim
Enthusiast
Enthusiast
Posts: 294
Joined: Fri Jan 19, 2024 11:56 pm

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by PBJim »

Hi Rashad,

I tried to fix this but can't see where it's happening — if you choose a drop down option in column 4, every time you then single left click another line in that column, it always displays the data from the previous line, instead of the data (or blank value) of the line clicked.

Image

In this screen, I chose "Combobox item 1" in line 2, then single-clicked line 10. "Combobox item 1" appears although the data should be empty.

2. Is there a way to prevent the line ComboBoxGadget(5,0,0,0,0,#WS_CLIPSIBLINGS) from causing the ListIconGadget to occupy the full width of the window? Removing the line shows its effect, but increasing its width just creates the unwanted effect of a non-hidden field in the top-left corner.

Thanks,
Jim
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by RASHAD »

SetGadgetText(): Set the displayed text. If the ComboBoxGadget is not editable, the text must be in the dropdown list.

Code: Select all

.
.

   Case #WM_VSCROLL,#WM_HSCROLL
      MoveWindow_(GadgetID(2),0,0,0,0,1)
      MoveWindow_(GadgetID(5),0,0,0,0,1)            
      SetGadgetText(5,"")  
      SetGadgetItemColor(0,OLdr,#PB_Gadget_FrontColor,#Black ,Oldc)
      SetGadgetItemColor(0,Oldr, #PB_Gadget_BackColor, LIColor,Oldc)
.
.
ComboBoxGadget(5,0,0,0,0,#PB_ComboBox_Editable |#WS_CLIPSIBLINGS)
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 »

Thanks again Rashad, it's certainly interesting what can be achieved. Getting it to behave just as required will take more time I think, especially with the combobox column.

It would be nice if this was a dedicated gadget in PureBasic. I saw that Visual Basic offers the data grid control, which is an editable version of the view-only FlexGrid. https://ibb.co/dGX7RcL
User avatar
jacdelad
Addict
Addict
Posts: 1991
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by jacdelad »

This only works for Windows, so it surely won't happen. Anyway, you can build a module from it or simply an include file to make it available.
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
PBJim
Enthusiast
Enthusiast
Posts: 294
Joined: Fri Jan 19, 2024 11:56 pm

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by PBJim »

Is it possible, Rashad, to disallow editing of a given line, if there is nothing in column 0 for that line? At the moment, if we attempt to edit a cell on a line containing no values, it instead edits the column heading.

Image
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by RASHAD »

Previous post updated
Row 0 and Row 4 and Cell (Row 2 Col 2) forbid editing

Code: Select all

      If  row = 0 Or row = 4 Or (row = 2 And col = 2)
        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
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 »

Thanks Rashad, but it's become really buggy. Just clicking on cells without changing anything and it's picking up other values...

Image
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: ComboBoxGadget in Editable ListIconGadget [Windows]

Post by RASHAD »

Sorry
I deleted editflag = 0 by mistake :wink:
Previous post updated also for resizing
Egypt my love
Post Reply