API函数CopyFileEx使用详解(delphi)

  • A+
所属分类:[开发技巧]

{ 函数原型 }

function CopyFileEx(
lpExistingFileName : PChar; // 来源文件
lpNewFileName : PChar; // 目标文件
lpProgressRoutine : TFNProgressRoutine; // 用于返回文件有关信息的回调函数
lpData : Pointer; // 传递给回调函数的参数
pbCancel : PBool; // 用于中途取消拷贝,函数会监视此值的状态,如果为真,则停止拷贝
dwCopyFlags : DWORD // 选项标志,见定义
): BOOL; stdcall; // 返回拷贝成功还是失败

{ CopyFileEx 回调函数可能的返回值 }

PROGRESS_CONTINUE = 0; // 让拷贝过程继续
PROGRESS_CANCEL = 1; // 终止拷贝过程并删除目标文件
PROGRESS_STOP = 2; // 停止拷贝,但以后可以继续开始
PROGRESS_QUIET = 3; // 让拷贝过程继续,但从此不再进行回调

{ CopyFileEx 回调函数状态 }

CALLBACK_STREAM_SWITCH = $00000001; // 第一次回调的状态是 CALLBACK_STREAM_SWITCH
CALLBACK_CHUNK_FINISHED = $00000000; // 而后的状态都是 CALLBACK_CHUNK_FINISHED

{ CopyFileEx 选项标志 }

COPY_FILE_FAIL_IF_EXISTS = $00000001; //文件存在则取消拷贝
COPY_FILE_RESTARTABLE = $00000002; //拷贝失败可重新开始

{ 回调函数原型 }

TFarProc = Pointer;
TFNProgressRoutine = TFarProc; //指针类型

function CopyProgress(
TotalFileSize : LARGE_INTEGER; // 文件总大小,字节
TotalBytesTransferred : LARGE_INTEGER; // 已复制的文件大小,字节
StreamSize : LARGE_INTEGER; // 当前流的总字节数
StreamBytesTransferred: LARGE_INTEGER; // 当前流已拷贝的字节数
dwStreamNumber : DWORD; // 当前流序号
dwCallbackReason : DWORD; // 回调函数的状态,见定义
hSourceFile : THANDLE; // 来源文件句柄
hDestinationFile : THANDLE; // 目标文件句柄
lpData : Pointer // CopyFileEx 函数传递过来的参数
) : DWORD; stdcall; // 回调函数的返回值,见定义

{ 说明 }

该函数复制一个已存在的文件到一个新文件。该函数保留了文件的扩展属性,OLE存储格式和文件属性。文件的安全属性不复制到新文件中去。
如果目标文件存在,且具有只读属性,则函数执行失败。
该函数每复制 65536字节(即64KB) 的内容后就调用一次回调函数。
第一次调用回调函数时 dwCallbackReason(回调函数的状态) 的值为 CALLBACK_STREAM_SWITCH,此时不复制任何数据,只是告诉回调函数,将要开始复制数据了。
此函数是线程同步的,也就是说,在主窗口中调用此函数时,窗口将无法响应用户的操作,直到文件复制完毕为止。
此函数无法复制锁定的文件,比如页面文件 PageFile.sys。就像在资源管理器中复制 PageFile.sys 一样,会提示文件正被另一个程序使用,无法复制。此函数不会提示错误,只会返回逻辑值否,表示复制失败。

{============================================================}
{ 例子 }
{============================================================}

unit Main;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm2 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
procedure Button2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form2 : TForm2;
Cancel : Boolean;
iCount : Integer;

implementation

{$R *.dfm}

function CopyProgress(
TotalFileSize: LARGE_INTEGER; // 文件总大小,字节
TotalBytesTransferred: LARGE_INTEGER; // 已复制的文件大小,字节
StreamSize: LARGE_INTEGER; // 当前流的总字节数
StreamBytesTransferred: LARGE_INTEGER; // 当前流已拷贝的字节数
dwStreamNumber: DWORD; // 当前流序号
dwCallbackReason: DWORD; // 回调函数的状态,见定义
hSourceFile: THANDLE; // 来源文件句柄
hDestinationFile: THANDLE; // 目标文件句柄
lpData: Pointer // CopyFileEx 函数传递过来的参数
): DWORD; stdcall; // 回调函数的返回值,见定义
begin
// if iCount = 2 then begin
// Result := PROGRESS_STOP;
// Exit;
// end;
Application.ProcessMessages;
Form2.Memo1.Clear;
Form2.Memo1.Lines.Add(IntToStr(TotalFileSize.QuadPart));
Form2.Memo1.Lines.Add(IntToStr(TotalBytesTransferred.QuadPart));
Form2.Memo1.Lines.Add(IntToStr(StreamSize.QuadPart));
Form2.Memo1.Lines.Add(IntToStr(StreamBytesTransferred.QuadPart));
Form2.Memo1.Lines.Add(IntToStr(dwStreamNumber));
Form2.Memo1.Lines.Add(IntToStr(Result));
Inc(iCount);
end;

procedure TForm2.Button1Click(Sender: TObject);
var
Src, Dest : string;
begin
iCount := 0;
Cancel := False;
Src := 'D:\Tools.rar';
Dest := 'E:\Tools.rar';

if not FileExists(Src) then begin
Memo1.Text := '文件 ' + Src + ' 不存在!';
Exit;
end;

CopyFileEx(
PChar(Src),
PChar(Dest),
@CopyProgress,
nil,
@Cancel,
COPY_FILE_RESTARTABLE);
end;

procedure TForm2.Button2Click(Sender: TObject);
begin
Cancel := True;
end;

end.

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin
广告也精彩
avatar
广告也精彩

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: