Comment créer un ListIconGadget éditable ?
Comment créer un ListIconGadget éditable ?
Est-il possible, dans un ListIconGadget, de laisse l'utilisateur modifier directement une valeur affichée ?
Tant que j'y suis, est-il possible de préselectionner le texte quand on clique sur un gadget de type StringGadget pour accélerer la saisie ?
Merci d'avance
Tant que j'y suis, est-il possible de préselectionner le texte quand on clique sur un gadget de type StringGadget pour accélerer la saisie ?
Merci d'avance
Salut,
ça, c'est un code srod. N'hésite pas à lui poser quelques questions dessus sur le forum anglais. Moi, j'y pige rien alors je fais mon propre tableau éditable sans Gadget. Les Chr(10) pour séparer les colonnes, c'est un peu Hard...
ça, c'est un code srod. N'hésite pas à lui poser quelques questions dessus sur le forum anglais. Moi, j'y pige rien alors je fais mon propre tableau éditable sans Gadget. Les Chr(10) pour séparer les colonnes, c'est un peu Hard...
Code : Tout sélectionner
;'Edit ListIcon'.
;-----------------
; Stephen Rodriguez.
; Created with Purebasic 4.02 for Windows.
;
; Date: May 2007.
;
; Platforms: Windows.
; Licence: DAYLike
; (Do As You Like with it! - No Warranties!)
; 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
EnableExplicit
DeclareDLL.l SetListIconEditable(listID)
Declare.l _LIEwinProc(hWnd, uMsg, wParam, lParam)
Declare.l _LIEListProc(hWnd, uMsg, wParam, lParam)
Declare.l _LIEeditProc(hWnd, uMsg, wParam, lParam)
Structure _LIEdit
listOldProc.l
editHwnd.l
item.l
subitem.l
x.l
y.l
cx.l
cy.l
EndStructure
;Returns zero if an error.
ProcedureDLL.l SetListIconEditable(listID)
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)
;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.
ProcedureDLL 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
SetWindowLong_(hWnd, #GWL_STYLE, GetWindowLong_(hWnd, #GWL_STYLE)|#LVS_EDITLABELS)
SetActiveGadget(listID)
SendMessage_(hWnd, #LVM_EDITLABEL, item, 0)
EndIf
EndIf
EndIf
EndProcedure
;Window proc of the ListIcon parent window.
Procedure.l _LIEwinProc(hWnd, uMsg, wParam, lParam)
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
;Window proc of the ListIcon.
Procedure.l _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
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.
SetWindowLong_(hWnd, #GWL_STYLE, GetWindowLong_(hWnd, #GWL_STYLE)|#LVS_EDITLABELS)
SendMessage_(hWnd, #LVM_EDITLABEL, PInfo\iItem, 0)
;*****************************************************************************************
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.l _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\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
;XIncludeFile "Edit ListIcon.pbi"
DisableExplicit
LoadFont(1, "Arial",10)
If OpenWindow(0, 100, 100, 600, 600, "ListIcon Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If CreateGadgetList(WindowID(0))
ListIconGadget(1, 5, 5, 490, 390, "", 0)
SetGadgetFont(1, FontID(1))
For i = 1 To 10
AddGadgetColumn(1, i, "Col "+Str(i), 100)
Next
For row = 1 To 100
AddGadgetItem(1,-1,"")
For col = 1 To 10
SetGadgetItemText(1, row-1, "row "+Str(row-1)+", col "+Str(col), col)
Next
Next
SetListIconEditable(1)
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf
EndIf
Salut et merci pour ta réponse Ollivier, je vais déjà essayer de piger ça.
Pour le moment, j'en étais réduit à ouvrir une nouvelle fenêtre ne contenant qu'un StringGadget prérempli avec la valeur à modifier, puis à refermer cette fenêtre après modification et réintégrer cette valeur dans ma ListIcon
A+
Pour le moment, j'en étais réduit à ouvrir une nouvelle fenêtre ne contenant qu'un StringGadget prérempli avec la valeur à modifier, puis à refermer cette fenêtre après modification et réintégrer cette valeur dans ma ListIcon

A+
Comme ça, c'est pas plus simple?
Code : Tout sélectionner
OpenWindow(0,200,200,500,400,"Tableau créé avec des StringGadget")
CreateGadgetList(WindowID(0))
For i=0 To 4
For j=0 To 7
gdg=gdg+1
StringGadget(gdg,(i*80)+20,(j*20)+20,80,20,Str(Random(5000)),#PB_Text_Right)
Next j
Next i
Repeat
event=WaitWindowEvent()
Until event=#PB_Event_CloseWindow
End
Si l'idée d'utiliser une librarie ne vous dérange pas, vous pouvez utiliser la version 'Plus' de ma librairie PureLVSORT pour PB4.0x/4.1x.
Voici un exemple qui transforme certaines colonnes d'un listicongadget en cellules éditables, avec un callback [facultatif] qui permet de contrôler la saisie.
J'ai ajouté des commentaires en français.
Voici un exemple qui transforme certaines colonnes d'un listicongadget en cellules éditables, avec un callback [facultatif] qui permet de contrôler la saisie.
J'ai ajouté des commentaires en français.
Code : Tout sélectionner
;
; PureLVSORT listicon editing example
;
Procedure.l MyEditCallback(Event.l, ListIconNumber.l, Column.l, Row.l, Text.s)
Debug "*** EDITING CALLBACK"
Select Event
Case #PureLVSORT_EditStart
Debug "ListIcon = " + Str(ListIconNumber)
Debug "Column = " + Str(Column)
Debug "Row = " + Str(Row)
Debug "-> Editing started"
;
; Return : - 0 to enable stringgadget
; - *string to enable spingadget [the string holds the choice items]
;
If Column = 2
; Pour la colonne 2, on veut un spingadget avec les valeurs 700|800|900|1000
ProcedureReturn @"700|800|900|1000"
Else
; Pour les autres colonnes, c'est un stringgadget
ProcedureReturn 0
EndIf
Case #PureLVSORT_EditText
Debug "ListIcon = " + Str(ListIconNumber)
Debug "Column = " + Str(Column)
Debug "Row = " + Str(Row)
Debug "-> Text = " + Text
;
; Return : - 0 to keep the text
; - *string to change the text [the string holds the changed text]
;
; Voici un exemple comment contrôler la saisie d'une chaîne
If Text = "Change this text" ; si le texte saisi est celui-ci
ProcedureReturn @"to another text" ; on l'échange avec celui-là
EndIf
Case #PureLVSORT_EditEnd
Debug "Editing ended"
Case #PureLVSORT_EditEscape
Debug "Editing cancelled"
EndSelect
Debug "******************"
EndProcedure
;
#Window_0 = 0
#ListIcon_0 = 0
Procedure Open_Window_0()
If OpenWindow(#Window_0, 0, 0, 602, 302, "PureLVSORT Make Editable Test", #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered | #PB_Window_MaximizeGadget| #PB_Window_MinimizeGadget | #PB_Window_SizeGadget)
If CreateGadgetList(WindowID(#Window_0))
ListIconGadget(#ListIcon_0, 5, 5, 590, 255, "String", 100)
AddGadgetColumn(#ListIcon_0, 1, "Numeric", 110)
AddGadgetColumn(#ListIcon_0, 2, "Float", 110)
AddGadgetColumn(#ListIcon_0, 3, "DateDDMMYYYY", 120)
AddGadgetColumn(#ListIcon_0, 4, "DateMMDDYYYY", 120)
AddGadgetColumn(#ListIcon_0, 5, "DateMMDDYYYY", 120)
AddGadgetItem(#ListIcon_0, -1, "ABCDE" + Chr(10) + "514" + Chr(10) + "1000" + Chr(10) + "31/12/2004" + Chr(10) + "12/31/2004" + Chr(10) + "12/31/2004")
AddGadgetItem(#ListIcon_0, -1, "ACDEF" + Chr(10) + "118" + Chr(10) + "700" + Chr(10) + "11/12/2004" + Chr(10) + "12/11/2004" + Chr(10)+ "12/11/2004")
AddGadgetItem(#ListIcon_0, -1, "ZABCD" + Chr(10) + "-414" + Chr(10) + "800" + Chr(10) + "21/01/2003" + Chr(10) + "01/21/2003" + Chr(10)+ "12/11/2004")
For n=1 To 25
AddGadgetItem(#ListIcon_0, -1, "DEFGH" + Chr(10) + "extra entry "+Str(n) + Chr(10) + "900" + Chr(10) + "10/06/2001" + Chr(10) + "06/10/2001" + Chr(10)+ "12/11/2004")
Next
PureRESIZE_SetGadgetResize(#ListIcon_0, 1, 1, 1, 1)
EndIf
EndIf
EndProcedure
Open_Window_0()
; ListIcon Sort Setup
If PureLVSORT_SelectGadgetToSort(#ListIcon_0, #PureLVSORT_ShowClickedHeader_IconLeft) = #PureLVSORT_Ok
PureLVSORT_SetColumnFlag(#ListIcon_0, 0, #PureLVSORT_Column_Hidden) ; Hide column 0
PureLVSORT_SetColumnType(#ListIcon_0, 0, #PureLVSORT_String)
PureLVSORT_SetColumnType(#ListIcon_0, 1, #PureLVSORT_Numeric)
PureLVSORT_SetColumnType(#ListIcon_0, 2, #PureLVSORT_Float)
PureLVSORT_SetColumnType(#ListIcon_0, 3, #PureLVSORT_DateDDMMYYYY)
PureLVSORT_SetColumnType(#ListIcon_0, 4, #PureLVSORT_DateMMDDYYYY)
PureLVSORT_SetLastColumnAutoResize(#ListIcon_0, #True)
; //////////////////////// Double-cliquer sur une cellule pour l'éditer
PureLVSORT_MakeColumnEditable(#ListIcon_0, 1, #True) ; La colonne 1 est éditable
PureLVSORT_MakeColumnEditable(#ListIcon_0, 2, #True) ; La colonne 2 est éditable
PureLVSORT_SetEditingColors(#Red, #White) ; Définir la couleur des zones éditables
PureLVSORT_SetEditingCallback(@MyEditCallback()) ; Callback pour contrôler l'édition des cellules (facultatif)
; ////////////////////////
EndIf
;
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_Gadget
EndSelect
Until Event = #PB_Event_CloseWindow
End
- Kwai chang caine
- Messages : 6989
- Inscription : sam. 23/sept./2006 18:32
- Localisation : Isere
@OLLIVIERFaut que j'arrête de balancer quelque chose qui n'est pas à moi et qui fait plus de 10 lignes. C'est carrément pas judicieux...
Je ne suis pas de ton avis, cette fois le code que tu as donné est plus long, mais il n'a pas tout à fait le meme effet.
En plus si je ne me trompe, banban73 avait demandé dans un listicongadget donc, je pense qu'au contraire tu avais tout juste.

L'important c'est que tu tende la main, si tu avais cette solution, c'est bien, si quelqu'un fait plus simple, tant mieux.
En attendant banban se fait aider et il a plusieures solutions, au lieu de se morfondre tout seul à se tirer les cheveux, maintenant à lui de voir celle qu'il prefere.
Il peut, grace à vous deux, se rendre compte que sur le forum on s'occupe de lui, et c'est aussi tres important.
Et qu'il peut y avoir moulte solution à un seul probleme.

C'est ce qui m'a plu avec DOBRO et CPL.BATOR quand je suis arrivé

Oups, un oubli ...RV a écrit :Par contre il m'a fallu installer la lib PureResize pour une ligne qui se trouve dans la procedure Open_Window_0()PureRESIZE_SetGadgetResize(#ListIcon_0, 1, 1, 1, 1)
Elle permet le redimensionnement automatique de #ListIcon_0 quand on redimensionne la fenêtre, dans le but de tester la fonction PureLVSORT_SetLastColumnAutoResize().RV a écrit :A quoi sert au juste cette ligne?
C'est un de mes codes de test de la librarie.
Salut et merci à tous pour vos réponses.
Ne t'inquiète pas Ollivier, ce n'est pas la longueur du code qui m'a fait fuir
, c'est juste que je n'ai malheureusement pas eu beaucoup de temps libre ces derniers jours.
Effectivement le tableau avec les stringgadgets (Meci RV) m'a l'air bien plus simple dans mon cas mais je garde les autres (Merci à Gnozal aussi) dans un coin de mon disque dur au cas où. J'ai la flemme de modifier mon source pour y intégrer une gestion plus poussée pour le moment (je m'y perds déjà assez !).
Effectivement, c'est réconfortant d'être aidé de la sorte. C'est vraiment sympa ! Et pis les codes bien longs, ça oblige à réfléchir un minimum au lieu de copier-coller bêtement.
Ciao
Ne t'inquiète pas Ollivier, ce n'est pas la longueur du code qui m'a fait fuir

Effectivement le tableau avec les stringgadgets (Meci RV) m'a l'air bien plus simple dans mon cas mais je garde les autres (Merci à Gnozal aussi) dans un coin de mon disque dur au cas où. J'ai la flemme de modifier mon source pour y intégrer une gestion plus poussée pour le moment (je m'y perds déjà assez !).
Effectivement, c'est réconfortant d'être aidé de la sorte. C'est vraiment sympa ! Et pis les codes bien longs, ça oblige à réfléchir un minimum au lieu de copier-coller bêtement.
Ciao