Как определить, является ли данный PIDL файлом .zip или аналогичным?
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, которые могут быть поддержаны в будущем, или другие типы контейнеров, которые, тем не менее, не являются папками.
Я не хочу исключать такие вещи, как «Сеть» и «Компьютер» из допустимых узлов. Только те, которые являются проблемными, такие как "Downloads \ Foobar.zip"
Я прошу прощения за этот бессвязный вопрос. Будем благодарны за любую помощь в улучшении моего понимания и творческих подходов к пониманию того, какие объекты являются частью пространства имен оболочки Microsoft и как их можно с пользой использовать!