如何检测给定的PIDL是否实际上是.zip文件或类似文件
How to detect if a given PIDL is actually a .zip file or similar?
VS2010引入了CMFCShellTreeCtrl,它允许将文件夹浏览器树ctrl放到我们的MFC应用程序中。
然而,这个类似乎严重缺乏过滤功能。也就是说,它将构建容器对象列表(IShellFolder)。但是似乎没有办法指定。zip容器不应该显示在文件夹树中。
它确实提供了一个虚值,可以粗略地用于此目的:
HRESULT CMFCShellTreeCtrl::EnumObjects(HTREEITEM hParentItem, LPSHELLFOLDER pParentFolder, LPITEMIDLIST pidlParent) { ASSERT_VALID(this); ASSERT_VALID(afxShellManager); LPENUMIDLIST pEnum = NULL; HRESULT hr = pParentFolder->EnumObjects(NULL, m_dwFlags, &pEnum); if (FAILED(hr) || pEnum == NULL) { return hr; } LPITEMIDLIST pidlTemp; DWORD dwFetched = 1; // Enumerate the item's PIDLs: while (SUCCEEDED(pEnum->Next(1, &pidlTemp, &dwFetched)) && dwFetched) { TVITEM tvItem; ZeroMemory(&tvItem, sizeof(tvItem)); // Fill in the TV_ITEM structure for this item: tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN; // AddRef the parent folder so it's pointer stays valid: pParentFolder->AddRef(); // Put the private information in the lParam: LPAFX_SHELLITEMINFO pItem = (LPAFX_SHELLITEMINFO)GlobalAlloc(GPTR, sizeof(AFX_SHELLITEMINFO)); ENSURE(pItem != NULL); pItem->pidlRel = pidlTemp; pItem->pidlFQ = afxShellManager->ConcatenateItem(pidlParent, pidlTemp); pItem->pParentFolder = pParentFolder; tvItem.lParam = (LPARAM)pItem; CString strItem = OnGetItemText(pItem); tvItem.pszText = strItem.GetBuffer(strItem.GetLength()); tvItem.iImage = OnGetItemIcon(pItem, FALSE); tvItem.iSelectedImage = OnGetItemIcon(pItem, TRUE); // Determine if the item has children: DWORD dwAttribs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_DISPLAYATTRMASK | SFGAO_CANRENAME | SFGAO_FILESYSANCESTOR; pParentFolder->GetAttributesOf(1, (LPCITEMIDLIST*) &pidlTemp, &dwAttribs); tvItem.cChildren = (dwAttribs & (SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR)); // Determine if the item is shared: if (dwAttribs & SFGAO_SHARE) { tvItem.mask |= TVIF_STATE; tvItem.stateMask |= TVIS_OVERLAYMASK; tvItem.state |= INDEXTOOVERLAYMASK(1); //1 is the index for the shared overlay image } // Fill in the TV_INSERTSTRUCT structure for this item: TVINSERTSTRUCT tvInsert; tvInsert.item = tvItem; tvInsert.hInsertAfter = TVI_LAST; tvInsert.hParent = hParentItem; InsertItem(&tvInsert); dwFetched = 0; } pEnum->Release(); return S_OK; }
令我感到困惑的是,缺乏区分枚举对象类型的能力(或者没有更好的方法来首先控制枚举,以便过滤掉诸如此类的非文件系统对象)。
可以查看正在枚举的项目的文本,如果它以".zip"结尾,则可以简单地排除它。然而,这对我来说似乎很不靠谱。毕竟,可以将任意文件夹命名为XYZ.zip(它仍然是一个文件夹,而不是zip归档文件)。类似地,除了.zip之外,将来可能还会支持其他的归档类型——或者其他容器类型,尽管它们不是真正的文件夹。
我不想从有效节点中消除像"网络"answers"计算机"这样的东西。只有一些有问题的,比如"DownloadsFoobar.zip"
我为这个问题跑题道歉。任何有助于提高我的理解和创造性方法,以了解哪些类型的对象是Microsoft shell名称空间的一部分,以及如何有效地使用它们,将不胜感激!一个zip文件/文件夹会有SFGAO_STREAM/SFGAO_DROPTARGET和SFGAO_FOLDER,所以如果你能把shell项目读成流,那么它可能不是一个目录。另一种方法是使用SHGetPathFromIDList+PathIsDirectory,但是这只适用于具有文件系统路径的pidl。
还有其他类型的可浏览文件,比如保存的搜索(如果您浏览到文件中,则可能需要很长时间才能完成枚举项),因此您可能也需要考虑如何处理这些文件。
相关文章:
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 文本文件中的单词链表
- CMake-按正确顺序将项目与C运行时对象文件链接
- 使用新行和不使用新行读取文件
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 挂起和取消挂起一个文件DLL
- 如何确定我已使用非编码文件到达 EOF?
- 命名空间中具有.h和.cpp文件的类
- 如何使用ndk-build.cmd构建Android.so文件
- 从包含m行的文件中提取n行,必要时(惰性地)重复该文件
- C++:实际上不是从二进制文件中读取
- 成功使用CMakeLists制作后如何修复"open: No such file or directory"错误(该文件实际上存在)
- Android本机运行时无法加载符号,即使它们实际上是在加载的.so文件中找到的
- 确定特定文件实际上是一个3GP文件
- feof()实际上是如何知道何时到达文件末尾的
- C++和 Sqlite DELETE 查询实际上不会从数据库文件中删除该值
- Qt信号/槽实际上是如何耦合到.ui文件中的元素的?
- 使用 fstream.h 可以打开多少文件是否有任何限制(实际上)
- 如何检测给定的PIDL是否实际上是.zip文件或类似文件