Avatar billede hrc Mester
15. januar 2014 - 15:06 Der er 2 kommentarer og
1 løsning

Brug af Winapi MoveFileWithProgress

Jeg prøver, i XE3, med et 32bit program, at bruge MoveFileWithProgress til at flytte nogle filer og tager udgangspunkt i dette: http://delphidabbler.com/tips/160.

Funktionen:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365242(v=vs.85).aspx

Call back headeren:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363854(v=vs.85).aspx

Ideen er at kalde MS' procedure for at flytte filer. Ved at koble en call back procedure på, kan jeg lave min egen visning af fremskridt.

Headeren er den samme om det er copy eller move så der afviger den ikke fra Peter Belows udgangspunkt. Har også prøvet med CopyFileEx og der er adresserne også forkerte:

function MoveCallback(TotalFileSize, TotalBytesTransferred, StreamSize, StreamBytesTransferred: Int64;
                      dwStreamNumber, dwCallbackReason: DWORD;
                      hSourceFile, hDestinationFile: THandle;
                      Data: LPVOID): DWORD; stdcall;

Problemet er parameteren Data som er en pointer til de data man gerne vil have ført med over i sin call back, eksempelvis en label der skal opdateres, eller en progressbar. Det virker bare ikke!
Hvis jeg tager adressen på panelet, hvis caption jeg vil bruge, så er den en ting før kaldet og en anden inde i call back'en. Kan nogen hjælpe mig?

Call back funktionen er her:

function MoveCallback(TotalFileSize, TotalBytesTransferred, StreamSize, StreamBytesTransferred: Int64;
                      dwStreamNumber, dwCallbackReason: DWORD;
                      hSourceFile, hDestinationFile: THandle;
                      aData: LPVOID): DWORD; stdcall;
var
  Pct: Integer;
const
  PROCESS_CONTINUE = 0; // carry on
  PROCESS_CANCEL = 1; // cancel and delete dest-file
  PROCESS_STOP = 2; // pause
  PROCESS_QUIET = 3; // don't call the call back routine no more
begin
  Result := PROCESS_CONTINUE;
  if dwCallbackReason = CALLBACK_CHUNK_FINISHED then
  begin
    if TotalBytesTransferred mod 100 = 0 then
    begin
      Pct := muldiv(100,TotalBytesTransferred,TotalFileSize);
      OutputDebugString(pchar('aData: ' + IntToHex(integer(addr(aData)),8)));
      //OutputDebugString(pchar(format('Flytter %s (%d/%d bytes) - %d %%',['',TotalBytesTransferred,TotalFileSize,NewPos])));
      // xx.Caption := ;
      Application.ProcessMessages;
    end;
  end;
end;

Kaldet her:

OutputDebugString(pchar('pProgress: ' + IntToHex(integer(addr(pProgress)),8)));
if not MoveFileWithProgress(pchar(Src + Filename),
                            pchar(Dst + Filename),
                            addr(MoveCallback),
                            pointer(pProgress),
                            MOVEFILE_COPY_ALLOWED or MOVEFILE_WRITE_THROUGH) then
begin
  LastError := GetLastError;
  MessageDlg(format('GetLastError: %d (%s)',[LastError,SysErrorMessage(LastError)]), mtInformation, [mbOK], 0);
end;
Avatar billede a_nor Nybegynder
15. januar 2014 - 15:59 #1
Hej HRC
Jeg går ud fra at du har prøvet at kalde med NIL i stede for callback-funktionsangivelsen, og at det virker.

Du skriver at det skal være (/er) en 32 bit version. Hvordan sikrer du at det er den "rigtige" kernel32 (fra Syswow64) der anvendes?

/ Anders
Avatar billede hrc Mester
15. januar 2014 - 16:32 #2
Jeg sikrer mig ikke noget. Bruger bare funktionen der findes i Delphi. Det virker fint med nil (også med, blot jeg ikke førsøger at bruge aData), men jeg vil netop have noget sendt med over. Uden den bliver jeg nødt til at have globale variable og den slags vil jeg undgå. I eksemplet jeg har snuppet ideen fra, skriver han at det er testet og virker - men hans eksempel virker heller ikke hos mig.
Avatar billede hrc Mester
16. januar 2014 - 09:43 #3
Jeg fik det til at virke. Humlen var, at aData var en var (sikken' sætning).

function MoveCallback(TotalFileSize, TotalBytesTransferred, StreamSize, StreamBytesTransferred: Int64;
                      dwStreamNumber, dwCallbackReason: DWORD;
                      hSourceFile, hDestinationFile: THandle;
                      var aData: LPVOID): DWORD; stdcall

Desuden troede jeg at pointer(Panel1) ville returnere adressen panelet, men der skulle en asterisk på.

if not MoveFileWithProgress(pchar(Src + Filename),
                            pchar(Dst + Filename),
                            addr(MoveCallback),
                            pointer(@pProgress),
                            MOVEFILE_COPY_ALLOWED or MOVEFILE_WRITE_THROUGH) then
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester