现在的位置: 首页 > 综合 > 正文

项目总结(三)——复制文件时显示进度对话框

2018年04月11日 ⁄ 综合 ⁄ 共 4436字 ⁄ 字号 评论关闭

 

 

实际需求介绍:

       由于本系统将采用光盘随书分发,故写了个光盘运行菜单程序,使用户可以选择安装和快捷浏览部分文件。本来这个菜单程序功能也没什么,很容易实现。谁知最后客户突然要求加个菜单项来拷贝音频文件,这就麻烦了,音频文件有600MB,使用CopyFile函数肯定不行,这么大肯定需要一些时间,这么长时间总不能不给点提示让用户干等吧!而我又是一个很懒的人,不想自己去实现进度显示功能,很想调用Windows的右键菜单复制功能来实现。
【注1】

       没法子,谁让“客户”是上帝呢!只有“加班”查找资料了!功夫不负有心人,让我看到了外壳操作函数SHFileOperation可以实现上述功能,于是赶紧学习了下其使用方法。

 

MSDN上SHFileOperation函数原型如下:

 

int SHFileOperation( __in  LPSHFILEOPSTRUCT  lpFileOp );

(1) 该函数的功能是 复制、移动、重命名、删除 一个文件系统对象。【注2】

(2) 参数lpFileOp是一个指向SHFILEOPSTRUCT结构体的指针,该参数不能为空,SHFILEOPSTRUCT结构体包含了该函数执行指定操作所需的信息。

(3) 返回值:成功返回0,否则返回非0。【注3】

 

MSDN上SHFILEOPSTRUCT结构体定义如下:

typedef struct _SHFILEOPSTRUCT {

HWND                 hwnd;

UINT                    wFunc;

LPCTSTR             pFrom;

LPCTSTR             pTo;

FILEOP_FLAGS   fFlags;

BOOL                   fAnyOperationsAborted;

LPVOID                hNameMappings;

LPCTSTR             lpszProgressTitle;

} SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT;

 

各成员含义如下:

(1) hwnd  显示信息的对话框的窗口句柄

 

(2) wFunc  执行的操作,可取以下值。

可取的值

将执行的操作

FO_COPY

将pFrom指定的文件复制到pTo

FO_DELETE

删除pFrom指定的文件

FO_MOVE

将pFrom指定的文件移动到pTo

FO_RENAME

重命名pFrom指定的单个文件

 

(3) pFrom  指定要操作的文件。该成员是一个路径,最好使用完整路径,在路径的最后文件名部分可以使用通配符,如“*”等,进行指定多个文件。虽然该成员申明的类型是LPCTSTR,一个以单个NULL字符(即\0)终结的字符串,但实际上是一个可以保存多个以NULL字符终结的文件名的缓冲,该缓冲在最后再加一个NULL字符表示结尾。

 

(4) pTo    指示目的文件夹(目录)或目的文件。该成员如果不用(如当wFunc=FO_DELETE时)必须设为NULL。和pFrom一样,该成员也是一个以两个NULL字符结尾的字符串,但该成员不能使用通配符。对于复制与移动操作,如果pTo指定的目录不存在,将显示一个询问是否创建新目录的对话框,要禁止显示该询问对话框而直接创建,请设置FOF_NOCONFIRMMKDIR到fFlags成员。如果fFlags中含有FOF_MULTIDESTFILES,pTo缓冲中可含多个文件名。

 

(5) fFlag   控制文件操作标志。可取下列值通过“|”结合。

说明

FOF_ALLOWUNDO

允许撤消,允许放回回收站。如果pFrom不包含完全限定路径和文件名,该标志将被忽视

FOF_CONFIRMMOUSE

(未使用)

FOF_FILESONLY

pFrom的文件名部分含有通配符时只操作文件

FOF_MULTIDESTFILES

pTo指定多个目的文件而不是一个目的文件夹(目录)

FOF_NOCONFIRMATION

以“全部是”自动响应所有显示对话框

FOF_NOCONFIRMMKDIR

不询问是否创建新目录(当操作需要创建新目录时自动创建)

FOF_NO_CONNECTED_ELEMENTS

不移动关联文件(5.0版本)

FOF_NOCOPYSECURITYATTRIBS

不复制属性,目的文件从新文件夹获取安全属性(4.71版本)

FOF_NOERRORUI

当出错时不显示对话框

FOF_NORECURSEREPARSE

(未使用)

FOF_NORECURSION

执行操作只针对当前目录,不递归针对子文件夹

FOF_NO_UI

后台执行操作,不显示界面和所有对话框,相当于FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR。(6.0.6060版本——Windows Vista)

FOF_RENAMEONCOLLISION

当文件名冲突时执行重命名操作

FOF_SILENT

不显示进度对话框界面

FOF_SIMPLEPROGRESS

示进度对话框界面,但不显示当前正在操作的文件(简单模式)

FOF_WANTMAPPINGHANDLE

当已指定FOF_RENAMEONCOLLISION和所以文件已被重命名,分配一个包含新旧文件名的名称映射对象给hNameMappings成员,当不再使用该对象时,需用SHFreeNameMappings释放该对象

FOF_WANTNUKEWARNING

当文件被永久删除而非删除到回收站时,给出一个警告(5.0版本)

 

(6) fAnyOperationsAborted  如果执行的操作在其完成前,人为取消退出或系统默认选择取消退出,则该成员被设置为True,否则为Flase。

(7) hNameMappings       一个名称映射对象句柄,该对象包含重命名文件的新旧文件名称。只有在fFlags成员含有FOF_WANTMAPPINGHANDLE标志时,该成员才可用。

(8) lpszProgressTitle       进度对话框界面的标题,只有在fFlags成员含有FOF_SIMPLEPROGRESS标志时,该成员才有效。

 

在使用SHFILEOPSTRUCT结构体给SHFileOperation传参之前,有必要了解MSDN上关于该结构体解释说明的Remarks部分http://msdn.microsoft.com/en-us/library/bb759795(v=VS.85).aspx

 

       通过以上的介绍,利用SHFileOperation函数很容易实现复制文件时显示进度对话框的功能。Delphi源代码如下:

{******************************************************************}
{                  FileOperationDialog unit                        }
{                    (文件操作对话框单元)                            }
{                                                                  }
{                Author:tht      QQ:245806497                      }
{                Blog:http://blog.csdn.net/tht2009                 }
{                   Copyright(c) 2011 THT                          }
{                         2011年9月                                      }
{******************************************************************}
{(1)dlgCopyFiles(FromPath,ToPath:string)     复制同目录下的文件       }
{                                                                  }
{******************************************************************}
unit FileOPDlg;

interface
uses  ShellAPI;

function dlgCopyFiles(FromPath,ToPath:string):Integer;


implementation

//********************************************************************
//功能:将FromPath路径指定的文件拷贝到ToPath指定路径下
//参数:(1)FromPath,一个完全限定的文件路径,指定源操作文件位置
//      (2)ToPath,目的文件位置,如果ToPath指定的目录不存在将自动创建它
//返回值:  1,复制操作成功完成
//         0,复制操作被取消
//        -1,复制操作执行失败
//
// 说明:ToPath中不能含有通配符
//      若FromPath指定一个文件,则ToPath可以指定一个目录或一个将创建的
//      新文件;若FromPath指定一个目录或含有通配符的路径,即使ToPath指
//      定一个新文件,ToPath也将被解析为一个目录(目录名即为新文件名)。
//*********************************************************************
function dlgCopyFiles(FromPath,ToPath:string):Integer;
var
lpFileOP:SHFileOpStruct;
begin
  lpFileOP.Wnd:=0;
  lpFileOP.wFunc:=FO_COPY;
  lpFileOP.pFrom:=PWideChar(FromPath+#0);
  lpFileOP.pTo:=PWideChar(ToPath+#0);
  //自动创建目录
  lpFileOP.fFlags:=FOF_NOCONFIRMMKDIR;
  Result:=SHFileOperation(lpFileOP);
  if(lpFileOP.fAnyOperationsAborted)then
  Result:=0
  else
  begin
    if(Result=0)then Result:=1
    else Result:=-1;
  end;
end;

end.

 

 测试效果

      

 



[1]:虽然大小只有600MB,但文件数量有两万多个,而且文件分布无规律,如果要达到系统复制的界面效果,一个个去枚举文件,我估计也不是件简单的事。

[2]:该函数在Windows Vista 上已被IFileOperation接口替代,使用后者能获得更强大的功能。有关IFileOperation 接口的详细资料请参见MSDN的介绍http://msdn.microsoft.com/en-us/library/bb775771(v=VS.85).aspx http://blog.csdn.net/tht2009/article/details/6787271

[3]:更多关于SHFileOperation函数返回值的说明请参见http://msdn.microsoft.com/en-us/library/bb762164(v=VS.85).aspx

 

 

 

 

 

 

抱歉!评论已关闭.