Editing cells in ListIcons (updated for Vista)

Share your advanced PureBasic knowledge/code with the community.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5357
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Editing cells in ListIcons (updated for Vista)

Post by Kwai chang caine »

Hey MASTER !!!!!
So happy to talk to you :D
Image

- First, i want to thanks you for your rapid fix, it works perfectly

- Second, i want to thanks you very much for this splendid library i use each time i need a listicon editable 8)

- Third, never you imagine what your servant dare to do ???? :shock:
He have adding three cowpat functions into the splendid jewel code of his favorite MASTER :?
And you know what ???? that works !!!! :lol: (so i hope :oops:)

KCC have adding :oops:

Code: Select all

; First function
Debug LigneSelection(#ListIcon) ; Return the number of the line selected

; Second function
Debug CaseEditable(1, 1) ; Return the state of the cell (#True the cell is editable or #False the cell is not editable)
CaseEditable(1, 1, #False) ; Make the cell row1/Line1 not editable
CaseEditable(1, 1, #True) ; Make the cell row1/Line1 editable

; Third function
ColonneEditable(1) ; Return the state of the column 1 (#True the collumn 1 is editable or #False the column 1 is not editable)
ColonneEditable(1, #False) ; Make the full column 1 not editable
ColonneEditable(1, #True) ; Make the full column 1 editable
------------------------------------------ ATTENTION -------------------------------------------
If a kind member have the courage to use this code and is harmed....the "KCC corporation society" decline all responsability :mrgreen:

Code: Select all

;'Edit ListIcon'.
;-----------------
;   MASTER Author : Stephen Rodriguez.
;   Blaster author : KCC [ Adding LigneSelection() + CaseEditable() + ColonneEditable() ]
;   Created with Purebasic 4.02 for Windows (date:  May 2007).
;   Maintained with PB 4.4.

;   Platforms:  Windows (tested on XP and Vista 32-bit).

;   Licence: DAYLike
;     (Do As You Like with it! - No Warranties!) AND AGAIN MORE AFTER KCC HAVE ADDING HIS COWPAT FUNCTIONS !!!
;     A credit to myself, whilst nice, is not absolutely necessary.

;*******************************************************************************************

;NOTES.
;------
; 1)  Register a listicon gadget to have editable cells by using the command SetListIconEditable(listID).
;     You MUST set up such listicons to have a column zero of zero width.
; 2)  Cells are made editable by intercepting double-clicks, setting the #LVS_EDITLABELS style,
;     repositioning the edit control which Windows uses to edit the labels in column zero and copying
;     the resulting text to the listicon cell.
; 3)  Cells can also be edited by means of the command EditCell().
;*******************************************************************************************

#LVM_SUBITEMHITTEST = #LVM_FIRST+57 
#LVM_GETSUBITEMRECT = #LVM_FIRST+56 
#LVM_GETHEADER = #LVM_FIRST+31 
#EC_RIGHTMARGIN = 2 

Structure _LIEdit ; ListIcon editable
 listOldProc.l 
 editHwnd.l 
 item.l 
 subitem.l 
 x.l 
 y.l 
 cx.l 
 cy.l 
EndStructure

Structure Cellule
 Col.i
 Lig.i
EndStructure

Declare.l SetListIconEditable(listID) 
Declare.l _LIEwinProc(hWnd, uMsg, wParam, lParam) 
Declare.l _LIEListProc(hWnd, uMsg, wParam, lParam) 
Declare.l _LIEeditProc(hWnd, uMsg, wParam, lParam)

Global NewList ListCasesNonEditables.Cellule()
Global Dim TabloColonneNonEditables(0)

Procedure LigneSelection(PbIdListIcon) ; Créée par Kcc
 
 PInfo.LVHITTESTINFO
 hWnd = GadgetID(PbIdListIcon)
 GetCursorPos_(@PInfo\pt)
 MapWindowPoints_(0, hWnd,  @PInfo\pt, 1)
 SendMessage_(hWnd, #LVM_SUBITEMHITTEST, 0, PInfo)
 ProcedureReturn PInfo\iItem
 
EndProcedure

Procedure CaseEditable(Colonne, Ligne, Editable = -1) ; Créée par Kcc
 
 ; Editable = #False (N'est plus editable)
 ; Editable = #True (Devient editable)
 ; Editable = -1 (Demande l'état de la case == > Retourne 1 si la case est editable et 0 si elle ne l'est pas)
 
 Select Editable
  
  Case #False
  
   AddElement(ListCasesNonEditables())
   ListCasesNonEditables()\Col = Colonne
   ListCasesNonEditables()\Lig = Ligne
  
  Case #True
  
   ForEach ListCasesNonEditables()
    
    If ListCasesNonEditables()\Col = Colonne And ListCasesNonEditables()\Lig = Ligne
     DeleteElement(ListCasesNonEditables())
    EndIf 
   
   Next
   
  Case -1
  
   NonEditable = #False
  
   ForEach ListCasesNonEditables()
      
    If ListCasesNonEditables()\Col = Colonne And ListCasesNonEditables()\Lig = Ligne
     NonEditable = #True
     Break
    EndIf 
   
   Next
   
   ProcedureReturn Bool(Not NonEditable)
  
 EndSelect  
   
EndProcedure

Procedure ColonneEditable(Colonne, Editable = -1) ; Créée par Kcc
 
 ; Editable = #False (La colonne complete n'est plus editable)
 ; Editable = #True (La colonne complete devient editable)
 ; Editable = -1 (Demande l'état de la colonne complete == > Retourne 1 si la colonne est editable et 0 si elle ne l'est pas)
  
 Select Editable
  
  Case #False
      
   TabloColonneNonEditables(Colonne) = #True
  
  Case #True
  
   TabloColonneNonEditables(Colonne) = #False
   
  Case -1
 
   ProcedureReturn Bool(Not TabloColonneNonEditables(Colonne))
  
 EndSelect  

EndProcedure

Procedure.l SetListIconEditable(listID) ; ListIcon editable (Returns zero if an error)
  Protected result, parenthWnd, *mem._LIEdit, hWnd 
  ;Check that listID references a valid listicon. 
    If IsGadget(listID) And GadgetType(listID)=#PB_GadgetType_ListIcon
      
      hWnd = GadgetID(listID)
      numcols = SendMessage_(SendMessage_(hWnd,#LVM_GETHEADER,0,0), #HDM_GETITEMCOUNT,0,0) ; Rajout KCC
      ReDim TabloColonneNonEditables(numcols) ; Rajout KCC
            
      ;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 

ProcedureDLL EditCell(listID, item, subitem) ; ListIcon editable (Sets the specified cell To be edited)
  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 
              SetWindowLong_(hWnd, #GWL_STYLE, GetWindowLong_(hWnd, #GWL_STYLE)|#LVS_EDITLABELS) 
              SetActiveGadget(listID) 
              SendMessage_(hWnd, #LVM_EDITLABEL, item, 0) 
            EndIf 
        EndIf 
    EndIf 
EndProcedure 
 
Procedure.l _LIEwinProc(hWnd, uMsg, wParam, lParam) ; ListIcon editable (Window proc of the ListIcon parent window)
  Protected result, oldwinproc, *nmh. NMHDR, listhWnd, edithWnd, *liedit._LIEdit, *lvd.LV_DISPINFO, rc.RECT 
  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 
              InvalidateRect_(listhWnd,0,1) 
              UpdateWindow_(listhWnd) 
              SetWindowLong_(listhWnd, #GWL_STYLE, GetWindowLong_(listhWnd, #GWL_STYLE)&~#LVS_EDITLABELS) 
            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 

Procedure.l _LIEListProc(hWnd, uMsg, wParam, lParam) ; ListIcon editable (Window proc of the ListIcon)
  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 
        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 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 2 LINES FOR THOSE CELLS WHICH ARE TO BE EDITED.

       If CaseEditable(PInfo\iSubItem, PInfo\iItem) And Not TabloColonneNonEditables(PInfo\iSubItem)
        SetWindowLong_(hWnd, #GWL_STYLE, GetWindowLong_(hWnd, #GWL_STYLE)|#LVS_EDITLABELS) 
        SendMessage_(hWnd, #LVM_EDITLABEL, PInfo\iItem, 0)
       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 

Procedure.l _LIEeditProc(hWnd, uMsg, wParam, lParam) ; ListIcon editable (Window proc of the edit control)
  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\cy=*liedit\cy+3 
      *wpos\x=*liedit\x 
      *wpos\y=*liedit\y-2 
      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 

Procedure UnSetListIconEditable(listID)
  Protected hWnd, *mem._LIEdit
  If IsGadget(listID) And GadgetType(listID)=#PB_GadgetType_ListIcon
    hWnd = GadgetID(listID)
    *mem = GetProp_(hWnd, "_LIEdit")
    If *mem
      SendMessage_(hWnd, #LVM_EDITLABEL, 0, 0)
      SetWindowLongPtr_(hWnd, #GWL_WNDPROC, *mem\listOldProc)
      FreeMemory(*mem)
      RemoveProp_(hWnd, "_LIEdit")
    EndIf
  EndIf
EndProcedure

CompilerIf #PB_Compiler_IsMainFile

 #ListIcon = 1
 
 OpenWindow(0, 100, 100, 600, 600, "ListIcon Example", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
 ListIconGadget(#ListIcon, 5, 5, 490, 390, "", 0, #PB_ListIcon_GridLines)
 
 ; Creation des colonnes
 For i = 1 To 5
  AddGadgetColumn(#ListIcon, i, "Col " + Str(i), 100)
 Next
 
 ; Ecriture dans les cellules
 For row = 1 To 2
  
  AddGadgetItem(#ListIcon, -1, "")

  For col = 1 To 5
   SetGadgetItemText(#ListIcon, row - 1, "row " + Str(row - 1) + ", col " + Str(col), col)
  Next
 
 Next
 
 ; Rendre les cellules editables sans ecrire (Juste ajouter une ligne vide)
 For row = 3 To 20
  AddGadgetItem(#ListIcon, -1, "")
 Next
 
 SetListIconEditable(#ListIcon)
 
 ; Donner le focus à une cellule
 EditCell(#ListIcon, 1,3)
 
 ; Retourne le numero de la ligne sélectionnée
 Debug LigneSelection(#ListIcon)
 
 ; Rendre une cellule non editable
 Debug CaseEditable(1, 1)
 CaseEditable(1, 1, #False) ; N'est plus éditable
 Debug CaseEditable(1, 1)
 CaseEditable(1, 1, #True) ; Redevient editable
 Debug CaseEditable(1, 1)
 
 ; Rendre la ListIcon non editable (Plante)
 UnSetListIconEditable(#ListIcon)
  
 Repeat
  Event = WaitWindowEvent()
 Until Event = #PB_Event_CloseWindow
  
CompilerEndIf
ImageThe happiness is a road...
Not a destination
User avatar
dobro
Enthusiast
Enthusiast
Posts: 766
Joined: Sun Oct 31, 2004 10:54 am
Location: France
Contact:

Re: Editing cells in ListIcons (updated for Vista)

Post by dobro »

cette librairie ne fonctionne plus avec Pb 5.42
j'ai une erreur : @_LIEListProc() n'est pas déclarée !
*********************************************
this library is no longer working with Pb 5.42
I get an error: @_LIEListProc() is not declared!

I fail to compile ...

Thanks
Image
Windows 98/7/10 - PB 5.42
■ sites : http://michel.dobro.free.fr/
infratec
Always Here
Always Here
Posts: 6883
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Editing cells in ListIcons (updated for Vista)

Post by infratec »

Hi dobro,

I just took KCCs extended version and it works with 5.42 x86 on win x64 without problems.
I only had to comment out

Code: Select all

UnSetListIconEditable(#ListIcon)
:mrgreen:

Bernd
User avatar
dobro
Enthusiast
Enthusiast
Posts: 766
Joined: Sun Oct 31, 2004 10:54 am
Location: France
Contact:

Re: Editing cells in ListIcons (updated for Vista)

Post by dobro »

arf !!!
I do not know why, just now
it did not compile ....

now it works .. ^^ Image
Image
Windows 98/7/10 - PB 5.42
■ sites : http://michel.dobro.free.fr/
User avatar
dobro
Enthusiast
Enthusiast
Posts: 766
Joined: Sun Oct 31, 2004 10:54 am
Location: France
Contact:

Re: Editing cells in ListIcons (updated for Vista)

Post by dobro »

no, really, I insist !! Image

1 - uninstall the library in the folder USERLIB of your Pb 5.42

copy - paste the Last code of KCC .... Or Srod Code

run the prg

i try with 2 different editors I

reported an error 1 about the procedure: AbortFTPFile (hWnd, uMsg, wParam, lParam) .. Exist in PB 5.42... solution : rename

a reported error 2 about the procedure:
ListViewGadget (PbIdListIcon); Created by Kcc (ok , the name of this function is an function Purebasic.. solution: rename)

and after you rename these two procedures in
AbortFTPFile2 ()
ListViewGadget2 ()

a new error occurs:
_LIEwinProc () Is not declared !!!

look here
https://www.youtube.com/watch?v=PbluuGzpQZE
Last edited by dobro on Thu Jun 30, 2016 8:55 am, edited 1 time in total.
Image
Windows 98/7/10 - PB 5.42
■ sites : http://michel.dobro.free.fr/
Post Reply