自做的文件复制函数(用API的FileCopy(...)),在复制大文件时进度条无法正常显示,像死机似的,有没有办法解决。100分。(能做出像Winows的文件复制的效果。)

解决方案 »

  1.   

    用fileread和filewrite吧
    可以先取得文件的大小,然后按字节读和写。(不是单个字节的读)
    这样进度条比较好控制。
    可惜pascal的语法忘的差不多了,只能说这么多
      

  2.   

    别用FileCopy吧,
    自己读写文件,用I/O 函数,或者流都可以。
      

  3.   

    如果是普通文件(也可以是二进制),DELPHI里有很好用的函数,
    BlockRead, BlockWrite,详细的参数你可以看一下帮助,这两
    个可以帮助你读和写,这样根据文件大小,很容易可以控制进度
    表,速度很快的(可以每次读2048以上字节,以加快之)
        :-> )
      

  4.   

    循环中加入
    Application.ProcessMessages;或放入子线程中处理
      

  5.   

    楼主在等代码否?要的话说一声。反正我不会写,正好看看。hoho...
    我up, up, up
      

  6.   

    多个文件用Application.ProcessMessages;是可以的,但我说的是只有一个文件的时候,并且这个文件很大,如100M时,如果文件很小当然没事啦
      

  7.   

    说不定Windows.CopyFileEx可以,但我也不会用,问问SDK/API的大牛们。
      

  8.   

    不用自己写吧,用一个API不行吗?
    WINSHELLAPI int WINAPI SHFileOperation(    LPSHFILEOPSTRUCT lpFileOp
       );
    在Delphi给你一个例子吧:
    uses
      ShellAPI;
    procedure TForm1.Button1Click(Sender: TObject);
    var
      ShFile:TSHFILEOPSTRUCT;
    begin
      ShFile.Wnd:=Handle;
      ShFile.pFrom:='D:\Example';
      ShFile.pTo:='P:\PJ';
      ShFile.wFunc:=FO_COPY;
      SHFileOperation(ShFile);
    end;
      

  9.   

    我不要API的,我要的是自己编的
      

  10.   

    其实用SHFileOperation很好啊,连对话框都有的。CopyFile不也是API吗?一定要自己写的话,就用TFileStream或者TMemoryStream,比较方便。
      

  11.   

    顺便说一句,API里面好东西多的是。
    大部分时候,当然有特殊要求的情况例外,只要是它有的函数,都会比你能写出来的要好,至少是会更通用。有很多Delphi的函数不过就是简单的封装一下API而已。再说这些东西最后都是要着落到API上实现的,你又何必计较那么多?
      

  12.   

    CopyFileEx(...)可以,它有一个回调
      

  13.   

    摩托~~~have a try:Function CopyProgressRoutine(
      TotalFileSize : Int64;
      TotalBytesTransferred : Int64;
      StreamSize : Int64;
      StreamBytesTransferred : Int64;
      dwStreamNumber : Cardinal;
      dwCallbackReason : DWord;
      hSourceFile : THandle;
      hDestinationFile : THandle;
      lpData : Pointer):integer;Begin
       form1.ProgressBar1.Max:=StreamSize;
       form1.ProgressBar1.Min :=0;
       form1.ProgressBar1.Position := StreamBytesTransferred;
       application.ProcessMessages ;
       Result := PROGRESS_CONTINUE;
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      if copyfileex(pchar('d:\ttt.mp3'),pchar('d:\lll.mp3'),@copyprogressroutine,nil,0,COPY_FILE_FAIL_IF_EXISTS) then showmessage('ok');
    end;
      

  14.   

    楼主:
    没有FileCopy这个API啊!嗬嗬,
    只有CopyFile和CopyFileEx这两个API啊!
    CopyFileEx这个API中的回调函数是干嘛用的?这个回调函数就是提供Copy的百分比的啊!
    看到同志们这么多的议论我要昏倒了!
      

  15.   

    to BlueTrees:
      CopyFileEx似乎只能在NT下用哦。
      

  16.   

    摩托的CopyFileEx的回调例子,没有问题的~~~~~
      

  17.   

    CopyFileEx的确只能在nt 2000下用~~~
      

  18.   

    function CreateFileStream(const filename: string; mode: Word): TFileStream;
    begin
      try
        Result := TFileStream.Create(filename, mode);
      except
        Result := nil;
      end;
    end;function MyCopyFile(const sfn, dfn: string): integer;   // Copy file ; ret 0 for ok, 1 for open error, 2 for copy error
    var
      sfm: TFileStream;
      dfm: TFileStream;
      hDir: string;
      i: integer;
      wantsize: integer;
      errstr: string;
      rescode: integer;
      tempstr: string;
      PreTick: Int64;
      CurTick: Int64;
      TransKValid: Int64;
    begin //
      SyncForm.syncMeter.Position := 0;  hDir := ExtractFileDir(dfn);
      if not DirectoryExists(hDir) then
        ForceDirectories(hDir);
      if FileExists(dfn) then
        FileSetAttr(dfn, faArchive);  // because some file can't be modified;  rescode := 0;  dfm := CreateFileStream(dfn, fmCreate);
      sfm := CreateFileStream(sfn, fmOpenRead or fmShareDenyNone);
      PreTick := GetTickCount();
      TransKValid := KILO16;
      wantsize := 1;
      try
        if (dfm = nil) then
        begin
          errstr := Faces[SYNLANBASE + 3] + dfn;
          rescode := 2;
        end
        else if (sfm = nil) then
        begin
          errstr := Faces[SYNLANBASE + 4] + sfn;
          rescode := 1;
        end
        else
        repeat
          CurTick := GetTickCount();
          if CurTick > PreTick then
          begin
            Inc(TransKValid, CurrTask.MaxSpeed * (CurTick-PreTick));
            PreTick := CurTick;
          end;
          if TransKValid < KILO16 then
          begin
            Application.ProcessMessages();
            Continue;
          end;
          wantsize := KILO16;
          if wantsize > sfm.Size - sfm.Position then
            wantsize := sfm.Size - sfm.Position;
          if wantsize > 0 then
          begin
            if (SyncStatus = ssBreak) then
            begin
              errstr := Faces[SYNLANBASE + 5] + sfn;
              rescode := 4;
              Break;
            end;
            try
              i := dfm.CopyFrom(sfm, wantsize);
              if i <> wantsize then
              begin
                rescode := 3;
                Break;
              end;
              Dec(TransKValid, i);
            except
              errstr := Faces[SYNLANBASE + 6] + sfn;
              rescode := 3;
              Break;
            end;
            if i > 0 then
            begin
              tempstr := Faces[SYNLANBASE + 7];
              SyncForm.syncMeter.Position := Int64(sfm.position) * 100 div sfm.Size; // 02252104
              Inc(fcSizeNow, i);
              SyncForm.totMeter.Position := fcSizeNow * 100 div fcTotalSize; // 02252104
              Replace(tempstr, '%1', Size2String(fcSizeNow));
              Replace(tempstr, '%2', Size2String(fcTotalSize - fcSizeNow));
              SyncForm.Label4.Caption := tempstr;
            end;
          end;
          Application.ProcessMessages();
        until (wantsize = 0);
      finally
        if sfm <> nil then
          sfm.Free();
        if dfm <> nil then
          dfm.Free();
        if wantsize > 0 then  // 未完成
        begin
          if dfm <> nil then
            DeleteFile(dfn);    // 删除未完成的目标文件
          resForm.resMemo.Lines.Append(errstr);
        end;
      end;
      if rescode = 0 then  // ok
      begin
        FileSetAge(dfn, FileAge(sfn));
        FileSetAttr(dfn, FileGetAttr(sfn));
      end;
      Result := rescode;
    end;
      

  19.   

    (补充)以下变量用于限制复制速度
      PreTick: Int64;
      CurTick: Int64;
      TransKValid: Int64