Seite 1 von 1

PB 5.1 und PostEvent mit Edit von ExplorerTreeGadget

Verfasst: 09.01.2013 18:01
von hjbremer
Habe mal einen älteren Code etwas aktualisiert auf die neue Version
und PB_Gadget_SendGadgetCommand gegen PostEvent und dem von Edel verratenem PB_Event_Add getauscht.

Leider hat das ExplorerTreegadget immer noch die Macke das #WM_NCDESTROY nicht die letzte Message ist.
Genauso doof ist das Vertauschen der Parameter bei PostEvent und PB_Event_Add. Aber vielleicht ändert sich das. PostEvent wird gebraucht, damit bei Änderungen im ExplorerListGadget sich das ExplorerTreeGadget aktualisiert. Umgedreht gehts von selbst.

Hier das Beispiel mit Edit der Einträge. Wer Systemdateien etc umbenennt hat selber Schuld. Habe zwar versucht das zu unterbinden, aber alles kann man nicht verhindern. Eine Eingabeprüfung findet ebenfalls nicht statt, denn bei Unsinn meckert Windows sowieso. ( Ist aber möglich, indem man das EditLabel subclasst. #LVM_GETEDITCONTROL gibt das Handle zurück )

Gibt es 2 Gadgets wie im Beispiel, so ist bei ExplorerGadgetEdit() die Angabe der WindowNr (keine ID) wichtig, sonst gibt es kein PostEvent.

Nur zur Info. Damit EditLabel funktioniert, braucht man einen MainCallback, denn Die entsprechenden Messages werden nur ans ParentWindow gesendet. siehe #WM_Notify. Und da ich wieder alles verschlimmbessert habe gibt es auch keine Garantie. Nur wer testet erntet Segen.

Code: Alles auswählen

;PB ab 4.41 x86 - Windows Vista 32 Bit - HJBremer aktualisiert Jan. 2013

;Edit von Einträgen im ExplorerTreeGadget und ExplorerListGadget
; unter Verwendung der EDITLABEL Befehle der Windows Api

;wird benötigt ab Vista ohne Aero, sieht besser aus.
CompilerIf Defined(SetWindowTheme, #PB_Procedure) = 0
   Import "UxTheme.lib"
      SetWindowTheme(hwnd, AppName.p-unicode, IdList)
   EndImport
CompilerEndIf

;PB_Event_Add aus dem Forum von "edel" 
;http://www.purebasic.fr/german/viewtopic.php?f=6&t=26229&start=10#p307870

;ab Pb 5.1 gibt es Postevent(), ob die Parameter so bleiben, wer weiß

CompilerIf Defined(PostEvent, #PB_Function) = 0
   ImportC ""  
      PBEventAdd(ID, ObjectID, WindowID, Type) As "_PB_Event_Add"
   EndImport
   Macro PostEvent(ID, WindowID, ObjectID, Type) 
      PBEventAdd(ID, ObjectID, WindowID, Type) 
   EndMacro      
CompilerEndIf
 
#explorergadget_propid = "ExplorerEditStruktur"

Structure ExplorerEditStruktur
   lvnr.i               ;Gadget PBnr
   lvid.i               ;Gadget Id
   lvptr.i              ;Pointer Ori WndProc
   winnr.i              ;ParentWindow PbNr
   oritext.s            ;Original Datei/Dir Name
   edittext.s           ;Text im Editlabel
   gadgettype.i         ;Gadgettype Tree oder List
EndStructure

EnableExplicit

Procedure.i ExplorerGadget_Rename(*ee.ExplorerEditStruktur)
   
   With *ee  
      Protected oldname$, newname$
      Protected endung$, info$ = ""       
      Protected attribut = GetFileAttributes_(\oritext)
      
      If attribut = -1  ;INVALID_FILE_ATTRIBUTES
         info$ = "Systemfehler " + Str(GetLastError_())
      ElseIf attribut & #PB_FileSystem_System = #PB_FileSystem_System
         info$ = "Systemdatei kann nicht umbenannt werden"
      EndIf
      If info$: MessageRequester("Info", info$): ProcedureReturn 0: EndIf   
      
      ; \ entfernen, damit GetPathPart() bei Directorys das Parentdir zurückgibt
      If Right(\oritext, 1) = "\": \oritext = Left(\oritext, Len(\oritext)-1): EndIf
      
      oldname$ = \oritext
      newname$ = GetPathPart(oldname$) + \edittext      
      endung$  = LCase(GetExtensionPart(oldname$)) 
      
      Select endung$
         Case "exe", "dll", "lib", "bin"
            info$ = "Rename dieser Datei ist verboten"
            MessageRequester("Info", info$): ProcedureReturn 0
      EndSelect
      
      If RenameFile(oldname$, newname$)   
         ;Rename ok
         If \gadgettype = #PB_GadgetType_ExplorerTree
            ;aktualisieren
            SetGadgetText(\lvnr, GetPathPart(oldname$)+"*.*")
         EndIf   
      Else
         info$ = "Rename nicht erfolgreich"
         MessageRequester("Info", info$): ProcedureReturn 0
      EndIf
      
   EndWith
   ProcedureReturn 1        
EndProcedure

Procedure.i ExplorerGadget_Parent(hwnd, msg, wParam, lParam) 
   ;hwnd ist hier gleich der ID vom ParentWindow   
   
   Protected *nmhdr.NMHDR
   Protected *lv_dispinfo.LV_DISPINFO, *tv_dispinfo.TV_DISPINFO
   Protected *ee.ExplorerEditStruktur
   Protected item
   
   If msg = #WM_NOTIFY
      *nmhdr = lParam
      *ee = GetProp_(*nmhdr\hwndFrom, #explorergadget_propid)
      If *ee 
         If *ee\lvid = *nmhdr\hwndFrom
            Select *nmhdr\code 
               Case #LVN_BEGINLABELEDIT
                  item = GetGadgetState(*ee\lvnr)
                  *ee\oritext = GetGadgetText(*ee\lvnr) + GetGadgetItemText(*ee\lvnr, item)
                  SendMessage_(*ee\lvid, #LVM_GETEDITCONTROL, 0, 0)
                  
               Case #LVN_ENDLABELEDIT 
                  *ee\edittext = ""
                  *lv_dispinfo = lparam
                  If *lv_dispinfo\item\pszText   ;nur wahr, wenn Text verändert
                     *ee\edittext = PeekS(*lv_dispinfo\item\pszText)                     
                     ExplorerGadget_Rename(*ee)
                     ;senden von #PB_EventType
                     If *ee\winnr > -1
                        PostEvent(#PB_Event_Gadget, *ee\winnr, *ee\lvnr, #PB_EventType_ReturnKey)
                     EndIf   
                  EndIf
                  
               Case #TVN_BEGINLABELEDIT
                  *ee\oritext = GetGadgetText(*ee\lvnr)
                  SendMessage_(*ee\lvid, #TVM_GETEDITCONTROL, 0, 0)
                  
               Case #TVN_ENDLABELEDIT 
                  *ee\edittext = ""
                  *tv_dispinfo = lparam
                  If *tv_dispinfo\item\pszText   ;nur wahr, wenn Text verändert
                     *ee\edittext = PeekS(*tv_dispinfo\item\pszText)                     
                     ExplorerGadget_Rename(*ee)
                  EndIf               
            EndSelect
         EndIf
      EndIf
   EndIf
   
EndProcedure 

Procedure.i ExplorerGadget_Callback(hwnd, msg, wParam, lParam) 
   ;hwnd ist gleich der ID vom Gadget = \lvid 
   ;dieser Callback muß sein, um F2 abzufragen und #WM_NCDESTROY.
   
   ;im ExplorerTreeGadget ist #WM_NCDESTROY -NICHT- die letzte Message !!!
   ; sondern #TVM_GETIMAGELIST, darum das destroyflag
   
   Static destroyflag
   Protected item
   Protected *ee.ExplorerEditStruktur = GetProp_(hwnd, #explorergadget_propid)   
   Protected oldwndproc = *ee\lvptr 
   
   Select msg             
         
      Case #WM_NCDESTROY
         If *ee\gadgettype = #PB_GadgetType_ExplorerList
            RemoveProp_(hwnd, #explorergadget_propid)
            FreeMemory(*ee)
         Else
            destroyflag = 1
         EndIf   
         
      Case #TVM_GETIMAGELIST
         If destroyflag
            destroyflag = 0
            RemoveProp_(hwnd, #explorergadget_propid)
            FreeMemory(*ee)
         EndIf               
         
      Case #WM_KEYDOWN
         Select wparam                  
            Case #VK_F2 ;F2 startet Edit
               If *ee\gadgettype = #PB_GadgetType_ExplorerList
                  item = GetGadgetState(*ee\lvnr)   
                  If item > -1
                     SendMessage_(hwnd, #LVM_EDITLABEL, item, 0)
                  EndIf                     
               Else
                  item = SendMessage_(hwnd, #TVM_GETNEXTITEM, #TVGN_CARET, 0)      
                  If item
                     SendMessage_(hwnd, #TVM_EDITLABEL, 0, item)
                  EndIf   
               EndIf
               ProcedureReturn 0
         EndSelect
   EndSelect
   
   ProcedureReturn CallWindowProc_(oldwndproc, hwnd, msg, wParam, lParam) 
EndProcedure 

Procedure.i ExplorerGadgetEdit(gadgetnr, windownr = -1)
   Protected parent, style, type = GadgetType(gadgetnr)
   
   If IsGadget(gadgetnr) = 0
      Debug "ungültige GadgetNummer"
      ProcedureReturn 0
   Else
      Select type
         Case #PB_GadgetType_ExplorerList: style = #LVS_EDITLABELS
         Case #PB_GadgetType_ExplorerTree: style = #TVS_EDITLABELS
         Default:
            Debug "kein ExplorerGadget"
            ProcedureReturn 0            
      EndSelect
      Protected *ee.ExplorerEditStruktur = AllocateMemory(SizeOf(ExplorerEditStruktur))    
      With *ee  
         \lvnr = gadgetnr
         \lvid = GadgetID(gadgetnr)
         \lvptr = GetWindowLongPtr_(\lvid, #GWL_WNDPROC) ;WndProcPointer holen
         \winnr = windownr
         \gadgettype = type
         SetProp_(\lvid, #explorergadget_propid, *ee)   ;Memory setzen + eigene WndProc setzen
         SetWindowLongPtr_(\lvid, #GWL_WNDPROC, @ExplorerGadget_Callback())
         SetWindowLongPtr_(\lvid, #GWL_STYLE, GetWindowLongPtr_(\lvid, #GWL_STYLE)|style)
         SetWindowTheme(\lvid, "Explorer", 0)
      EndWith
      ProcedureReturn *ee
   EndIf
   
EndProcedure

DisableExplicit

; -Ende Include-

Enumeration 1
   #window   
   #font1
   #liste1
   #liste2
   #gadget1
   #gadget2
EndEnumeration

Procedure MainWindowCallback(WindowID, Message, wParam, lParam)
   Protected Result = #PB_ProcessPureBasicEvents
   
   Select message
      Case #WM_NOTIFY
         ExplorerGadget_Parent(WindowID, Message, wParam, lParam) 
         
      Case #WM_HELP     ;nur zur Demo
         Protected *help.HELPINFO   
         *help = lParam
         Debug "F1 gedrückt"
         Debug "  Gadget IdNr " + Str(*help\hItemHandle)
         Debug "  Gadget PbNr " + Str(*help\iCtrlId)
         Debug "  Mousepos x " + Str(*help\MousePos\x)
         Debug "  Mousepos y " + Str(*help\MousePos\y)
         
   EndSelect
   
   ProcedureReturn Result
EndProcedure

Procedure.i Mainwindow()
   
   LoadFont(#font1, "Arial", 10)   
   Protected event   
   Protected flags = #PB_Window_SystemMenu|#PB_Window_MinimizeGadget
   
   OpenWindow(#window, 150, 100, 820, 600, "", flags)

   ExplorerTreeGadget(#liste1, 10, 10, 390, 500, "c:\bremer\")
   ExplorerListGadget(#liste2, 410, 10, 390, 500, "c:\bremer\", #PB_Explorer_FullRowSelect)

   SetGadgetFont(#liste1, FontID(#font1))
   SetGadgetItemAttribute(#liste1, -1, #PB_Explorer_ColumnWidth, 190)
   
   ButtonGadget(#gadget1, 10, 530, 111, 44, "Freegadget")
   
   SetWindowCallback(@MainWindowCallback())
   
   ExplorerGadgetEdit(#liste1, #window)
   ExplorerGadgetEdit(#liste2, #window)
   
   Repeat: event = WaitWindowEvent()      
      If event = #PB_Event_Gadget          
         Select EventGadget()               
            Case #liste1
               
            Case #liste2
               ;aktualisieren von ExplorerTreeGadget erzwingen
               ;habe #PB_EventType_ReturnKey genommen, weil ich es schön finde, kann auch
               ;ein anderer sinnvoller Wert sein, aber nicht #PB_EventType_StatusChange 
               If EventType() = #PB_EventType_ReturnKey  
                  dir$ = GetGadgetText(#liste1) + "*.*"
                  SetGadgetText(#liste1, dir$)
               EndIf               
               
            Case #gadget1
               ;Eventtype() abfragen vermeidet doppelte Ausführung
               If EventType() = #PB_EventType_LeftClick
                  FreeGadget(#liste1)
               EndIf               
         EndSelect         
      EndIf      
   Until event = #PB_Event_CloseWindow 
   
EndProcedure

Mainwindow()

Re: PB 5.1 und PostEvent mit Edit von ExplorerTreeGadget

Verfasst: 09.01.2013 18:33
von edel

Code: Alles auswählen

PBEventAdd(ID, ObjectID, WindowID, Type) As "_PB_Event_Add@16"
Das ist falsch. Das "@16" hat da nicht zu suchen.

Re: PB 5.1 und PostEvent mit Edit von ExplorerTreeGadget

Verfasst: 09.01.2013 18:59
von hjbremer
dann kommt es weg :D