ExplorerListGadget selbstgemacht
Verfasst: 24.01.2011 14:00
Das ExplorerListGadget ist ja eine feine Sache, was aber nervt ist das Geflacker beim aktualisieren, wenn man Daten ins aktuelle Verzeichnis kopiert hat. Tritt leider nur auf wenn rechts der vertikale Scrollbalken da ist.
Darum selbstgemacht, hier das Ergebnis incl. Beispiel für Windows x86 32Bit
Edit: Default in ExplorerFileGetGadgetItemState hinzugefügt
Darum selbstgemacht, hier das Ergebnis incl. Beispiel für Windows x86 32Bit
Code: Alles auswählen
;XIncludeFile "\Bremer\PureBasicPbi\debugmacros.pbi"
EnableExplicit
Structure ExplorerGadgetCallback ;um mehr als einen Wert an Callback zu übergeben, erspart Shared oder globale Variablen
lpPrevFunc.i ;subclassing
flag.i ;
;...
EndStructure
Structure LVHITPOSITION
StructureUnion ;für Callback Hitinfo
lparam.i ;teilt lparam in LoWord und Hiword
pt.points ;points besteht aus 2 Word
EndStructureUnion
EndStructure
#my_Explorer_Dir = 2
#my_Explorer_File = 4
#my_Explorer_Root = 1
#my_Explorer_Drive = 8
#my_Explorer_Run = 1 ;ExplorerFileGadget(10, 5, 5, 490, 590, "c:\", #my_Explorer_Run) = startet Anwendungen etc
#my_Explorer_Dirmax = 30000 ;max Anzahl Einträge pro Dir
#my_Explorer_ReadIcon = 1000 ;wenn Dir mehr Einträge hat, wird ein Standardicon benutzt, dauert mir sonst zulange
Procedure.i ExplorerFileGetGadgetItemState(nr, item)
Protected state = 0
If IsGadget(nr)
state = GetGadgetItemData(nr, item)
Select state
Case #my_Explorer_File: state = #PB_Explorer_File
Case #my_Explorer_Dir: state = #PB_Explorer_Directory
Default: state = #PB_Explorer_None
EndSelect
If GetGadgetItemState(nr, item) = #PB_ListIcon_Selected
state | #PB_Explorer_Selected
EndIf
EndIf
ProcedureReturn state
EndProcedure
Procedure.s ExplorerFileGetGadgetText(nr)
If IsGadget(nr)
Protected mem = GetGadgetData(nr)
If mem
ProcedureReturn Trim(PeekS(mem, #MAX_PATH))
EndIf
EndIf
ProcedureReturn ""
EndProcedure
Procedure.i ExplorerFileGadgetDrives(Array drives.s(1))
;wird von ExplorerFileGadgetUpdate() aufgerufen
Protected drive$ = Space(#MAX_PATH)
Protected memory = @drive$
Protected anzahl = GetLogicalDriveStrings_(#MAX_PATH, memory) / 4
Protected state.s = "3" ;drei für Laufwerk
Protected j, lw.s, typ.s = "unbekannt", name.s
ReDim drives(anzahl)
For j = 1 To anzahl
lw = PeekS(memory)
memory + 4
Select GetDriveType_(lw)
Case 2: typ = "Diskettenlaufwerk"
Case 3: typ = "Festplatte"
Case 4: typ = "Netzwerk"
Case 5: typ = "CD-Rom"
Case 6: typ = "Ram-Disk"
EndSelect
name = Space(#MAX_PATH)
GetVolumeInformation_(lw, @name, #MAX_PATH, 0,0,0,0,0)
drives(j) = state + lw + #LF$ + #LF$ + Trim(name) + " " + Trim(typ)
Next
ProcedureReturn anzahl
EndProcedure
Procedure.i ExplorerFileGadgetRead(Array entry.s(1), path.s)
;schreibt alle Einträge von path ins entry Feld (ohne die Inhalte aus Unterverzeichnissen)
;und setzt eine Zahl (state) davor, welche die Art des Eintrages kennzeichnet, Dir File etc
;diese Zahl wird dann in den Data Bereich einer Zeile des LV geschrieben und dient zum Sortieren
;und kann mit ExplorerFileGetGadgetItemState abgefragt werden.
Protected j
Protected name.s
Protected groesse.s, typ.s, datum.s
;Wert für GetGadgetItemData um Files und Ordner zu unterscheiden, wird in Update der Lv-Zeile zugewiesen
Protected state
If ExamineDirectory(0, path, "*.*")
While NextDirectoryEntry(0)
name = DirectoryEntryName(0)
;folgende Einträge überspringen
If name = ".": Continue: EndIf
If DirectoryEntryAttributes(0) & #PB_FileSystem_System: Continue: EndIf
If DirectoryEntryAttributes(0) & #PB_FileSystem_Hidden: Continue: EndIf
;es geht weiter
groesse = Str(Round(DirectoryEntrySize(0) / 1024, #PB_Round_Up)) + " Kb"
If groesse = "0 Kb": groesse = "": EndIf
If DirectoryEntryType(0) = #PB_DirectoryEntry_Directory
state = #my_Explorer_Dir
typ = "Ordner"
If name = "..": state = #my_Explorer_Root: typ = path: EndIf
Else
state = #my_Explorer_File
typ = UCase(GetExtensionPart(name))
Select typ
Case "PB": typ = "PureBasic"
Case "PBI": typ = "PB Include"
Case "JPG": typ = "Bild"
Case "JPEG": typ = "Bild"
Case "EXE": typ = "Anwendung"
Case "DLL": typ = "Bibliothek"
Case "CHM": typ = "Hilfe Datei"
;case usw.
Default: typ + " Datei"
EndSelect
EndIf
datum = FormatDate("%dd.%mm.%yyyy - %hh:%ii:%ss", DirectoryEntryDate(0, #PB_Date_Modified))
j + 1
If j > #my_Explorer_Dirmax: Break: EndIf
entry(j) = Str(state) + name + #LF$ + groesse + #LF$ + typ + #LF$ + datum
Wend
FinishDirectory(0)
EndIf
ReDim entry(j)
SortArray(entry(), #PB_Sort_NoCase)
ProcedureReturn j
EndProcedure
Procedure.i ExplorerFileGadgetIcon(entry.s)
Protected info.SHFILEINFO, flags = #SHGFI_ICON | #SHGFI_USEFILEATTRIBUTES | #SHGFI_SMALLICON
Protected p = FindString(entry, #LF$, 1)
entry = Left(entry, p - 1) ;:Debug entry
SHGetFileInfo_(entry, #FILE_ATTRIBUTE_NORMAL, info, SizeOf(SHFILEINFO), flags)
ProcedureReturn info\hIcon
EndProcedure
Procedure.i ExplorerFileGadgetUpdate(nr, path.s = "")
;hängt immer ein \ an wenn nicht vorhanden !!!
;liest Ordner ins entry Feld ein
;zeigt Daten an
;schreibt Pfad in LV-Data Bereich !
If Not IsGadget(nr): ProcedureReturn: EndIf
path = Trim(path)
If Not path
;falls ExplorerFileGadgetUpdate() ohne Path aufgerufen wird
path = ExplorerFileGetGadgetText(nr) ;wenn ""
If Not path: path = "C:\": EndIf ;dann c:\
EndIf
If Right(path, 1) <> "\": path + "\": EndIf
If Mid(path, 2, 1) <> ":": path = Left(GetCurrentDirectory(), 2) + path: EndIf
Static diricon, rooticon, driveicon, fileicon, icon, cursor_ori, cursor_app
If Not diricon
diricon = ExtractIcon_(0,"Shell32.dll", 3)
fileicon = ExtractIcon_(0,"Shell32.dll", 0)
rooticon = ExtractIcon_(0,"Shell32.dll", 146)
driveicon = ExtractIcon_(0,"Shell32.dll", 7)
cursor_ori = GetClassLongPtr_(GetParent_(GadgetID(nr)), #GCL_HCURSOR)
cursor_app = LoadCursor_(0, #IDC_APPSTARTING)
EndIf
SetCursor_(cursor_app)
ShowCursor_(#True)
Protected Dim entry.s(#my_Explorer_Dirmax), anz, j , state, item = 0
anz = ExplorerFileGadgetRead(entry(), path) ;:Debug path: Debug anz
SendMessage_(GadgetID(nr), #WM_SETREDRAW, #False, 0) ;oder HideGadget(nr, 1) für schnelles anzeigen
ClearGadgetItems(nr)
If anz
state = Val(Left(entry(1), 1))
;wenn es kein Root Eintrag gibt
If state <> #my_Explorer_Root
AddGadgetItem(nr, item, "..", rooticon)
SetGadgetItemColor(nr, item, #PB_Gadget_FrontColor, #Red, 0)
SetGadgetItemText(nr, item, path, 2)
SetGadgetItemData(nr, item, #my_Explorer_Root)
item + 1
EndIf
For j = 1 To anz
state = Val(Left(entry(j), 1))
If state = #my_Explorer_Root
AddGadgetItem(nr, item, Mid(entry(j), 2), rooticon) ;state im String überspringen
SetGadgetItemColor(nr, item, #PB_Gadget_FrontColor, #Red, 0)
SetGadgetItemData(nr, item, state)
item + 1
ElseIf state = #my_Explorer_Dir
AddGadgetItem(nr, item, Mid(entry(j), 2), diricon)
SetGadgetItemColor(nr, item, #PB_Gadget_FrontColor, #Blue, 0)
SetGadgetItemData(nr, item, state)
item + 1
Else
icon = fileicon
If anz < #my_Explorer_ReadIcon
icon = ExplorerFileGadgetIcon(path + Mid(entry(j), 2))
EndIf
AddGadgetItem(nr, item, Mid(entry(j), 2), icon)
SetGadgetItemData(nr, item, state)
item + 1
EndIf
Next
Else
;wenn anz null, dann falsches Lw im Path !
;ist Absicht, wenn vom Root Verzeichnis zurück gegangen wird
;oder Fehler beim Aufruf vom ExplorerFileGadget() mit falschem Lw im Path
anz = ExplorerFileGadgetDrives(entry())
For j = 1 To anz
AddGadgetItem(nr, -1, Mid(entry(j), 2), driveicon)
state = Val(Left(entry(j), 1))
SetGadgetItemData(nr, j - 1, #my_Explorer_Drive)
Next
EndIf
Protected mem = GetGadgetData(nr)
PokeS(mem, path, #MAX_PATH)
;Spaltenbreite
SendMessage_(GadgetID(nr), #LVM_SETCOLUMNWIDTH, 1, #LVSCW_AUTOSIZE_USEHEADER)
SendMessage_(GadgetID(nr), #LVM_SETCOLUMNWIDTH, 2, #LVSCW_AUTOSIZE_USEHEADER)
If GetGadgetItemAttribute(nr, 0, #PB_ListIcon_ColumnWidth, 2) > 120
SetGadgetItemAttribute(nr, 0, #PB_ListIcon_ColumnWidth, 120, 2)
EndIf
SendMessage_(GadgetID(nr), #LVM_SETCOLUMNWIDTH, 3, #LVSCW_AUTOSIZE_USEHEADER)
SendMessage_(GadgetID(nr), #WM_SETREDRAW, #True, 0) ;oder HideGadget(nr, 0)
SetCursor_(cursor_ori)
ShowCursor_(#True)
EndProcedure
Procedure.i ExplorerFileGadgetCallback(hWnd, msg, wParam, lParam)
Protected *p.ExplorerGadgetCallback = GetWindowLongPtr_(hWnd, #GWL_USERDATA)
If msg = #WM_LBUTTONDBLCLK ;515
Protected HitPosi.LVHITPOSITION
Protected HitInfo.LVHITTESTINFO
HitPosi\lparam = lParam
Hitinfo\pt\x = HitPosi\pt\x
HitInfo\pt\y = HitPosi\pt\y
SendMessage_(hwnd, #LVM_SUBITEMHITTEST, 0, HitInfo)
Protected nr, mem, path.s, anz, j, endg.s, state
;pbnr holen, path + state lesen
nr = GetDlgCtrlID_(hwnd)
mem = GetGadgetData(nr)
path = PeekS(mem)
state = GetGadgetItemData(nr, hitinfo\iitem)
;Debugl(hitinfo\iitem)
;Debugl(hitinfo\isubitem)
;Debugs(path)
;Debugl(state)
If state = #my_Explorer_Drive
;Laufwerk angeklickt oder ".." im Root Verzeichnis
path = GetGadgetItemText(nr, hitinfo\iitem)
ExplorerFileGadgetUpdate(nr, path)
ElseIf state = #my_Explorer_Root
;zurück ".." angeklickt
anz = CountString(path, "\")
If anz > 1
For j = Len(path) - 1 To 1 Step -1
If Mid(path, j, 1) = "\": Break: EndIf
Next
path = Left(path, j)
ExplorerFileGadgetUpdate(nr, path)
Else
;wenn ".." im Root Verzeichnis angeklickt, dann falsches Lw zuweisen damit Drives gelesen werden
path = "1"
ExplorerFileGadgetUpdate(nr, path)
EndIf
ElseIf state = #my_Explorer_Dir
path + GetGadgetItemText(nr, hitinfo\iitem)
ExplorerFileGadgetUpdate(nr, path)
ElseIf state = #my_Explorer_File
If *p\flag & #my_Explorer_Run
path + GetGadgetItemText(nr, hitinfo\iitem)
endg = LCase(GetExtensionPart(path))
Select endg
Case "txt"
RunProgram("Notepad", path, "")
Case "jpg", "jpeg", "pb", "pbi" ;usw
RunProgram(path)
EndSelect
EndIf
EndIf
EndIf
ProcedureReturn CallWindowProc_(*p\lpPrevFunc, hWnd, msg, wParam, lParam)
EndProcedure
Procedure.i ExplorerFileGadget(nr, x, y, br, hh, path.s, flag = 0)
Protected *p.ExplorerGadgetCallback ;um mehr als einen Wert an den Callback zu übergeben
*p = AllocateMemory(SizeOf(ExplorerGadgetCallback))
*p\flag = flag
Protected id
Protected lvflags = #PB_ListIcon_MultiSelect|#PB_ListIcon_AlwaysShowSelection|#PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect
If nr = #PB_Any
nr = ListIconGadget(#PB_Any, x, y, br, hh, "Name", 150, lvflags)
Else
id = ListIconGadget(nr, x, y, br, hh, "Name", 150, lvflags)
EndIf
AddGadgetColumn(nr, 1, "Größe", 80)
AddGadgetColumn(nr, 2, "Typ", 120)
AddGadgetColumn(nr, 3, "Datum", 120)
;subclassing
*p\lpPrevFunc = SetWindowLongPtr_(GadgetID(nr), #GWL_WNDPROC, @ExplorerFileGadgetCallback())
SetWindowLongPtr_(GadgetID(nr), #GWL_USERDATA, *p)
;Format: fmt = #LVCFMT_CENTER, #LVCFMT_LEFT, #LVCFMT_RIGHT
Protected lv.LV_COLUMN
lv\mask = #LVCF_FMT
lv\fmt = #LVCFMT_RIGHT
SendMessage_(GadgetID(nr), #LVM_SETCOLUMN, 1, lv)
lv\fmt = #LVCFMT_CENTER
SendMessage_(GadgetID(nr), #LVM_SETCOLUMN, 2, lv)
Protected exstyle = SendMessage_(GadgetID(nr), #LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0)
SendMessage_(GadgetID(nr), #LVM_SETEXTENDEDLISTVIEWSTYLE, 0, exstyle | #LVS_EX_LABELTIP)
;Platz für Path und mem merken im LV
Protected mem = AllocateMemory(#MAX_PATH + 2)
SetGadgetData(nr, mem)
;Directory lesen
ExplorerFileGadgetUpdate(nr, path)
If id
ProcedureReturn id
Else
ProcedureReturn nr
EndIf
EndProcedure
Code: Alles auswählen
Define event, nr, item, state
OpenWindow(0, 100, 100, 500, 600, "ListIcon Example", #PB_Window_SystemMenu)
nr = ExplorerFileGadget(#PB_Any, 5, 5, 490, 590, "c:\")
Repeat
Event = WaitWindowEvent()
If event = #PB_Event_Gadget
If EventGadget() = nr
Select EventType()
Case #PB_EventType_LeftClick
Debug ExplorerFileGetGadgetText(nr)
item = GetGadgetState(nr)
state = ExplorerFileGetGadgetItemState(nr, item)
If state & #PB_Explorer_Directory
Debug GetGadgetItemText(nr, item) + " ist ein Dir"
ElseIf state & #PB_Explorer_File
Debug GetGadgetItemText(nr, item) + " ist ein File"
EndIf
If ExplorerFileGetGadgetItemState(nr, 3) & #PB_Explorer_Selected
Debug "item 3 ist selected"
EndIf
EndSelect
EndIf
EndIf
Until Event = #PB_Event_CloseWindow