PB 5.20 Listicongadget simples Edit als Modul

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

PB 5.20 Listicongadget simples Edit als Modul

Beitrag von hjbremer »

Hier mal als Modul, only Windows wegen der vielen Api Befehle, die nötig sind, da in PB immer noch sehr viel fehlt. :)

Doppelclick auf eine Zelle = Edit

Taste entf + einfg mit/ohne Shift werden unterstützt

ebenfalls externes auswerten der Eingaben

Das ganze läßt sich natürlich erweitern, aber das bleibt bei Bedarf jedem selbst überlassen
Ist dann aber nicht mehr Simpel :mrgreen:

Code: Alles auswählen

; 07.09.2013 - PB 5.20 beta 17 Windows x86

DeclareModule ListIconGadgetEdit
   ; Alle Elemente in diesem Abschnitt sind für den Zugriff von außerhalb verfügbar
   
   Declare ListIconGadgetEdit(lvnr, window, ptr = 0)
   
   #my_EventType_EditEnd = #PB_Event_FirstCustomValue + 10
   
EndDeclareModule

Module ListIconGadgetEdit   
   ; Alle Elemente in diesem Abschnitt sind privat. Alle Namen können ohne
   ; Namenskonflikt auch woanders verwendet werden.
   
   Structure EditStruktur
      lvnr.i               ;ListIconGadget PBnr
      lvpt.i               ;Pointer Ori WndProc
      item.i               ;Zeile
      subitem.i            ;Spalte
      header.i             ;Header Id
      strgnr.i             ;Stringgadget PBnr
      strgid.i
      strgpt.i             ;Pointer Ori WndProc
      editflag.i           ;wenn 1 im Editmode
      oldtext.s
      newtext.s
      checktext.i        ; einen Pointer;  0 für keinen Check;  1 für Eventtype
      StructureUnion       ;um lParam in Hi + Loword zu zerlegen, nur für Mouseposi
         lparam.i          ; lParam vom Callback
         points.points     ; aufgeteiltes lParam in x + y
      EndStructureUnion   
   EndStructure
   
   Prototype p_checktext(nr, item, subitem, old$, new$)
   
   Global CheckText.p_checktext
   
   EnableExplicit
   
   Macro Edit_End(p)
      If p\editflag
         p\editflag = 0
         p\oldtext = GetGadgetItemText(p\lvnr, p\item, p\subitem)
         p\newtext = GetGadgetText(p\strgnr)
         SetGadgetItemText(p\lvnr, p\item, p\newtext, p\subitem)
         HideGadget(p\strgnr, 1) 
         SetGadgetState(p\lvnr, p\item)
         ;Check
         If p\checktext = 1
            PostEvent(#PB_Event_Gadget, EventWindow(), p\lvnr, #my_EventType_EditEnd)
         ElseIf p\checktext > 1
            CheckText = p\checktext
            If CheckText(p\lvnr, p\item, p\subitem, p\oldtext, p\newtext) = #False
               SetGadgetItemText(p\lvnr, p\item, p\oldtext, p\subitem)
            EndIf            
         EndIf         
      EndIf
   EndMacro
   
   Macro Edit_Esc(p)
      If p\editflag
         p\editflag = 0
         HideGadget(p\strgnr, 1)   
         SetGadgetState(p\lvnr, p\item)
      EndIf
   EndMacro
   
   Procedure.s ListIconGadgetGetItem(lvnr, iitem)      
      Protected j
      Protected head = SendMessage_(GadgetID(lvnr), #LVM_GETHEADER, 0, 0)
      Protected cols = SendMessage_(head, #HDM_GETITEMCOUNT, 0, 0)
      Protected item$ = GetGadgetItemText(lvnr, iitem, 0)  
      
      For j = 1 To cols -1
         item$ + #TAB$ + GetGadgetItemText(lvnr, iitem, j)
      Next
      item$ + #CR$  
      
      ProcedureReturn item$
   EndProcedure
   
   Procedure.i CallBackLv(hwnd, msg, wParam, lParam) 
      ;hwnd ist die ID vom Gadget
      
      Protected *lv.EditStruktur = GetWindowLongPtr_(hwnd, #GWL_USERDATA)   
      
      With *lv      
         
         Protected hitinfo.LVHITTESTINFO
         Protected rect.RECT
         Protected *nm.NMHDR
         Protected j, x, y, br, hh, txt$, txtbr      
         Protected index, shift
         Protected itemcount
         Protected lvwidth = GadgetWidth(\lvnr) - 6   ;Rahmen abziehen 
         
         ;Scrollbar vorhanden ?
         If GetWindowLongPtr_(hwnd, #GWL_STYLE) & #WS_VSCROLL
            lvwidth - GetSystemMetrics_(#SM_CXVSCROLL) 
         EndIf
                  
         Static item$   ;für Insert
         
         Select msg 
            Case #WM_MOUSEMOVE
               ;#WM_MOUSEMOVE Abfrage extra für F2
               ;sonst könnte man lparam von #WM_LBUTTONDBLCLK nehmen
               If \editflag = 0
                  \lparam = lparam    ;Mouseposi: Hi+Loword stehen in \points\x + y
               EndIf            
               
            Case #WM_LBUTTONDBLCLK            
               ;zuerst Endemacro aufrufen
               Edit_End(*lv)                  
               ;LBUTTONDBLCLK auf welches Subitem (points kommt von #WM_MOUSEMOVE)    
               hitinfo\pt\x = \points\x      ;von #WM_MOUSEMOVE siehe EditStruktur
               hitinfo\pt\y = \points\y  
               SendMessage_(hwnd, #LVM_SUBITEMHITTEST, 0, hitinfo)
               \item = hitinfo\iitem
               \subitem = hitinfo\iSubItem
               ;Subitem Größe holen
               rect\top = \subitem          
               rect\left = #LVIR_LABEL
               SendMessage_(hwnd, #LVM_GETSUBITEMRECT, \item, rect)
               ;verschieben horizontal?
               If rect\left < 0
                  SendMessage_(hwnd, #LVM_SCROLL, rect\left - 4, 0)
               ElseIf rect\right > lvwidth
                  SendMessage_(hwnd, #LVM_SCROLL, Abs(lvwidth - rect\right), 0)
               EndIf
               ;rect wieder abfragen, falls verschoben
               rect\top = \subitem
               rect\left = #LVIR_LABEL
               SendMessage_(hwnd, #LVM_GETSUBITEMRECT, \item, rect)
               ;Posi vom Stringgadget + Größe + anzeigen
               x = rect\left + 1 
               y = rect\top + 0
               br = rect\right - rect\left - 1 
               hh = rect\bottom - rect\top - 0
               txt$ = GetGadgetItemText(\lvnr, \item, \subitem)
               txtbr = SendMessage_(hwnd, #LVM_GETSTRINGWIDTH, 0, @txt$) + 15
               If txtbr > br: br = txtbr: EndIf
               If x + br > lvwidth: br = lvwidth - x: EndIf
               ResizeGadget(\strgnr, x, y, br, hh)
               SetGadgetText(\strgnr, txt$)
               SendMessage_(GadgetID(\strgnr), #EM_SETSEL, Len(txt$), -1)  ;Cursor ans Ende
               HideGadget(\strgnr, 0)
               SetActiveGadget(\strgnr)
               SetGadgetState(\lvnr, -1)
               \editflag = 1
               
            Case #WM_VSCROLL, #WM_HSCROLL, #WM_RBUTTONDOWN, #WM_LBUTTONDOWN ;, #WM_NCMOUSELEAVE
               Edit_End(*lv)
               
            Case #WM_NOTIFY   ;vom Header 
               *nm = lparam               
               If *nm\hwndFrom = \header: Edit_End(*lv): EndIf
               
            Case #WM_KEYDOWN  ;: Debug wParam
               Select wParam
                  Case #VK_F2: PostMessage_(hwnd, #WM_LBUTTONDBLCLK, 0, 0)
                     
                  Case #VK_DELETE                     
                     shift = #False
                     If GetKeyState_(#VK_SHIFT) > 1: shift = #True: EndIf
                     If shift = #True: item$ = "": EndIf
                     index = -1
                     itemcount = SendMessage_(hwnd, #LVM_GETSELECTEDCOUNT, 0, 0)
                     For j = 1 To itemcount
                        index = SendMessage_(hwnd, #LVM_GETNEXTITEM, index, #LVNI_SELECTED) 
                        If shift = #True
                           item$ + ListIconGadgetGetItem(\lvnr, index)
                           SetClipboardText(item$)
                        EndIf
                        RemoveGadgetItem(\lvnr, index)
                        index - 1
                     Next
                     SetGadgetState(\lvnr, index + 1)                       
                     
                  Case #VK_INSERT
                     shift = #False
                     If GetKeyState_(#VK_SHIFT) > 1: shift = #True: EndIf                     
                     index = GetGadgetState(\lvnr) 
                     If shift = #False
                        If index = -1 
                           AddGadgetItem(\lvnr, index, "")
                           index = CountGadgetItems(\lvnr) - 1
                        Else
                           AddGadgetItem(\lvnr, index, "")
                        EndIf
                     Else 
                        If index = -1: index = CountGadgetItems(\lvnr): EndIf
                        itemcount = CountString(item$, #CR$)
                        ReplaceString(item$, #TAB$, #LF$, #PB_String_InPlace)
                        For j = 1 To itemcount
                           AddGadgetItem(\lvnr, index + j - 1, StringField(item$, j, #CR$))                    
                        Next
                        SetGadgetState(\lvnr, -1)
                     EndIf                       
                     SetGadgetState(\lvnr, index)
                     
               EndSelect               
               
         EndSelect       
         ProcedureReturn CallWindowProc_(\lvpt, hwnd, msg, wParam, lParam)      
      EndWith
   EndProcedure 
   
   Procedure.i CallBackStrg(hwnd, msg, wParam, lParam) 
      Protected *lv.EditStruktur = GetWindowLongPtr_(hwnd, #GWL_USERDATA)
      If msg = #WM_CHAR            
         Select wparam 
            Case #VK_RETURN: Edit_End(*lv)
            Case #VK_ESCAPE: Edit_Esc(*lv)
         EndSelect
      ElseIf msg = #WM_KEYDOWN
         Select wparam 
            Case #VK_DOWN, #VK_UP: ProcedureReturn 0
         EndSelect
      ElseIf msg = #WM_KILLFOCUS
         Edit_End(*lv)
      EndIf
      ProcedureReturn CallWindowProc_(*lv\strgpt, hwnd, msg, wParam, lParam) 
   EndProcedure 
   
   Procedure.i ListIconGadgetEdit(lvnr, window, ptr = 0)   
      
      Protected *lv.EditStruktur = AllocateMemory(SizeOf(EditStruktur))    
      Protected lvid, oldlist, null.w 
      
      With *lv      
         ;LV
         \lvnr = lvnr: lvid = GadgetID(lvnr)
         \lvpt = GetWindowLongPtr_(lvid, #GWL_WNDPROC)         ;Ori WindowProcPointer holen
         SetWindowLongPtr_(lvid, #GWL_USERDATA, *lv)           ;Memory setzen
         SetWindowLongPtr_(lvid, #GWL_WNDPROC, @CallBackLv())  ;WindowProc setzen
         \header = SendMessage_(lvid, #LVM_GETHEADER, 0, 0)
         ;StringGadget
         oldlist = UseGadgetList(WindowID(window))
         \strgnr = StringGadget(#PB_Any, 0, 0, 0, 0, "") 
         \strgid = GadgetID(\strgnr)         
         \strgpt = GetWindowLongPtr_(\strgid, #GWL_WNDPROC)
         SetGadgetFont(\strgnr, GetGadgetFont(lvnr))
         HideGadget(\strgnr, 1)
         SetParent_(\strgid, lvid) 
         SetWindowLongPtr_(\strgid, #GWL_USERDATA, *lv)
         SetWindowLongPtr_(\strgid, #GWL_WNDPROC, @CallBackStrg())
         If oldlist: UseGadgetList(oldlist): EndIf
         ;div
         \checktext = ptr
         Setwindowtheme_(\strgid, @null, @null)
         SendMessage_(\strgid, #EM_SETMARGINS, #EC_LEFTMARGIN, 3)
      EndWith   
   EndProcedure   
   
EndModule

UseModule ListIconGadgetEdit

; -Test

CompilerIf #PB_Compiler_IsMainFile
   
   Import "UxTheme.lib"
      SetWindowTheme(hwnd, classname.p-unicode, titlename)
   EndImport
   
   Enumeration
      #window   
      #liste1   
      #liste2   
   EndEnumeration
   
   Procedure.i MainEditCheck(nr, item, subitem, old$, new$)
      
      Debug "nr " + nr
      Debug "iitem " + item
      Debug "subitem " + subitem
      Debug "oldtext " + old$
      Debug "newtext " + new$
      
      ProcedureReturn #True
      
   EndProcedure
   
   Procedure.i Mainwindow()
      
      Protected j, event   
      Protected flags = #PB_Window_SystemMenu|#PB_Window_MinimizeGadget
      
      OpenWindow(#window, 150, 150, 700, 600, "", flags)
      
      flags = #PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect
      flags | #PB_ListIcon_MultiSelect   
      
      ListIconGadget(#liste1, 20, 5, 290, 500, "0", 40, flags)
      ListIconGadget(#liste2, 320, 5, 290, 500, "0", 40, flags)
      
      For j = 1 To 3
         AddGadgetColumn(#liste1, j, Str(j), 90)
         AddGadgetColumn(#liste2, j, Str(j), 80)
      Next   
      For j = 0 To 27      
         AddGadgetItem(#liste1, -1, Str(j)+#LF$+"Hans"+#LF$+"Meiereisung"+#LF$+Str(Random(999)))      
         AddGadgetItem(#liste2, -1, Str(j)+#LF$+"Otto"+#LF$+"Leier"+#LF$+Str(Random(999)))      
      Next 
      
      ListIconGadgetEdit(#liste1, #window, @MainEditCheck())
      ListIconGadgetEdit(#liste2, #window, @MainEditCheck())
      SetActiveGadget(#liste1)
      
      SetWindowTheme(GadgetID(#liste1), "explorer", 0)
      
      Repeat: event = WaitWindowEvent()      
      Until event = #PB_Event_CloseWindow 
      
   EndProcedure
   
   Mainwindow()
   
CompilerEndIf
__________________________________________________
Thread verschoben
Windows>Code, Tipps und Tricks
09.09.2013
RSBasic
Zuletzt geändert von hjbremer am 09.09.2013 08:01, insgesamt 1-mal geändert.
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: PB 5.20 Listicongadget simples Edit als Modul

Beitrag von RSBasic »

:allright:
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
dige
Beiträge: 1242
Registriert: 08.09.2004 08:53

Re: PB 5.20 Listicongadget simples Edit als Modul

Beitrag von dige »

Gut gemacht! Danke.
"Papa, ich laufe schneller - dann ist es nicht so weit."
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Re: PB 5.20 Listicongadget simples Edit als Modul

Beitrag von hjbremer »

Falls Interresse, es gibt auch eine Version in der man von Feld zu Feld springen kann und Eingaben verbieten kann. Funktioniert ist aber noch Beta im Test.
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Benutzeravatar
alter Mann
Beiträge: 201
Registriert: 29.08.2008 09:13
Wohnort: hinterm Mond

Re: PB 5.20 Listicongadget simples Edit als Modul

Beitrag von alter Mann »

hjbremer hat geschrieben:Falls Interresse, es gibt auch eine Version in der man von Feld zu Feld springen kann und Eingaben verbieten kann. Funktioniert ist aber noch Beta im Test.
...mein Dank würde Dir ewig hinterherschleichen...
Win11 64Bit / PB 6.0
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Re: PB 5.20 Listicongadget simples Edit als Modul

Beitrag von hjbremer »

alter Mann hat geschrieben:...mein Dank würde Dir ewig hinterherschleichen...
aber nie einholen :D

nun gut, aber folgender Code ist halt nicht mehr simpel

ausführlich getestet werden muß noch der "Trick" mit der Tabtaste. Habe zwar noch keine Probleme festgestellt, aber wer weiß das schon so genau bei Windows.

Code: Alles auswählen

; 10.09.2013 - 5.20 B17 x86

DeclareModule ListIconGadgetEdit
   ; Alle Elemente in diesem Abschnitt sind für den Zugriff von außerhalb verfügbar
   
   Declare ListIconGadgetEdit(lvnr, window)
   
   Declare ListIconGadgetEditSet(lvnr, msg, param1, param2 = -1) 
   
   #my_EventType_EditEnd = #PB_Event_FirstCustomValue + 10
   
   Enumeration
      #ListIconEdit_CharCB      ;Callback setzen für einzelne Zeichen
      #ListIconEdit_TextCB      ;Callback setzen für ganzen Text
      #ListIconEdit_Color       ;Vorgabe vorhanden, Farbe im Stringgadget
      #ListIconEdit_FontId      ;Vorgabe ist LV-Font, Font für Stringgadget
      #ListIconEdit_noEdit      ;Max Aufrufe siehe Index in der Struktur
   EndEnumeration
   
EndDeclareModule

Module ListIconGadgetEdit   
   ; Alle Elemente in diesem Abschnitt sind privat. Alle Namen können ohne
   ; Namenskonflikt auch woanders verwendet werden.
   
   Structure EditStruktur
      lvnr.i               ;ListIconGadget PBnr
      lvid.i
      lvpt.i               ;Pointer Ori WndProc
      item.i               ;Zeile
      subitem.i            ;Spalte
      header.i             ;Header Id
      strgnr.i             ;Stringgadget PBnr
      strgid.i
      strgpt.i             ;Pointer Ori WndProc
      editflag.i           ;wenn 1 im Editmode
      oldtext.s
      newtext.s
      checktext.i          ;einen Pointer; 0 für keinen Check; 1 für Eventtype
      checkchar.i          ;einen Pointer; 0 für keinen Check 
      backcolor.i          ;für Stringgadget
      textcolor.i          ;für Stringgadget
      leftmargin.i         ;für Stringgadget, wird Font geändert dann auch Margin
      keyflag.i            ;gesetzt wenn Tab oder Pfeiltasten gedrückt
      noeditidx.i          ;anzahl noedit Aufrufe, die im Array gespeichert werden
      Array noedit.point(20)  ;noedit Felder werden markiert angezeigt
      StructureUnion       ;um lParam in Hi + Loword zu zerlegen, nur für Mouseposi
         lparam.i          ; lParam vom Callback
         points.points     ; aufgeteiltes lParam in x + y
      EndStructureUnion   
   EndStructure
   
   Prototype p_checktext(nr, item, subitem, old$, new$)
   Prototype p_checkchar(nr, item, subitem, char)
   
   Global CheckText.p_checktext
   Global CheckChar.p_checkchar
   
   EnableExplicit
   
   Macro Edit_End(p)
      If p\editflag
         p\editflag = 0
         p\oldtext = GetGadgetItemText(p\lvnr, p\item, p\subitem)
         p\newtext = GetGadgetText(p\strgnr)
         SetGadgetItemText(p\lvnr, p\item, p\newtext, p\subitem)
         HideGadget(p\strgnr, 1) 
         If p\keyflag = 0: SetGadgetState(p\lvnr, p\item): EndIf
         UnregisterHotKey_(p\strgid, #VK_TAB)
         UnregisterHotKey_(p\strgid, #VK_SHIFT|#VK_TAB)
         ;Check
         If p\checktext = 1
            PostEvent(#PB_Event_Gadget, EventWindow(), p\lvnr, #my_EventType_EditEnd)
         ElseIf p\checktext > 1
            CheckText = p\checktext
            If CheckText(p\lvnr, p\item, p\subitem, p\oldtext, p\newtext) = #False
               SetGadgetItemText(p\lvnr, p\item, p\oldtext, p\subitem)
            EndIf            
         EndIf   
      EndIf
   EndMacro
   
   Macro Edit_Esc(p)
      If p\editflag
         p\editflag = 0
         HideGadget(p\strgnr, 1)   
         SetGadgetState(p\lvnr, p\item)
         UnregisterHotKey_(p\strgid, #VK_TAB)
         UnregisterHotKey_(p\strgid, #VK_SHIFT|#VK_TAB)
      EndIf
   EndMacro
   
   Procedure.s ListIconGadgetGetItem(lvnr, iitem)      
      Protected j
      Protected head = SendMessage_(GadgetID(lvnr), #LVM_GETHEADER, 0, 0)
      Protected cols = SendMessage_(head, #HDM_GETITEMCOUNT, 0, 0)
      Protected item$ = GetGadgetItemText(lvnr, iitem, 0)  
      
      For j = 1 To cols -1
         item$ + #TAB$ + GetGadgetItemText(lvnr, iitem, j)
      Next
      item$ + #CR$  
      
      ProcedureReturn item$
   EndProcedure
   
   Procedure.i ListIconGadgetGetWork(mem)      
      
      ;ist Edit erlaubt ?
      
      Protected *lv.EditStruktur = mem      
      Protected j, ok = #True
      
      With *lv         
         For j = 1 To \noeditidx
            If \noedit(j)\x = \subitem Or \noedit(j)\x = -1
               If \noedit(j)\y = \item Or \noedit(j)\y = -1
                  ;edit verboten
                  ok = #False    
                  Break
               EndIf               
            EndIf            
         Next         
      EndWith
      
      ProcedureReturn ok
   EndProcedure
   
   Procedure.i CallBackLv(hwnd, msg, wParam, lParam) 
      ;hwnd ist die ID vom Gadget
      
      Protected *lv.EditStruktur = GetWindowLongPtr_(hwnd, #GWL_USERDATA)   
      
      With *lv      
         
         Protected hitinfo.LVHITTESTINFO
         Protected rect.RECT
         Protected *nm.NMHDR
         Protected j, x, y, br, hh, txt$, txtbr      
         Protected index, shift      
         Protected itemcount
         Protected topindex
         Protected lastindex
         Protected colscount
         Protected lvwidth = GadgetWidth(\lvnr) - 6 
         
         ;Scrollbar vorhanden ?
         If GetWindowLongPtr_(hwnd, #GWL_STYLE) & #WS_VSCROLL
            lvwidth - GetSystemMetrics_(#SM_CXVSCROLL) 
         EndIf
         
         Static item$
         
         Select msg 
               
            Case #WM_CTLCOLOREDIT   ;vom Stringgadget, da LV das Parent ist
               SetTextColor_(wparam, \textcolor)
               SetBkColor_(wparam, \backcolor)
               ProcedureReturn 0 
               
            Case #WM_MOUSEMOVE
               ;#WM_MOUSEMOVE Abfrage extra für F2
               ;sonst würde lparam von #WM_LBUTTONDBLCLK reichen  
               If \editflag = 0
                  \lparam = lparam    ;Mouseposi: Hi+Loword stehen in \points\x + y
               EndIf            
               
            Case #WM_LBUTTONDBLCLK            
               ;zuerst Endemacro aufrufen
               Edit_End(*lv)                  
               SendMessage_(\strgid, #EM_SETREADONLY, 0, 0)
               
               ;Tab Tasten
               RegisterHotKey_(\strgid, #VK_TAB, 0, #VK_TAB)
               RegisterHotKey_(\strgid, #VK_SHIFT|#VK_TAB, #MOD_SHIFT, #VK_TAB)
               
               ;wenn Up/Down oder Tab, Hitinfo überspringen
               If \keyflag    
                  topindex  = SendMessage_(hwnd, #LVM_GETTOPINDEX, 0, 0)
                  itemcount = SendMessage_(hwnd, #LVM_GETITEMCOUNT, 0, 0)
                  lastindex = SendMessage_(hwnd, #LVM_GETCOUNTPERPAGE, 0, 0) 
                  colscount = SendMessage_(\header, #HDM_GETITEMCOUNT, 0, 0)                  
                  
                  If \keyflag = #VK_UP
                     \item - 1
                     If \item < topindex
                        SendMessage_(hwnd, #WM_VSCROLL, #SB_LINEUP, 0)
                     EndIf 
                     If \item < 0: \item = 0: EndIf                      
                     
                  ElseIf \keyflag = #VK_DOWN
                     \item + 1
                     If \item > lastindex + topindex - 1
                        SendMessage_(hwnd, #WM_VSCROLL, #SB_LINEDOWN, 0)
                     EndIf 
                     If \item > itemcount - 1: \item = itemcount - 1: EndIf
                     
                  ElseIf \keyflag = #VK_TAB
                     \subitem + 1
                     If \subitem > colscount - 1: \subitem - 1: EndIf
                     
                  ElseIf \keyflag = #VK_SHIFT|#VK_TAB
                     \subitem - 1
                     If \subitem < 0: \subitem + 1: EndIf
                     
                  EndIf
                  
                  \keyflag = 0
                  
               Else   
                  ;LBUTTONDBLCLK auf welches Subitem (points kommt von #WM_MOUSEMOVE)    
                  hitinfo\pt\x = \points\x      ;von #WM_MOUSEMOVE siehe EditStruktur
                  hitinfo\pt\y = \points\y  
                  SendMessage_(hwnd, #LVM_SUBITEMHITTEST, 0, hitinfo)
                  \item = hitinfo\iitem
                  \subitem = hitinfo\iSubItem
               EndIf
               
               ;Subitem Größe holen
               rect\top = \subitem          
               rect\left = #LVIR_LABEL
               SendMessage_(hwnd, #LVM_GETSUBITEMRECT, \item, rect)
               ;verschieben horizontal?
               If rect\left < 0
                  SendMessage_(hwnd, #LVM_SCROLL, rect\left - 4, 0)
               ElseIf rect\right > lvwidth
                  SendMessage_(hwnd, #LVM_SCROLL, Abs(lvwidth - rect\right), 0)
               EndIf
               ;rect wieder abfragen, falls verschoben
               rect\top = \subitem
               rect\left = #LVIR_LABEL
               SendMessage_(hwnd, #LVM_GETSUBITEMRECT, \item, rect)
               ;Posi vom Stringgadget + anzeigen
               x = rect\left + 1 
               y = rect\top + 0
               br = rect\right - rect\left - 1 
               hh = rect\bottom - rect\top - 0
               txt$ = GetGadgetItemText(\lvnr, \item, \subitem)
               txtbr = SendMessage_(hwnd, #LVM_GETSTRINGWIDTH, 0, @txt$) + 15
               If txtbr > br: br = txtbr: EndIf
               If x + br > lvwidth: br = lvwidth - x: EndIf
               ResizeGadget(\strgnr, x, y, br, hh)
               SetGadgetText(\strgnr, txt$)
               SendMessage_(GadgetID(\strgnr), #EM_SETSEL, Len(txt$), -1)  ;Cursor ans Ende
               If ListIconGadgetGetWork(*lv) = #False
                  ;noedit Felder werden Readonly und markiert
                  SendMessage_(\strgid, #EM_SETREADONLY, 1, 0)
                  SendMessage_(\strgid, #EM_SETSEL, 0, -1)
               EndIf   
               HideGadget(\strgnr, 0)
               SetActiveGadget(\strgnr)
               SetGadgetState(\lvnr, -1)
               \editflag = 1
               
            Case #WM_VSCROLL, #WM_HSCROLL, #WM_RBUTTONDOWN, #WM_LBUTTONDOWN ;, #WM_NCMOUSELEAVE
               Edit_End(*lv)
               
            Case #WM_NOTIFY   ;vom Header 
               *nm = lparam               
               If *nm\hwndFrom = \header
                  If *nm\code <> -12
                     Edit_End(*lv)
                  EndIf   
               EndIf
               
            Case #WM_KEYDOWN
               Select wParam
                  Case #VK_F2: PostMessage_(hwnd, #WM_LBUTTONDBLCLK, 0, 0)
                     
                  Case #VK_DELETE                     
                     shift = #False
                     If GetKeyState_(#VK_SHIFT) > 1: shift = #True: EndIf
                     If shift = #True: item$ = "": EndIf
                     index = -1
                     itemcount = SendMessage_(hwnd, #LVM_GETSELECTEDCOUNT, 0, 0)
                     For j = 1 To itemcount
                        index = SendMessage_(hwnd, #LVM_GETNEXTITEM, index, #LVNI_SELECTED) 
                        If shift = #True
                           item$ + ListIconGadgetGetItem(\lvnr, index)
                           SetClipboardText(item$)
                        EndIf
                        RemoveGadgetItem(\lvnr, index)
                        index - 1
                     Next
                     SetGadgetState(\lvnr, index + 1)                       
                     
                  Case #VK_INSERT
                     shift = #False
                     If GetKeyState_(#VK_SHIFT) > 1: shift = #True: EndIf                     
                     index = GetGadgetState(\lvnr) 
                     If shift = #False
                        If index = -1 
                           AddGadgetItem(\lvnr, index, "")
                           index = CountGadgetItems(\lvnr) - 1
                        Else
                           AddGadgetItem(\lvnr, index, "")
                        EndIf
                     Else 
                        If index = -1: index = CountGadgetItems(\lvnr): EndIf
                        itemcount = CountString(item$, #CR$)
                        ReplaceString(item$, #TAB$, #LF$, #PB_String_InPlace)
                        For j = 1 To itemcount
                           AddGadgetItem(\lvnr, index + j - 1, StringField(item$, j, #CR$))                    
                        Next
                        SetGadgetState(\lvnr, -1)
                     EndIf                       
                     SetGadgetState(\lvnr, index)
                     
               EndSelect               
               
         EndSelect       
         ProcedureReturn CallWindowProc_(\lvpt, hwnd, msg, wParam, lParam)      
      EndWith
   EndProcedure 
   
   Procedure.i CallBackStrg(hwnd, msg, wParam, lParam) 
      Protected *lv.EditStruktur = GetWindowLongPtr_(hwnd, #GWL_USERDATA)
      
      With *lv
         
         Select msg
               
            Case #WM_KILLFOCUS
               Edit_End(*lv)
               
            Case #WM_CHAR            
               Select wparam 
                  Case #VK_RETURN: Edit_End(*lv)
                  Case #VK_ESCAPE: Edit_Esc(*lv)
                  Default
                     If \checkchar
                        CheckChar = \checkchar
                        wParam = CheckChar(\lvnr, \item, \subitem, wParam)            
                     EndIf                  
               EndSelect
               
            Case #WM_KEYDOWN
               Select wparam 
                  Case #VK_DOWN, #VK_UP
                     \keyflag = wparam
                     PostMessage_(GadgetID(\lvnr), #WM_LBUTTONDBLCLK, 0, 0)
                     ProcedureReturn 0
               EndSelect  
               
            Case #WM_HOTKEY
               \keyflag = wparam 
               PostMessage_(GadgetID(\lvnr), #WM_LBUTTONDBLCLK, 0, 0)
               ProcedureReturn 0
               
         EndSelect
         
         ProcedureReturn CallWindowProc_(\strgpt, hwnd, msg, wParam, lParam) 
      EndWith
   EndProcedure 
   
   Procedure.i ListIconGadgetEditSet(lvnr, msg, param1, param2 = -1) 
      
      If IsGadget(lvnr)
         If GadgetType(lvnr) = #PB_GadgetType_ListIcon
            
            Protected j, *lv.EditStruktur 
            Protected ptr = GetWindowLongPtr_(GadgetID(lvnr), #GWL_USERDATA)
            
            If ptr
               *lv = ptr               
               With *lv
                  Select msg
                     Case #ListIconEdit_CharCB: \checkchar = param1
                     Case #ListIconEdit_TextCB: \checktext = param1
                     Case #ListIconEdit_Color:  \textcolor = param1: \backcolor = param2
                     Case #ListIconEdit_FontId                         
                        SetGadgetFont(\strgnr, param1)
                        SendMessage_(\strgid, #EM_SETMARGINS, #EC_LEFTMARGIN, \leftmargin)

                     Case #ListIconEdit_noEdit
                        ;da Redim in StrukturArrays nicht geht, wurde Array begrenzt.
                        ;ansonsten müßten die Daten hin und her kopiert werden, beim
                        ;erweitern des Arrays.
                        If \noeditidx < ArraySize(\noedit())
                           \noeditidx + 1
                           \noedit(\noeditidx)\x = param1
                           \noedit(\noeditidx)\y = param2
                        Else
                           Debug "zuviele 'noedit' Aufrufe"
                        EndIf
                        
                  EndSelect
               EndWith
            EndIf
            
         EndIf         
      EndIf
      
   EndProcedure
   
   Procedure.i ListIconGadgetEdit(lvnr, window)   
      
      ;Für jedes Lv darf ListIconGadgetEdit() nur einmal aufgerufen werden.
      ;dies wird nicht kontrolliert !!!
      ;Jedes Lv bekommt seinen eigen MemoryBereich.
      
      Protected *lv.EditStruktur = AllocateMemory(SizeOf(EditStruktur))    
      Protected oldlist, null.w 
      
      InitializeStructure(*lv, EditStruktur) ;wegen Array in der Struktur
      
      With *lv      
         ;LV
         \lvnr = lvnr
         \lvid = GadgetID(lvnr)
         \lvpt = GetWindowLongPtr_(\lvid, #GWL_WNDPROC)         ;Ori WindowProcPointer holen
         SetWindowLongPtr_(\lvid, #GWL_USERDATA, *lv)           ;Memory setzen
         SetWindowLongPtr_(\lvid, #GWL_WNDPROC, @CallBackLv())  ;WindowProc setzen
         \header = SendMessage_(\lvid, #LVM_GETHEADER, 0, 0)
         ;StringGadget
         oldlist = UseGadgetList(WindowID(window))
         \strgnr = StringGadget(#PB_Any, 0, 0, 0, 0, "")	
         \strgid = GadgetID(\strgnr)         
         \strgpt = GetWindowLongPtr_(\strgid, #GWL_WNDPROC)
         SetGadgetFont(\strgnr, GetGadgetFont(lvnr))
         HideGadget(\strgnr, 1)
         SetParent_(\strgid, \lvid) 
         SetWindowLongPtr_(\strgid, #GWL_USERDATA, *lv)
         SetWindowLongPtr_(\strgid, #GWL_WNDPROC, @CallBackStrg())
         If oldlist: UseGadgetList(oldlist): EndIf
         ;div
         \backcolor = $DFFFFF
         \textcolor = $880000
         \leftmargin = 2
         Setwindowtheme_(\strgid, @null, @null)
         SendMessage_(\strgid, #EM_SETMARGINS, #EC_LEFTMARGIN, \leftmargin)
         ProcedureReturn \strgnr
      EndWith   
   EndProcedure   
   
EndModule

UseModule ListIconGadgetEdit

; -Test

CompilerIf #PB_Compiler_IsMainFile
   
   Import "UxTheme.lib"
      SetWindowTheme(hwnd, classname.p-unicode, titlename)
   EndImport
   
   Enumeration
      #window   
      #liste1   
      #liste2   
   EndEnumeration
   
   Procedure.i LVEditCheckText(nr, item, subitem, old$, new$)
      
      If nr = #liste1
         If subitem = 3   
            If Val(new$) > 1000
               MessageRequester("", "Eingabe zu groß")
               ProcedureReturn #False
            EndIf
         EndIf
      EndIf
      
      ProcedureReturn #True 
      
   EndProcedure
   
   Procedure.i LVEditCheckChar(nr, item, subitem, char)
      
      If nr = #liste1 
         If subitem = 0
            Select char
               Case ',': char = '.'
            EndSelect      
         EndIf
      EndIf
      
      ProcedureReturn char
      
   EndProcedure
   
   Procedure.i Mainwindow()
      
      Protected j, event   
      Protected flags = #PB_Window_SystemMenu|#PB_Window_MinimizeGadget
      
      OpenWindow(#window, 150, 150, 700, 600, "", flags)
      
      flags = #PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect
      flags | #PB_ListIcon_MultiSelect   
      
      ListIconGadget(#liste1, 20, 5, 290, 500, "0", 40, flags)
      ListIconGadget(#liste2, 320, 5, 290, 500, "0", 40, flags)
      SetGadgetColor(#liste1, #PB_Gadget_BackColor, #Yellow)
      
      For j = 1 To 5
         AddGadgetColumn(#liste1, j, Str(j), 90)
         AddGadgetColumn(#liste2, j, Str(j), 80)
      Next   
      For j = 0 To 27      
         AddGadgetItem(#liste1, -1, Str(j)+#LF$+"Hans"+#LF$+"Meiereisung"+#LF$+Str(Random(999)))      
         AddGadgetItem(#liste2, -1, Str(j)+#LF$+"Otto"+#LF$+"Leier"+#LF$+Str(Random(999)))      
      Next 
      
      
      ListIconGadgetEdit(#liste1, #window)
      ListIconGadgetEdit(#liste2, #window)
      
      ListIconGadgetEditSet(#liste1, #ListIconEdit_TextCB, @LVEditCheckText()) 
      ListIconGadgetEditSet(#liste1, #ListIconEdit_CharCB, @LVEditCheckChar()) 
      
      ListIconGadgetEditSet(#liste1, #ListIconEdit_noEdit, 0)     ;Spalte 0 gesperrt alle Zeilen
      ListIconGadgetEditSet(#liste1, #ListIconEdit_noEdit, 2, 3)  ;Spalte 2 Zeile 3 gesperrt
      ListIconGadgetEditSet(#liste1, #ListIconEdit_noEdit, -1, 4) ;alle Spalten In Zeile 4
      
      SetActiveGadget(#liste1)
      
      SetWindowTheme(GadgetID(#liste1), "explorer", 0)
      
      Repeat: event = WaitWindowEvent() 
      Until event = #PB_Event_CloseWindow 
      
   EndProcedure
   
   Mainwindow()
   
CompilerEndIf

Zuletzt geändert von hjbremer am 18.09.2013 13:23, insgesamt 1-mal geändert.
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Benutzeravatar
alter Mann
Beiträge: 201
Registriert: 29.08.2008 09:13
Wohnort: hinterm Mond

Re: PB 5.20 Listicongadget simples Edit als Modul

Beitrag von alter Mann »

... habe gerade keine Zeit, ich schaue es mir aber auf jeden Fall an und melde mich dann zurück... :allright:

edit: Ich hab's gerade ausprobiert. Genau das, was ich gesucht habe! :praise:
Win11 64Bit / PB 6.0
Benutzeravatar
ProgOldie
Beiträge: 236
Registriert: 19.05.2012 17:09
Computerausstattung: Windows11, Arduinos, Pi3, PureBasic 6.02

Re: PB 5.20 Listicongadget simples Edit als Modul

Beitrag von ProgOldie »

Super Lösung, von der ich leider vieles nicht verstanden habe, weil dazu meine API-Kenntnisse nicht ausreichen. Schön auch die nachträgliche Typüberprüfungsmöglichkeit.

Daher eine Frage zur Erweiterung.
Eine Grundidee ist ja die einmalige Erstellung eines Stringgadgets, das unsichtbar gemacht und dann bei Bedarf an das ausgewählte Tabellenfeld angepasst und sichtbar gemacht wird. Es wäre natürlich phantastisch, wenn man hier auch mit anderen, zum Spaltentyp passenden, Gadgets arbeiten könnte.
Könnte man dazu nicht ein (globales?) Array definieren, das Spaltenkopfbezeichner, Spaltentyp und gewisse Typparameter enthält, etwa so:

Cols(0,0)="Nummer" :Cols(0,1)="Int"
Cols(1,0)="Nachname" :Cols(1,1)="Str"
Cols(2,0)="Vorname" :Cols(2,1)="Combo" : Cols(2,2)="A|B|C|Auswahl D|E|F"
Cols(3,0)="Geburtsdatum" :Cols(3,1)="Date"

Außerdem erweitert man die Struktur von EditStruktur um die entsprechenden Gadgetnummern:
strgnr.i, combonr.i, datenr.i etc.....

In ListIconGadgetEdit erzeugt man dann für jeden der o.a. Datentypen erst einmal auf Vorrat ein (unsichtbares) Gadget.

Dann definiert man eine Prozedur GadNr.i(item,subitem,Cols()), welche die Nummer des zum Typ passenden Gadgets bestimmt. Und die ruft man jedesmal da auf, wo bisher strgnr benutzt wird, um strgnr durch den von GadNr berechneten Wert zu ersetzen.

Hat so etwas prinzipiell Aussicht auf Erfolg?
Windows10 / PB5.70 / Arduino (-Due) / Raspberry Pi3 /Linux Mint 18
Antworten