PB 5.1 und PostEvent mit Edit von ExplorerTreeGadget
Verfasst: 09.01.2013 18:01
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.
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()