R
Jap genau. Deswegen deklariere ich die Callback-Funktion erstmal im Kopf und formuliere sie dann weiter unten aus.
Ich deklariere sie also bloß einmal.
Das ist einfach schönerer Programmierstil. Weil wenn du jede Funktion die neu hinzukommt immer bloß in den Kopf schreibst wird das irgendwann sehr unübersichtlich.
Zu deinem Problem mit dem Abbrechen. Bool-Werte sind in der WinApi ints.
So müsste das korrekt aussehen:
private: // Anwender-Deklarationen
int bCancel ;
Mit *bCancel würdest du dem Compiler sagen das er bCancel als Pointer betrachten soll. Allerdings ist das natürlich kein Pointer. Daher die Exception.
So muss es richtig aussehen:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
bCancel=TRUE;
}
Außerdem solltest du bCancel jedes mal auf FALSE setzen bevor du CopyFileEx aufrufst. Sonst klappt es nichtmehr nachdem du einmal abgebrochen hast weil bCancel dann ja auf TRUE steht.
Also so:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
bCancel=FALSE;
CopyFileEx(Edit1->Text.c_str(), Edit2->Text.c_str(),
CopyProgressRoutine, CGauge1, &bCancel, 0); //Das & vor bCancel nicht vergessen!!!
}
Dass die Form nicht einfriert verdankst du dem Application->ProcessMessages(). Schau dir dazu mal die Borland-Hilfe an.
Damit du die Form schließen kannst müssen zunächst alle Operationen die in der Form laufen beendet worden sein.
Also setzt du bCancel in der OnClose-Routine der Form einfach wieder auf TRUE:
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
bCancel=TRUE;
}
Ich hab mir noch ein paar Gedanken zur Dateigröße gemacht und bin darauf gekommen, dass es schon ab 2 GB Fehler gibt weil's dann im int einen Überlauf zum negativen hin gibt.
Das bedeutet, dass man da ein bisschen rumrechnen muss.
Das wäre mein Vorschlag:
DWORD CALLBACK CopyProgressRoutine(
LARGE_INTEGER TotalFileSize,
LARGE_INTEGER TotalBytesTransferred,
LARGE_INTEGER StreamSize,
LARGE_INTEGER StreamBytesTransferred,
DWORD dwStreamNumber,
DWORD dwCallbackReason,
HANDLE hSourceFile,
HANDLE hDestinationFile,
LPVOID lpData
) {
if ( dwCallbackReason == CALLBACK_STREAM_SWITCH )
{ ((TProgressBar*)lpData)->Max=TotalFileSize.HighPart+100; }
//Die Zahl die du hinzuaddierst ist egal, sollte jedoch nicht zu klein sein.
((TProgressBar*)lpData)->Position =
((TProgressBar*)lpData)->Max*TotalBytesTransferred.QuadPart/TotalFileSize.QuadPart;
Application->ProcessMessages();
return PROGRESS_CONTINUE ;
}
Das müsste bis zu Dateigrößen von 2^61-1 Byte = 2305843009213693951 Byte = 2147483647 Gigabyte (hoffe, dass ich mich nicht verrechnet habe ) eigentlich ganz gut funktionieren
Ich habs jetzt mit einer 7,5 Gig Datei getestet und da gings wunderbar.