使用CMFCShellTreeCtrl过滤文件类型

时间:2014-11-27 09:40:48

标签: c++ mfc treeview mfc-feature-pack

我在CMFCOutlookBar对象中使用一个名为CShellTreeCtrl的CMFCShellTreeCtrl派生类来显示文件,我想过滤文件类型,以后可以从中拖放文件。

我设法显示文件和文件夹,但很难理解如何使用IEnumIDList来实现文件类型过滤。

int CBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMFCOutlookBar::OnCreate(lpCreateStruct) == -1)
    return -1;

CMFCOutlookBarTabCtrl* pOutlookBar = (CMFCOutlookBarTabCtrl*)GetUnderlyingWindow();

if (pOutlookBar != NULL)
{
    pOutlookBar->SetImageList(IDB_PAGES_HC, 24);
    pOutlookBar->SetToolbarImageList(IDB_PAGES_SMALL_HC, 16);
    pOutlookBar->EnableInPlaceEdit(FALSE);
    RecalcLayout();
}

RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);

// can float, can autohide, can resize, CAN NOT CLOSE
DWORD dwStyle = AFX_CBRS_AUTOHIDE | AFX_CBRS_RESIZE;


CRect rectDummy(0, 0, 0, 0);
const DWORD dwTreeStyle = WS_CHILD | WS_VISIBLE | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_INFOTIP;
m_pDirList = new CShellTreeCtrl;
m_pDirList->Create(dwTreeStyle, rectDummy, this, ID_SHELLDRILL);
m_pDirList->SetFlags(m_pDirList->GetFlags() | SHCONTF_NONFOLDERS);
pOutlookBar->AddControl(m_pDirList, _T("Folders"), 2, FALSE, dwStyle);
}

1 个答案:

答案 0 :(得分:0)

使用以下代码改编自this similar question

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

        string str = strItem;

        if (tvItem.cChildren & SFGAO_HASSUBFOLDER)
        {
            InsertItem(&tvInsert);
        }
        else
        {
            if ((str.substr(str.find_last_of(".") + 1) == "pdf"))
            {
                InsertItem(&tvInsert);
            }
        }
        dwFetched = 0;
    }

    pEnum->Release();
    return S_OK;
}