ListIcongadget Edit für Felder, klein + ohne Callback

Windowsspezifisches Forum , API ,..
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

ListIcongadget Edit für Felder, klein + ohne Callback

Beitrag von hjbremer »

Habe einen Code überarbeitet den ich vor vielen Jahren geschrieben hatte, hier nun als Modul

etwas modernisiert und wichtig war mir klein, relativ simpel und kein Callback und Felder sperren.
ohne Callback gibt es natürlich einige Einschränkungen was Edit der Felder angeht, aber dann wäre es nicht mehr klein. Mehr geht immer.

zuerst ein kleines Demoprog
dann das Modul, habe es ListIconEdit.pbi genannt

Code: Alles auswählen

XIncludeFile "ListIconEdit.pbi"   ;12.08.2022

EnableExplicit
   
   Enumeration 10
      #window  
      #liste1
      #liste2
   EndEnumeration
   
   Define fontStd = LoadFont(#PB_Any, "Calibri", 11)
   
   OpenWindow(#window, 0, 0, 820, 600, "LV Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
   
   ListIconGadget(#liste1, 5, 5, 500, 590, "Column 0", 125, #PB_ListIcon_FullRowSelect|#PB_ListIcon_GridLines)
   ListIconGadget(#liste2, 510, 5, 300, 590, "Col 0", 60, #PB_ListIcon_FullRowSelect|#PB_ListIcon_GridLines)
   
   SetGadgetFont(#liste1, FontID(fontStd))            ;zu empfehlen, für mich old man sonst zu klein 
   SetWindowTheme_(GadgetID(#liste1), "explorer", 0)  ;sieht besser aus finde ich
   
   Define j, jahr, zahl
   
   For j = 1 To 15
      AddGadgetColumn(#liste1, j, "Col " + Chr(j+64), 75)
      AddGadgetColumn(#liste2, j, "Col " + Str(j), 55)
   Next
   For j = 0 To 30   
      jahr = Random(2022, 2010)
      zahl = Random(6000, 1000)
      AddGadgetItem(#liste1, -1, "Col 0/" + Str(j) + #LF$ + Str(jahr) + #LF$ + Str(zahl) + #LF$ + Str(zahl*2))
      AddGadgetItem(#liste2, -1, "Col 0/" + Str(j) + #LF$ + Str(jahr) + #LF$ + Str(zahl) + #LF$ + Str(zahl*2))
   Next   
   
   SetListAlign(#liste1, 1, #LVCFMT_RIGHT)
   SetListAlign(#liste1, 2, #LVCFMT_RIGHT)
   
   setEditOk(#liste1, "x-bcdefghi") ;die 2. Spalte gesperrt für Edit(Strich oder Space), dann bis i erlaubt, Rest gesperrt
   setEditOk(#liste2, " xxx")       ;die 1. Spalte gesperrt, 2.+3.+4. erlaubt, Rest gesperrt da nicht definiert
   
   ;-Repeat Event   
   Define event 
   
   Repeat
      event = WaitWindowEvent()   
      event = ListIconEdit(event)   
      
      Select Event         
         Case #PB_Event_Gadget         
            Select EventGadget()
               Case #liste1
                  If EventType() = #PB_EventType_LeftDoubleClick 
                     Debug "EventType: " + "#PB_EventType_LeftDoubleClick"
                     
                  ElseIf EventType() = #PB_EventType_Input
                     Debug "#PB_EventType_Input"
                     Debug "row = " + GetGadgetState(#liste1)
                     Debug "col = " + EventData()
                     Debug GetGadgetItemText(#liste1, GetGadgetState(#liste1), EventData())
                  EndIf               
            EndSelect
      EndSelect
   Until Event = #PB_Event_CloseWindow
   

Code: Alles auswählen

;{ Info
;-Info ListIconEdit.pbi
; Include für ListIconGadget um Felder zu editieren, ist klein, einfach und simpel, für kleinere Listen gedacht.
;
; V 2.01 2009/2022 by HJBremer - getestet PB 5.70x86 5.72x64 6.00x64 Unicode Windows 64 Bit !!!!!!
; 
; das Original wurde von mir 2009 veröffentlich und nun von mir überarbeitet
;     Original siehe http://forums.purebasic.com/german/viewtopic.php?t=20818

; Aufruf: im Hauptprogramm nur eine Zeile einfügen, direkt nach 
;         event = WaitWindowEvent() 
;   kommt event = ListIconEdit(event)
;         in ALLEN ListIcongadgets können dann Felder via Doppelclick bearbeitet werden !!!
; 
; zusätzlicher Parameter selflag 0, 1 oder 2, gilt für alle Listen
;         event = ListIconEdit(event, 2) 
;         0 = Cursor am Anfang, 1 = ans Ende, ist Vorgabe !!!
;         2 = Cursor ans Ende + Feldinhalt wird markiert 
;         
; mit Doppelclick auf ein Feld wird Edit aktiviert
; mit ESC oder ein Klick auf ein Feld/Gadget/Window oder Zeile wird Edit beendet, siehe exitflag
;
; !!! NUR mit Return werden Eingaben übernommen !!!
;     und ein EventType() = #PB_EventType_Input wird gesendet incl. die Column als EventData()
;
;SetEditOk(pbnr, ok.s)
;  dient dazu bestimmte Spalten oder alle einer Liste zu sperren
;  pbnr  = GadgetNummer der Liste
;  ok.s  = ein Strich/Leerzeichen oder keine Angabe sperrt die Spalte 
;
;          SetEditOk(#liste2, "x x")   ;die 1. + 3. Spalte erlaubt, Rest gesperrt !!!
;          SetEditOk(#liste1, "x-xxx") ;die 2. Spalte gesperrt mit Info
;          SetEditOk(#liste5, "")      ;alle Spalten gesperrt für Edit
;
;          Strich (Minus) für gesperrt = es erscheint eine Info "ist gesperrt", Leerzeichen keine Info.
;          gibt es mehr Spalten als man im ok.s angegeben hat werden diese gesperrt
;          wenn eine Spalte gesperrt ist, gibt es beim Doubleclick immer das entsprechende Eventtype()
;Hinweis:
;  wenn die 2 EnableScrollBar_() Befehle aktiviert sind, kann man nicht Horz. scrollen wenn Edit aktiv,
;  denn das scrollen verursacht Drawfehler, sieht etwas doof aus. 
;  Da PB die Scrollevents nicht sofort rausrückt, weiß ich nicht wie man das abstellt, außer man hat einen Callback.
;}
;-Modul
DeclareModule ListIconEdit
   
   Declare.i ListIconEdit(event, selflag = 1)
   
   Declare.i SetEditOk(pbnr, ok.s)
   Declare.i SetListAlign(pbnr, column, align)
   
EndDeclareModule

Module ListIconEdit   
   EnableExplicit

   Procedure.i GetGadgetColumn(pbnr)   ;intern
      Protected lvid = GadgetID(pbnr), lvhit.LVHITTESTINFO   
      GetCursorPos_(lvhit\pt)          ;wo ist Maus on Screen   
      ScreenToClient_(lvid, lvhit\pt)  ;Mausposi in Liste
      SendMessage_(lvid, #LVM_SUBITEMHITTEST, 0, lvhit)
      ProcedureReturn lvhit\iSubItem   ;Column ab null zurückgeben
   EndProcedure     
   
   ;EditOk Proceduren
   Structure EditOk
      pbnr.l   ;PB-Nummer der Liste für Abfrage in GetEditOk()   
      ok.s     ;Ok-String (die Abfrage via Mid() ergibt Null wenn ok.s zu klein ist)
   EndStructure
   
   Global NewList editok.EditOk() 
   
   Procedure.i GetEditOk(pbnr, col, editfeld = 0) ;intern, überprüft ob column gesperrt
      Protected iitem$, okchar, ok = #True      
      
      ForEach editok()
         If editok()\pbnr = pbnr
            okchar = Asc(Mid(editok()\ok, col+1, 1))  ;col+1 weil Mid() bei 1 beginnt, Listen bei null
            If editfeld = 0   ;wenn null dann Abfrage ob Column gesperrt. 
               Select okchar
                  Case 45: ok = #PB_Ignore: MessageRequester("Info", "bearbeiten gesperrt"): Break ;45=Strich (Minus)
                  Case 0,32: ok = #PB_Ignore: Break                                 ;0=nicht definiert, 32=Leerzeichen
               EndSelect
            EndIf
         EndIf
      Next
      ProcedureReturn ok
   EndProcedure
   
   Procedure.i SetEditOk(pbnr, ok.s)
      Protected found = #False
      ForEach editok()
         If editok()\pbnr = pbnr ;falls schon vorhanden dann ändern
            editok()\ok = ok: found = #True
         EndIf
      Next
      If found = #False          ;wenn noch nicht vorhanden dann neu
         AddElement(editok())
         editok()\pbnr = pbnr: editok()\ok = ok
      EndIf
   EndProcedure

   Procedure.i SetListAlign(pbnr, column, align)      
      Protected lv.LV_Column\mask = #LVCF_FMT
      lv\fmt = align                   ;#LVCFMT_LEFT=0, #LVCFMT_RIGHT=1, #LVCFMT_CENTER=2
      SendMessage_(GadgetID(pbnr), #LVM_SETCOLUMN, column, lv) ;LVCFMT_FIXED_WIDTH = $100 
   EndProcedure
   
   ;-Edit Procedure
   Procedure ListIconEdit(event, selflag = 1)
      
      Protected exitflag, iitem$, r.RECT
      Static lvnr, lvrow, lvcol, editfeld 
      
      If editfeld  ;wenn es ein Editfeld gibt         
         Select event           
            Case #PB_Event_Gadget   ;Edit beeenden wenn LostFocus            
               If EventGadget() = editfeld
                  If EventType() = #PB_EventType_LostFocus
                     exitflag = 1
                  EndIf
               EndIf
               
            Case #WM_KEYDOWN  ;Edit beeenden wenn ESC oder Return            
               If EventwParam() = #VK_ESCAPE: exitflag = 1: EndIf
               If EventwParam() = #VK_RETURN: exitflag = 2: EndIf   
               
            Case #WM_NCLBUTTONDOWN  ;Maustaste gedrückt im NichtClientBereich z.B. Scrollbalken etc            
               exitflag = 1 
               SendMessage_(GadgetID(lvnr), #WM_SETREDRAW, #True, 0) ;neu zeichnen falls Liste verschoben 
               InvalidateRect_(GadgetID(lvnr), 0, #True)     
               
            Case #WM_MOUSEWHEEL, #PB_Event_Menu, #PB_Event_SysTray  ;bei Bedarf mehr Events für Abbruch
               exitflag = 1            
         EndSelect
         
         If exitflag          ;Edit beenden         
            If exitflag = 2   ;Return gedrückt = Daten übernehmen + #PB_EventType_Input senden               
               GetEditOk(lvnr, lvcol, editfeld)
               iitem$ = GetGadgetText(editfeld)
               SetGadgetItemText(lvnr, lvrow, iitem$, lvcol)   ;dann EventType() senden
               PostEvent(#PB_Event_Gadget, EventWindow(), lvnr, #PB_EventType_Input, lvcol)
            EndIf
            FreeGadget(editfeld): editfeld = 0 
            SetGadgetState(lvnr, lvrow)
            EnableScrollBar_(GadgetID(lvnr), #SB_HORZ, #ESB_ENABLE_BOTH)
         EndIf
         
      ElseIf event = #PB_Event_Gadget  ;wenn es noch kein Editfeld gibt dann erstellen
         
         lvnr = EventGadget()                               ;Gadget Nummer holen
         If IsGadget(lvnr) = 0: ProcedureReturn -1: EndIf   ;falls es kein gültiges Gadget ist 
         
         If GadgetType(lvnr) = #PB_GadgetType_ListIcon      ;wenn ein ListIconGadget            

            If EventType() = #PB_EventType_LeftDoubleClick

               lvrow = GetGadgetState(lvnr)              ;in welcher Zeile
               lvcol = GetGadgetColumn(lvnr)             ;in welcher Spalte Doubleclick
               If lvrow = -1: ProcedureReturn event: EndIf  ;wenn -1, z.B. Header angeclickt
               
               If GetEditOk(lvnr, lvcol) = #PB_Ignore: ProcedureReturn event: EndIf ;gesperrt              

               r\top = lvcol: r\left = #LVIR_LABEL          ;Vorgaben für #LVM_GETSUBITEMRECT
               SendMessage_(GadgetID(lvnr), #LVM_GETSUBITEMRECT, lvrow, r)       ;Größe holen 
               
               iitem$ = GetGadgetItemText(lvnr, lvrow, lvcol)  ;Text als Vorgabe + Gadget erstellen
               editfeld = StringGadget(#PB_Any, r\left, r\top, r\right-r\left-1, r\bottom-r\top-1, iitem$)
               
               SetParent_(GadgetID(editfeld), GadgetID(lvnr))  ;sehr wichtig, editfeld wird Teil der Liste               
               SetGadgetFont(editfeld, GetGadgetFont(lvnr))    ;Font der Liste dem editfeld zuweisen
               SetActiveGadget(editfeld)
               
               If selflag = 1                                  
                  SendMessage_(GadgetID(editfeld), #EM_SETSEL, Len(iitem$), -1)  ;Cursor ans Ende                 
               ElseIf selflag = 2                              
                  SendMessage_(GadgetID(editfeld), #EM_SETSEL, 0, -1)   ;ans Ende + alles markieren
               EndIf 
               SetGadgetState(lvnr, -1)   ;während der Eingabe Selectbalken weg, wird von exitflag wieder hergestellt
               EnableScrollBar_(GadgetID(lvnr), #SB_HORZ, #ESB_DISABLE_BOTH)   ;scrollen Horizontal aus
            EndIf
         EndIf         
      EndIf
      
      ProcedureReturn event
   EndProcedure   
EndModule

UseModule ListIconEdit

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