实战经验:使用IFileOperationProgressSink接收文件操作通知
作者:BlogUpdater |
时间:2018-11-04 |
浏览:5736 |
评论已关闭 条评论
思路
新版本的文件操作可以使用IFileOperation接口来实现,IFileOperation接口用来替代旧的SHFileOperation。SHFileOperation可以实现基本的文件操作,如复制,剪切,删除,重命名等,但缺乏文件操作进度通知这一特性。有时候,我们希望能得到文件的操作进度,进而在界面上进行操作进度的可视化呈现,那么,试试新的IFileOperation接口吧。
要想接收IFileOperation的通知,需要先实现IFileOperationProgressSink接口,该接口中的一些方法可以在文件操作的前后被IFileOpeation实例调用,例如复制前调用你实现的PreCopyItem方法,复制后则调用的是PostCopyItem方法。另外,如果想得到文件操作的进度通知,直接实现IFileOperationProgressSink的UpdateProgress方法就可以了,这样文件操作的进度更新时,我们的应用程序就可以知道了。
以下是示例代码
class CFileOperationSink : public IFileOperationProgressSink
{
public:
CFileOperationSink(HWND hWndNotify = NULL);
~CFileOperationSink(void);
public:
// 实现IUnknown接口
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv);
IFACEMETHODIMP_(ULONG) AddRef();
IFACEMETHODIMP_(ULONG) Release();
// 实现IFileOperationProgressSink接口
IFACEMETHODIMP StartOperations();
IFACEMETHODIMP FinishOperations(HRESULT hrResult);
IFACEMETHODIMP PreRenameItem(DWORD /*dwFlags*/, IShellItem * /*psiItem*/, PCWSTR /*pszNewName*/);
IFACEMETHODIMP PostRenameItem(DWORD /*dwFlags*/, IShellItem * /*psiItem*/, PCWSTR /*pszNewName*/, HRESULT /*hrRename*/, IShellItem * /*psiNewlyCreated*/);
IFACEMETHODIMP PreMoveItem(DWORD /*dwFlags*/, IShellItem * /*psiItem*/, IShellItem * /*psiDestinationFolder*/, PCWSTR /*pszNewName*/);
IFACEMETHODIMP PostMoveItem(DWORD /*dwFlags*/, IShellItem * /*psiItem*/,IShellItem * /*psiDestinationFolder*/, PCWSTR /*pszNewName*/, HRESULT /*hrNewName*/, IShellItem * /*psiNewlyCreated*/);
IFACEMETHODIMP PreCopyItem(DWORD dwFlags, IShellItem *psiItem,IShellItem *psiDestinationFolder, PCWSTR pszNewName);
IFACEMETHODIMP PostCopyItem(DWORD dwFlags, IShellItem *psiItem, IShellItem *psiDestinationFolder, PCWSTR pwszNewName, HRESULT hrCopy, IShellItem *psiNewlyCreated);
IFACEMETHODIMP PreDeleteItem(DWORD /*dwFlags*/, IShellItem * /*psiItem*/);
IFACEMETHODIMP PostDeleteItem(DWORD /*dwFlags*/, IShellItem * /*psiItem*/, HRESULT /*hrDelete*/, IShellItem * /*psiNewlyCreated*/);
IFACEMETHODIMP PreNewItem(DWORD /*dwFlags*/, IShellItem * /*psiDestinationFolder*/, PCWSTR /*pszNewName*/);
IFACEMETHODIMP PostNewItem(DWORD /*dwFlags*/, IShellItem * /*psiDestinationFolder*/,PCWSTR /*pszNewName*/, PCWSTR /*pszTemplateName*/, DWORD /*dwFileAttributes*/, HRESULT /*hrNew*/, IShellItem * /*psiNewItem*/);
IFACEMETHODIMP UpdateProgress(UINT iWorkTotal, UINT iWorkSoFar);
IFACEMETHODIMP ResetTimer();
IFACEMETHODIMP PauseTimer();
IFACEMETHODIMP ResumeTimer();
private:
HWND m_hWndNotify;
};
HRESULT FileCopy(LPCTSTR pszFrom, LPCTSTR pszTo)
{
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (FAILED(hr))
{
return hr;
}
IFileOperation * pfo = NULL;
hr = CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pfo));
if (FAILED(hr))
{
CoUninitialize();
return hr;
}
CFileOperationSink * pSink = new CFileOperationSink();
DWORD dwCookie = 0;
hr = pfo->Advise(pSink, &dwCookie);
if (FAILED(hr))
{
if (pfo != NULL)
{
pfo->Release();
pfo = NULL;
}
CoUninitialize();
return hr;
}
hr = pfo->SetOperationFlags(FOF_SILENT);
if (FAILED(hr))
{
if (pfo != NULL)
{
pfo->Release();
pfo = NULL;
}
CoUninitialize();
return hr;
}
// Create an IShellItem from the supplied source path
IShellItem * psiFrom = NULL;
hr = SHCreateItemFromParsingName(pszFrom, NULL, IID_PPV_ARGS(&psiFrom));
if (FAILED(hr))
{
if (pfo != NULL)
{
pfo->Release();
pfo = NULL;
}
CoUninitialize();
return hr;
}
// Create an IShellItem from the supplied destination path
IShellItem * psiTo = NULL;
hr = SHCreateItemFromParsingName(pszTo, NULL, IID_PPV_ARGS(&psiTo));
if (FAILED(hr))
{
if (psiFrom != NULL)
{
psiFrom->Release();
pszFrom = NULL;
}
if (pfo != NULL)
{
pfo->Release();
pfo = NULL;
}
CoUninitialize();
return hr;
}
hr = pfo->CopyItem(psiFrom, psiTo, NULL, NULL);
if (FAILED(hr))
{
if (psiFrom != NULL)
{
psiFrom->Release();
pszFrom = NULL;
}
if (psiTo != NULL)
{
psiTo->Release();
psiTo = NULL;
}
if (pfo != NULL)
{
pfo->Release();
pfo = NULL;
}
CoUninitialize();
return hr;
}
hr = pfo->PerformOperations();
if (FAILED(hr))
{
if (psiFrom != NULL)
{
psiFrom->Release();
pszFrom = NULL;
}
if (psiTo != NULL)
{
psiTo->Release();
psiTo = NULL;
}
if (pfo != NULL)
{
pfo->Release();
pfo = NULL;
}
CoUninitialize();
return hr;
}
if (psiFrom != NULL)
{
psiFrom->Release();
pszFrom = NULL;
}
if (psiTo != NULL)
{
psiTo->Release();
psiTo = NULL;
}
hr = pfo->Unadvise(dwCookie);
if (pfo != NULL)
{
pfo->Release();
pfo = NULL;
}
CoUninitialize();
return hr;
}
总结
以上代码展示了如何通过一个类CFileOperationSink来实现IFileOperationProgressSink接口,也给出了IFileOperation的使用方法,但是需要注意的是,实际工程中,为了避免出现接口忘记释放或者重复释放的问题,推荐使用CComPtr智能指针进行接口操作。
关于COM智能指针的使用,请参考我的前一篇文章。
如需转载,请注明来自:拓扑梅尔智慧办公平台 | TopomelBox 官方站点
相关推荐
- Visual Studio Code C++扩展更新: clang-tidy
- Posted on 12月16日
- 新的C++安全编码规则出炉
- Posted on 10月09日
- 为什么鼠标按键释放后才执行对应的动作?
- Posted on 11月23日
- 第 380 期:微软发布适用于 Windows 10 系统的 KB5071546 更新
- Posted on 12月13日



评论已关闭。