本文介绍了如何检测给定的PIDL是否实际上是.zip文件或类似文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

VS2010引入了CMFCShellTreeCtrl,它允许将文件夹浏览器树ctrl拖放到我们的MFC应用程序中.

VS2010 introduced CMFCShellTreeCtrl which allows for a folder-browser tree ctrl to be dropped into our MFC apps.

但是,此类似乎严重缺乏过滤功能.即它将构建容器对象列表(IShellFolder).但是似乎没有一种方法可以指定.zip容器不应显示在文件夹树中.

However, there seems to be a serious lack of filtering capabilities in this class. i.e. it will build the list of container-objects (IShellFolder). But there doesn't seem to be a way to specify that .zip containers should not be displayed in the folder tree.

它确实提供了一个可以粗略用于此目的的虚拟器:

It does supply a virtual that could be used crudely for this purpose:

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;
}

我感到困惑的是,缺乏区分被枚举的对象类型的能力(或者更好的方法是首先控制枚举,从而过滤掉诸如此类的非文件系统对象).

What I am confused by is the lack of ability to distinguish what type of object this is that is being enumerated (or a better way to control the enumeration in the first place so as to filter out non-filesystem objects such as these).

可以查看要枚举的项目的文本,如果以".zip"结尾,则可以将其排除.但是,这对我来说似乎很奇怪.毕竟,任意文件夹都可以命名为XYZ.zip(仍然是文件夹,而不是zip存档).同样,将来可能还支持除.zip以外的其他存档类型-或其他不是文件夹的容器类型.

It's possible to look at the text for the item being enumerated, and simply exclude it if it ends in ".zip". However, this seems wonky to me. After all, an arbitrary folder could be named XYZ.zip (which still being a folder, and not a zip archive). Similarly, there are likely other archive types than just .zip that may be yet supported in the future - or other container types which are nevertheless not really folders.

我不想消除网络"和计算机"之类的有效节点.只是那些有问题的文件,例如"Downloads \ Foobar.zip"

I don't want to eliminate things like "Network" and "Computer" from being valid nodes. Just ones that are problematic such as "Downloads\Foobar.zip"

我很抱歉这个问题很漫长.对于提高我的理解力和创造性方法的任何帮助,以了解哪种对象是Microsoft外壳程序命名空间的一部分,以及如何可以有偿地使用它们都是很重要的!

I apologize for this question being rambling. Any help in improving my understanding and creative approaches to knowing what sorts of objects are part of Microsoft's shell namespace, and how that they can be gainfully used would be appreciated!

推荐答案

一个zip文件/文件夹将具有SFGAO_STREAM/SFGAO_DROPTARGET和SFGAO_FOLDER,因此,如果您可以将外壳项目读取为流,那么它可能不是目录.另一种判断方法是使用SHGetPathFromIDList + PathIsDirectory,但这仅适用于具有文件系统路径的pidl.

A zip file/folder would have SFGAO_STREAM/SFGAO_DROPTARGET along with SFGAO_FOLDER, so if you can read the shell item as stream, then it probably isn't a directory. Another way to tell is to use SHGetPathFromIDList+PathIsDirectory, however this only works for pidl that have file system paths.

还有其他种类的可浏览文件,例如保存的搜索(如果您浏览该文件,它就像永远要枚举所有项一样),因此您可能还想考虑如何处理这些文件.

There are other kind of browsable files too, like a saved search (and if you browse into the file it takes like forever to finish enumerating the items), so you probably want to think about how to deal with those files too.

这篇关于如何检测给定的PIDL是否实际上是.zip文件或类似文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-07 01:57