CopyProgrRoutine



  • Hallo,
    ich bastle gerade an einem Programm, mit dem ich große Dateien kopieren möchte. Mit folgendem Code starte ich den Kopiervorgang und rufe die Callback-Funktion CopyProgrRoutine, um mir den Status im Hauptfenster anzeigen zu lassen. Alles funktioniert sehr schön abegesehen von der Tatsache, dass der Fortschritt nur dann angezeigt wird, wenn der Kopiervorgang abgeschlossen ist, weil das Hauptfenster (von dem aus die Copy-Funktion aufgerufen wird) in der Zeit nicht reagiert. Wenn ich die Callback-Funktion mit "Run to Cursor" im Compiler verfolge, sehe ich aber den Fortschritt. Wie kann ich denn das Problem lösen?

    {
    ...
    
    	CopyFileEx(szFullSourceFilePath.c_str(), szFullTargetFilePath.c_str(), &CopyProgrRoutine, NULL, FALSE, COPY_FILE_OPEN_SOURCE_FOR_WRITE);
    ...
    }
    
    DWORD CALLBACK 
    	CopyProgrRoutine(
    					LARGE_INTEGER TotalFileSize,
    					LARGE_INTEGER TotalBytesTransferred,
    					LARGE_INTEGER StreamSize,
    					LARGE_INTEGER StreamBytesTransferred,
    					DWORD dwStreamNumber,
    					DWORD dwCallbackReason,
    					HANDLE hSourceFile,
    					HANDLE hDestinationFile,
    					LPVOID lpData) 
    {
    	// Calculate the percentage here.
    	long double part        = (long double)TotalBytesTransferred.QuadPart;
    	long double total       = (long double)TotalFileSize.QuadPart;
    	long double Percentage        = 0;
    
    	if (total)      // Prevent Division by Zero.
    		Percentage = (part / total) * 100;
    
    	HWND hTargetPathEdit = GetDlgItem(hDlgMain, IDC_MAINWTARGET);
    
    	SetWindowText(hTargetPathEdit, NumberToStr<long double, string> (Percentage, Holder).c_str());
    
    	// Continue the file copy. It can also be stopped.
    	return PROGRESS_CONTINUE;
    }
    

    Grüße,
    Rewind.

    P.S. weiß nicht ob das von Bedeutung ist, aber die CopyFile-Funktion rufe ich nicht direkt vom Hauptfenster aus, sondern von einer normalen Funktion. Vereinfacht dargestellt würde das also so aussehen:
    LRESULT CALLBACK DlgProc(...) -> SomeFunction() { hier CopyFileEx() } -> CALLBACK CopyProgrRoutine()



  • Bitte verschieben - hab nicht gesehen, dass ich im falschen Forum bin.



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C++ (auch C++0x) in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Ich habe diese Funktion bisher nicht benutzt, aber das sieht ganz so danach aus, das du die Funktion aus einen Thread heraus aufrufen solltest. Das Problem dürfte sein, das die Message- Warteschlange während der CopyFilefunktion nicht abgearbeitet wird (die ja letztendlich dafür sorgt, das die Anzeige refresht wird), weil sie aus dem Hautpthread aufgerufen wird.

    Vertrachte also am besten CopyFileEx in einen separaten Thread.



  • Ich habs schon geahnt, dass ich nicht drum herum komme..


  • Mod

    Du kannst jederzeit mit UpdateWindow/RedrawWindow eine Aktualisierung dieses Fensters erzwingen.

    Allerdings würde ich prüfen ob hier SetWindowText nicht etwas oft aufgerufen wird und nur dann diese Aktion durchführen, wenn sich der Text auch ändert.



  • Danke, Martin, das hat tatsächlich den gewünschten Effekt gebracht 😉 Erzwingen möchte ich allerdings nichts. Ich muss mich auf jeden Fall mehr mit Threads und Messages auseinandersetzen sonst wird das hier nichts (oder nur ein gerade noch funktionierendes Programm).



  • SHFileOperation mit den entsprechenden Parameter geht auch, da bekommste sogar den Fortschrittsdialog des Windows Explorers angezeigt, inkl. Animation. Ist vielleicht ne Alternative...



  • DocShoe schrieb:

    SHFileOperation mit den entsprechenden Parameter geht auch, da bekommste sogar den Fortschrittsdialog des Windows Explorers angezeigt, inkl. Animation. Ist vielleicht ne Alternative...

    Die Funktion ist mir bekannt und genau diesen Effekt wollte ich nicht haben.


  • Mod

    [Rewind] schrieb:

    Danke, Martin, das hat tatsächlich den gewünschten Effekt gebracht 😉 Erzwingen möchte ich allerdings nichts. Ich muss mich auf jeden Fall mehr mit Threads und Messages auseinandersetzen sonst wird das hier nichts (oder nur ein gerade noch funktionierendes Programm).

    Solange Du hier nur einen Thread hast ist hier alles im gründen Bereich.
    D.h. wnen der Thread der CopyFileEx ausführt der gleiche ist, der auch den Progress-Dialog rzeugt hat, dnan ist UpdateWindow simpel und trvial.

    Theoretisch könntest Du das ausbauen und PumpMessage ausführen, wenn Du die entsprechende UI disablest, damit der User keine unerwünscten Fnktionen ausführen kann.


Anmelden zum Antworten