SHFileOperation用法学习
在Windows的shellapi文件中定义了一个名为SHFileOperation()的外壳函数,它可以用来实现各种文件操作,例如文件的拷贝、删除和移动等,该函数使用起来非常简单,它只有一个指向SHFILEOPSTRUCT结构的参数。使用SHFileOperation()函数时只要填写该专用结构--SHFILEOPSTRUCT,告诉Windows执行什么样的操作,以及其它重要信息就行了。SHFileOperation()的特别之处在于它是一个高级外壳函数,不同于低级文件处理。当调用SHFileOperation操作文件时,相应的外壳拷贝处理器(如果有的话)被调用。如在删除某个文件时,SHFileOperation会将删除的文件放到Recycle Bin中。
SHFileOperation()函数原型为:WINSHELLAPI int WINAPI SHFileOperation(LPSHFILESTRUCT lpFileOp);
LPSHFILESTRUCT结构格式如下:
Typedef struct _shFILEOPSTRUCT
{
HWND hWnd; //消息发送的窗口句柄;
UINT wFunc; //操作类型
LPCSTR pFrom; //源文件以及路径
LPCSTR pTo; //目标文件以及路径
FILEOP_FLAGS fFlags; //操作选择位
LPVOID hNameMapping; //文件映射
LPCSTR lpszProgressTitle; //文件操作进度窗口标题
}SHFILEOPSTRUCT,FAR* LPSHFILEOPSTRUCT;
在这个结构中,hWnd是指向发送消息的窗口句柄,pFrom与pTo是进行文件操作的源文件名和目标文件名,它包含文件的路径,对应单个文件的路径字符串,或对于多个文件,必须以NULL作为字符串的结尾或文件路径名之间的间隔,否则在程序运行的时候会发生错误。另外,pFrom和pTo都支持通配符*和?,这大大方便了开发人员的使用。例如,源文件或目录有两个,则应是:char pFrom[]="d:/Test1/0d:/Text.txt/0",它表示对要D:盘Test1目录下的所有文件和D:盘上的Text.txt文件进行操作。字符串中的""是C语言中的''的转义符,'/0'则是NULL。wFunc 是结构中的一个非常重要的成员,它代表着函数将要进行的操作类型,它的取值为如下:
·FO_COPY: 拷贝文件pFrom到pTo 的指定位置。
·FO_RENAME: 将pFrom的文件名更名为pTo的文件名。
·FO_MOVE: 将pFrom的文件移动到pTo的地方。
·FO_DELETE: 删除pFrom指定的文件。
使用该函数进行文件拷贝、移动或删除时,如果需要的时间很长,则程序会自动在进行的过程中出现一个无模式的对话框(Windows操作系统提供的文件操作对话框),用来显示执行的进度和执行的时间,以及正在拷贝、移动或删除的文件名,此时结构中的成员lpszProgressTitle显示此对话框的标题。fFlags是在进行文件操作时的过程和状态控制标识。它主要有如下一些标识,也可以是其组合:
·FOF_FILESONLY:执行通配符,只执行文件;
·FOF_ALLOWUNDO:保存UNDO信息,以便在回收站中恢复文件;
·FOF_NOCONFIRMATION:在出现目标文件已存在的时候,如果不设置此项,则它会出现确认是否覆盖的对话框,设置此项则自动确认,进行覆盖,不出现对话框。
·FOF_NOERRORUI:设置此项后,当文件处理过程中出现错误时,不出现错误提示,否则会进行错误提示。
·FOF_RENAMEONCOLLISION:当已存在文件名时,对其进行更换文提示。
·FOF_SILENT:不显示进度对话框。
·FOF_WANTMAPPINGHANDLE:要求SHFileOperation()函数返回正处于操作状态的实际文件列表,文件列表名柄保存在hNameMappings成员中。
·SHFILEOPSTRUCT结构还包含一个SHNAMEMAPPING结构的数组,此数组保存由SHELL计算的每个处于操作状态的文件的新旧路径。
同时也有一个重要的应用就是:
在进行文件操作时,可以使用CFile类中的Remove()函数来删除一个文件,但是这样的操作将永久性的删除该文件,不能在必要的时候再恢复该文件,解决这个问题的唯一方法就是把文件送到Windows系统中的回收站(Recycle Bin)里面,而不是简单的永久性删除它,这样用户就可以在必要的时候恢复这个文件。用这个函数实现编程来实现Windows回收站的文件存取操作。
在使用该函数删除文件时必须设置SHFILEOPSTRUCT结构中的神秘FOF_ALLOWUNDO标志,这样才能将待删除的文件拷到Recycle Bin,从而使用户可以撤销删除操作。需要注意的是,如果pFrom设置为某个文件名,用FO_DELETE标志删除这个文件并不会将它移到Recycle Bin,甚至设置FOF_ALLOWUNDO标志也不行,在这里你必须使用全路径名,这样SHFileOperation才会将删除的文件移到Recycle Bin。
代码如下:
void CFileOperationView::OnFileDelete()
{
int nOk;
char strSrc[]="d:/Vb/0";//源文件路径;
char strDst[]="d:/Vb1/0";//目标文件路径;
char strTitle[]="文件拷贝"; //文件删除进度对话框标题
SHFILEOPSTRUCT FileOp;//定义SHFILEOPSTRUCT结构对象;
FileOp.hwnd=this->m_hWnd;
FileOp.wFunc=FO_DELETE; //执行文件删除操作;
FileOp.pFrom=strSrc;
FileOp.pTo=strDst;
FileOp.fFlags=FOF_ALLOWUNDO;//此标志使删除文件备份到Windows回收站
FileOp.hNameMappings=NULL;
FileOp.lpszProgressTitle=strTitle;
//开始删除文件
nOk=SHFileOperation(&FileOp);
if(nOk)
TRACE("There is an error: %d/n",nOk);
else
TRACE("SHFileOperation finished successfully/n");
}
fFlags成员标志间的关系
标志 |
抑制的对话框 |
相关性与优先级 |
FOF_MULTIDESTFILES |
无 |
无 |
FOF_FILESONLY |
无 |
无 |
FOF_SILENT |
如果设置,进度对话框不显示。 |
优先于FOF_SIMPLEPROGRESS标志。 |
FOF_SIMPLEPROGRESS |
无 |
为FOF_SILENT标志所抑制。 |
FOF_RENAMEONCOLLISION |
如果设置了这个标志,当被移动或拷贝的文件与已存在文件同名时置换对话框不会出现。 |
名字冲突时,如果FOF_NOCONFIRMATION标志设置,则操作继续。 如果二者都设置了,则它优先于FOF_NOCONFIRMATION。即,文件以给定的新名字复制,而不是覆盖。 |
FOF_NOCONFIRMATION |
如果设置,确认对话框在任何情况下都不出现。 |
名字冲突时,引起文件覆盖,除非设置了FOF_RENAMEONCOLLISION标志。 |
FOF_NOCONFIRMMKDIR |
抑制请求建立新文件夹的对话框 |
缺省目录作为严重错误产生一个错误消息框。 建立目录的确认对话框作为错误消息框是否显示依赖于FOF_NOERRORUI的设置。 |
FOF_NOERRORUI |
抑制所有错误消息框。 |
优先于前一个标志。如果设置,则,缺省目录引起不被处理的异常,并且返回错误码。 |
删除文件
文件删除是一个简单的操作,它仅仅影响到输入缓冲pFrom,而pTo缓冲被忽略。与文件复制一样,操作的详细情况依赖于标志的设置。相关的标志是:
标志 |
值 |
描述 |
FOF_SILENT |
0x0004 |
这个操作不回馈给用户,就是说,不显示进度对话框。相关的消息框仍然显示。 |
FOF_NOCONFIRMATION |
0x0010 |
这个标志使函数对任何遇到的消息框都自动回答Yes。 |
FOF_ALLOWUNDO |
0x0040 |
如果设置,这个标志强迫函数移动被删除的文件到‘回收站’中。否则,文件将被物理地从磁盘上删除。 |
FOF_FILESONLY |
0x0080 |
设置这个标志导致函数仅仅删除文件,跳过目录项。它仅仅应用于指定通配符的情况。 |
FOF_SIMPLEPROGRESS |
0x0100 |
这导致简化用户界面。使之只有动画而不报告被删除的文件名。代之的是显示lpszProgressTitle成员中指定的文字。(Win7实际中貌似不可用) |
FOF_NOERRORUI |
0x0400 |
如果设置了这个标志,任何发生的错误都不能使消息框显示,而是程序中返回错误码。 |
这里出现的标志最要紧的是FOF_ALLOWUNDO,它决定文件是否一次就全部删除,或存储到‘回收站’中等候可能的恢复。如果FOF_ALLOWUNDO被设置,文件则被移动到回收站,并且这个操作可以被Undo(尽管可以手动Undo)。Undo特征仅在删除下可用,在拷贝与移动中没有等价的操作。
SHFileOperation()函数的返回值
MSDN资料中说明,SHFileOperation()在成功时返回0,失败时返回非0值。显然这是真的,但并不是最有用的解释。重复测试这个函数,可以确信它有非常多的终止方式。事实上,我们经常在系统错误的提示中运行,在有些地方这个函数只是简单地返回从更靠近文件系统的其它程序中获得的返回码。下面列表给出了SHFileOperation()返回的最通常的部分错误。
错误码 |
描述 |
2 |
如果你试图重命名多重文件,这个消息就会出现。描述是相当直接的:系统不能找到指定的文件。 |
7 |
在询问是否想要置换给定文件时,你回答了‘取消’,函数就返回这个错误码。它的描述也是相当的不明确—存储控制块被销毁。 |
115 |
在试图重命名文件到不同的文件夹时,发生这个文件系统错。重命名文件只是改变文件名,而不能改变文件夹。 |
117 |
一个IOCTL错(输入/输出控制),在目的路径中有错误时或取消了新目录的建立时,这个错误发生了。 |
123 |
你正在试图重命名一个文件,然而你给出的名字是一个已经存在的文件。它也有一个无用的描述:文件名,目录名,或卷标号的语法是不正确的。 |
1026
|
在试图移动或拷贝一个不存在的文件时,出现这个文件系统错。一般地,它提示了,源缓冲中的某些东西应该修改一下。这个错误码弹出一个的错误框,你可以通过设置FOF_NOERRORUI标志抑制它的显示。 |