Copy, Move oder Delete mit Fortschrittsanzeige

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
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Copy, Move oder Delete mit Fortschrittsanzeige

Beitrag von ts-soft »

Code: Alles auswählen

Procedure CopyWithProgress(Sources.s(), Destination.s, Function.l = #FO_COPY, Flags.l = #FOF_FILESONLY, ParendID.l = 0)
  Protected File.SHFILEOPSTRUCT, *Mem.l, Length.l, Pos.l
  *Mem = AllocateMemory(1)
  With File
    If ParendID = 0
      \hwnd = GetForegroundWindow_()
    Else
      \hwnd = ParendID
    EndIf
    \wFunc = Function
    ForEach Sources()
      Length = Len(Sources()) + 1
      *Mem = ReAllocateMemory(*Mem, Pos + Length)
      PokeS(*Mem + Pos, Sources(), Length)
      Pos + Length
    Next
    \pFrom = *Mem
    \pTo = @Destination
    \fFlags =Flags
  EndWith
  If SHFileOperation_(File) = #S_OK
    FreeMemory(*Mem)
    ProcedureReturn #True
  EndIf
  FreeMemory(*Mem)
  ProcedureReturn #False
EndProcedure
Wer ausser kopieren was anderes wünscht, möge die Flags im PSDK nachschlagen
Beispiel:

Code: Alles auswählen

NewList MySources.s()
AddElement(MySources())
MySources() = #PB_Compiler_Home + "PureBasic.exe"
AddElement(MySources())
MySources() = #PB_Compiler_Home + "SmartUpdate.exe"
AddElement(MySources())
MySources() = #PB_Compiler_Home + "Visual Designer.exe"
AddElement(MySources())
MySources() = #PB_Compiler_Home + "Examples\Sources\Billboard.pb"
AddElement(MySources())
MySources() = #PB_Compiler_Home + "Examples\Sources\Camera.pb"
AddElement(MySources())
MySources() = #PB_Compiler_Home + "Examples\Sources\CDAudio.pb"
AddElement(MySources())
MySources() = #PB_Compiler_Home + "Examples\Sources\Cipher.pb"
; hier bitte anpassen, etwas grösseres, sonst sieht man nicht viel
AddElement(MySources())
MySources() = "G:\Installation\CD-Images\Betriebssysteme\Kanotix\KANOTIX-2005-04.iso"
; usw.

CopyWithProgress(MySources(), GetTemporaryDirectory())
Ein paar etwas grössere Dateien sind schon sinnvoll, damit man den
Fortschritt auch angezeigt bekommt
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Kurzer
Beiträge: 1617
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Beitrag von Kurzer »

Hallo ts-soft,
danke für diesen Code, genau danach habe ich gesucht. :allright:

Was mich jedoch wundert ist, warum das mit

Code: Alles auswählen

\pTo = @Destination
funktioniert.

Lt. API HIlfe müssen sowohl pFrom als auch pTo Doppelnull-terminierte Listen sein.
pFrom ...Pointer to a buffer that specifies one or more source file names. Multiple names must be null-separated. The list of names must be double null-terminated...
pTo ...Pointer to a buffer that contains the name of the destination file or directory. The buffer can contain mutiple destination file names if the fFlags member specifies FOF_MULTIDESTFILES. Multiple names must be null-separated. The list of names must be double null-terminated.



Wenn man nur eine einzelne Datei kopieren möchte, dann kann man sich das Allokieren des Memeories und das Anlegen einer Liste übrigens sparen. Ich habe es mit Strings gelöst, in die direkt die zweite Null gepoked wird.

Code: Alles auswählen

Procedure CopyWithProgress(Source$, Destination$)
  Protected File.SHFILEOPSTRUCT, Length.l
  
  Source$ = Source$ + " " : PokeB(@Source$ + Len(Source$)-1, 0)
  Destination$ = Destination$ + " " : PokeB(@Destination$ + Len(Destination$)-1, 0)
  
  With File
    \hwnd = WindowID(0)
    \wFunc = #FO_COPY
    \pFrom = @Source$
    \pTo = @Destination$
    \fFlags = #FOF_FILESONLY|#FOF_NOCONFIRMATION
  EndWith

  Res = SHFileOperation_(File)
  
  If Res = #S_OK
    ProcedureReturn #True
  ElseIf Res = #DE_OPCANCELLED ; User-Abort, #DE_OPCANCELLED muß mit 117 definiert werden
    ProcedureReturn #DE_OPCANCELLED
  EndIf
  ProcedureReturn #False
EndProcedure
Gruß Markus
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2024: 56 Jahre.
Antworten