实战经验:使用IFileOperationProgressSink接收文件操作通知
作者:BlogUpdater |
时间:2018-11-04 |
浏览:5124 |
评论已关闭 条评论
思路
新版本的文件操作可以使用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 官方站点
相关推荐
- 你需要知道的:WM_WINDOWPOSCHANGED 的隐藏用法
- Posted on 05月27日
- C++模块介绍第一部分:主模块接口
- Posted on 07月25日
- Visual Studio: 关于内联的决策过程
- Posted on 08月04日
- 错误信息:VS2010添加成员变量提示JS错误
- Posted on 11月22日
评论已关闭。