Wenn SHFileOperation()
verwenden, können Sie die FOF_SILENT
Flags verwenden, um den Standard-Fortschrittsdialog aus wird gezeigt zu verhindern.
Es ist jedoch keine Option zum programmierbaren Abbruch SHFileOperation()
verfügbar, sobald es gestartet wird. Verwenden Sie dafür stattdessen CopyFileEx()
oder CopyFile2()
.
Beide Funktionen können Sie eine Kopie auf zwei verschiedene Arten abbrechen:
sie beide akzeptieren einen Zeiger auf eine BOOL
Variable als Eingabe. Wenn Ihr Code die BOOL
Variable auf TRUE
setzt, während die Funktion ausgeführt wird, wird die Kopie abgebrochen.
beide akzeptieren einen Zeiger auf eine Callback-Funktion für Fortschrittsberichte. Der Rückruf wird während verschiedener Phasen der Kopie aufgerufen. Wenn der Callback einen Wert von CANCEL
oder STOP
zurückgibt, wird die Kopie abgebrochen (und im Fall von CANCEL
wird die Zieldatei gelöscht, während STOP
die Datei zu einem späteren Zeitpunkt wieder aufnehmen kann).
So oder so, beide Funktionen nicht angezeigt eigenen Fortschritt Dialog von Windows automatisch, aber Sie können display it manually mit der IProgressDialog
Schnittstelle. Oder Sie können stattdessen Ihren eigenen benutzerdefinierten Dialog anzeigen.
Es ist keine gute Benutzererfahrung, einen Fortschrittsdialog für jede einzelne Datei anzuzeigen/auszublenden, wenn mehrere Dateien verarbeitet werden. Es ist überflüssiger Aufwand für das Betriebssystem, die Dialoge zu erstellen und zu zerstören. Das potenzielle Flackern ist für den Benutzer kein Spaß, um visuell zu sehen. Sie sollten den Dialog einmal anzeigen, wenn er benötigt wird, und ihn dann sichtbar und aktualisiert halten, bis die letzte Datei fertig ist.
versuchen, etwas wie folgt aus:
var
// this is redundant since IProgressDialog has its own
// Cancel button, this is just an example to demonstrate
// cancellation in code...
CancelClicked: BOOL = FALSE;
function MyCopyProgressCallback(TotalFileSize, TotalBytesTransferred, StreamSize, StreamBytesTransferred: LARGE_INTEGER; dwStreamNumber: DWORD; dwCallbackReason: DWORD; hSourceFile, hDestinationFile: THandle; lpData: Pointer): DWORD; stdcall;
var
msg: WideString;
begin
msg := WideFormat('Transferred %d of %d bytes', [TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart]);
IProgressDialog(lpData).SetLine(2, PWideChar(msg), False, PPointer(nil)^);
if IProgressDialog(lpData).HasUserCancelled then
Result := PROGRESS_CANCEL
else
Result := PROGRESS_CONTINUE;
end;
...
var
FileFrom: string;
FileTo: string;
I: Integer;
ProgressDialog: IProgressDialog;
begin
...
CancelClicked := FALSE;
OleCheck(CoCreateInstance(CLSID_ProgressDialog, nil, CLSCTX_INPROC_SERVER, IProgressDialog, ProgressDialog));
try
ProgressDialog.SetTitle('Processing files');
ProgressDialog.SetCancelMsg('Canceling, please wait...', PPointer(nil)^);
ProgressDialog.SetProgress(0, TheStringList.Count);
ProgressDialog.StartProgressDialog(frmMain.Handle, nil, PROGDLG_MODAL or PROGDLG_AUTOTIME or PROGDLG_NOMINIMIZE, PPointer(nil)^);
ProgressDialog.Timer(PDTIMER_RESET, PPointer(nil)^);
for I := 0 to TheStringList.Count-1 do
begin
FileFrom := ...;
FileTo := ...;
ProgressDialog.SetLine(1, PWideChar(WideString(FileFrom)), True, PPointer(nil)^);
ProgressDialog.SetLine(2, '', False, PPointer(nil)^);
if ProgressDialog.HasUserCancelled then
Break;
...
if not CopyFileEx(PChar(FileFrom), PChar(FileTo), @MyCopyProgressCallback, Pointer(ProgressDialog), @CancelClicked, 0) then
begin
if GetLastError = ERROR_REQUEST_ABORTED then
Break;
// something else happened during the copy, so
// you can decide whether to stop the loop here
// or just move on to the next file...
end;
...
ProgressDialog.SetProgress(I+1, TheStringList.Count);
end;
finally
ProgressDialog.StopProgressDialog;
ProgressDialog := nil;
end;
...
end;
Alternativ können Sie die IFileOperation
Schnittstelle stattdessen verwenden. Dies ermöglicht Ihnen:
Warteschlange alle Dateipfade vor der Zeit seiner CopyItem()
und CopyItems()
Methoden.
führen Sie alle in der Warteschlange befindlichen Kopien gleichzeitig mit der Methode PerformOperations()
aus.
implementieren Sie die IFileOperationProgressSink
Schnittstelle und Advise()
es, um Fortschrittsupdates zu erhalten. Dies beinhaltet die Möglichkeit, eigene Operationen durchzuführen (PreCopyItem()
) und nach (PostCopyItem()
) jede einzelne Datei zu kopieren. Jeder Fehler, den Sie von einer IFileOperationProgressSink
-Methode zurückgeben, bricht die gesamte Kopiersequenz ab.
Lassen Sie es den Standard-Windows-Fortschrittsdialog automatisch anzeigen lassen. Das Anzeigen des Dialogfelds wird verzögert, bis die Kopiersequenz länger als einige Sekunden dauert. Wenn Sie eine Menge kleiner Dateien schnell kopieren, muss der Dialog nicht angezeigt werden. Sobald jedoch eine merkliche Verzögerung auftritt, wird der Dialog für die aktuelle und die folgenden Dateien angezeigt, bis die Sequenz beendet ist. Wenn Sie das Verhalten anpassen möchten, können Sie die Schnittstelle IOperationsProgressDialog
implementieren und an die Methode IFileOperation::SetProgressDialog()
übergeben.
Verwenden Sie FOF_SILENT für kleine Dateien, alle Flags werden in der Dokumentation erklärt. –
Willkommen bei Stack Overflow. Du hast bewiesen, dass du weißt, wo die Dokumentation ist. Hast du es gelesen? Du hast den Teil über 'fof_Silent' gesehen, richtig? Hast Du es versucht? Welche weitere Frage hast du? Bitte [bearbeiten] Sie Ihre Frage zur Klärung. –
@Rob Kennedy: Danke, ich frage mich, ob ich mehr als nur das haben sollte, wie "FOF_FILESONLY" und/oder "FOF_NOCONFIRMATION" und/oder "FOF_NOERRORUI" und/oder ... etc. Genau was angenommen wird (Standard) ohne Flags und was ich definieren muss. – user3272241