前言
经常随手花上个半到一个小时,自己手写一个拷贝系统文件的代码,里面用上个几重递归,然后判断下文件属性,看是文件夹还是文件。然后自己根据文件的大小来控制进度条的显示进度。是否真的需要付出这么多了?
最近,研究了一下windows shell编程,发现其实很多系统有的功能,系统早就做好,并且完完全全的提供给我们了,只是我们比较喜欢一步步的自己来维护每一个流程。最终导致的结果是,耽误了开发进度,同时造成了某些不可知的软件bug。
简介
在vista之前的版本中,经常可以使用SHFileOperation这个系统函数处理类似于文件的拷贝、移动、删除和重命名操作。但vista之后的版本,系统又提供了com库接口IFileOperation的方式来处理相同的文件操作。当然以前的方法依然适用。只不过最新的文件操作方法使用起来会更加的“人性化”(后面会提到)。
内容
旧版文件操作
拷贝操作
[cpp]
int CEarlyFileOperator::FOCopyFile(const wstring &strFrom, const wstring &strTo)
{
wchar_t srcPath[MAX_PATH];
wchar_t dstPath[MAX_PATH];
memset(srcPath,'\0',MAX_PATH);
memset(dstPath,'\0',MAX_PATH);
memcpy(srcPath,strFrom.c_str(),strFrom.length() * sizeof(wchar_t));
memcpy(dstPath,strTo.c_str(),strTo.length() * sizeof(wchar_t));
SHFILEOPSTRUCT FileOp = {0};
FileOp.hwnd = NULL; // 调用过程会改变父窗口属性
FileOp.wFunc = FO_COPY; // 执行文件拷贝
FileOp.pFrom = srcPath;
FileOp.pTo = dstPath;
FileOp.hNameMappings = NULL;
FileOp.fFlags = FOF_ALLOWUNDO;
FileOp.lpszProgressTitle = _T("文件正在拷贝中...");
int nRet = SHFileOperation(&FileOp);
return nRet;
}
移动操作
[cpp]
int CEarlyFileOperator::FORemoveFile(const wstring &strFrom, const wstring &strTo)
{
wchar_t srcPath[MAX_PATH];
wchar_t dstPath[MAX_PATH];
memset(srcPath,'\0',MAX_PATH);
memset(dstPath,'\0',MAX_PATH);
memcpy(srcPath,strFrom.c_str(),strFrom.length() * sizeof(wchar_t));
memcpy(dstPath,strTo.c_str(),strTo.length() * sizeof(wchar_t));
SHFILEOPSTRUCT FileOp = {0};
FileOp.hwnd = NULL; // 调用过程会改变父窗口属性
FileOp.wFunc = FO_MOVE; // 执行文件拷贝
FileOp.pFrom = srcPath;
FileOp.pTo = dstPath;
FileOp.hNameMappings = NULL;
FileOp.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR;
//FileOp.lpszProgressTitle = _T("文件正在拷贝中...");
int nRet = SHFileOperation(&FileOp);
return nRet;
}
删除操作
[cpp]
int CEarlyFileOperator::FODelFile(const wstring &strFrom)
{
wchar_t srcPath[MAX_PATH];
memset(srcPath,'\0',MAX_PATH);
memcpy(srcPath,strFrom.c_str(),strFrom.length() * sizeof(wchar_t));
SHFILEOPSTRUCT FileOp = {0};
FileOp.hwnd = NULL;
FileOp.wFunc = FO_DELETE;
FileOp.pFrom = srcPath;
FileOp.pTo = NULL;
FileOp.hNameMappings = NULL;
FileOp.fFlags = FOF_ALLOWUNDO; //允许撤销,不出现确认对话框
int nRet = SHFileOperation(&FileOp);
return nRet;
}
重命名操作
[cpp]
int CEarlyFileOperator::FORenameFile(const wstring &strFrom, const wstring &strRename)
{
wchar_t srcPath[MAX_PATH];
wchar_t reName[MAX_PATH];
memset(srcPath,'\0',MAX_PATH);
memset(reName,'\0',MAX_PATH);
// 获取路径地址
wstring strPath = strFrom.substr(0,strFrom.rfind(_T("\\")));
wstring strTo = strPath + _T("\\") + strRename;
memcpy(srcPath,strFrom.c_str(),strFrom.length() * sizeof(wchar_t));
memcpy(reName,strTo.c_str(),strTo.length() * sizeof(wchar_t));
SHFILEOPSTRUCT FileOp = {0};
FileOp.hwnd = NULL; // 调用过程会改变父窗口属性
FileOp.wFunc = FO_RENAME; // 执行文件拷贝
FileOp.pFrom = srcPath;
FileOp.pTo = reName;
FileOp.hNameMappings = NULL;
FileOp.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION;
int nRet = SHFileOperation(&FileOp);
return nRet;
}
新版文件操作
拷贝操作
[cpp]
int CLaterFileOperator::FOCopyFile(const wstring &strFrom, const wstring &strTo)
{
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr))
{
IFileOperation *pfo;
///< Create the IFileOperation inte易做图ce
hr = CoCreateInstance(CLSID_FileOperation,
NULL,
CLSCTX_ALL,
IID_PPV_ARGS(&pfo));
if (SUCCEEDED(hr))
{
///< Set the operation flags
hr = pfo->SetOperationFlags(FOF_ALLOWUNDO);
if (SUCCEEDED(hr))