Filtering file types with CMFCShellTreeCtrl

1.2k views Asked by At

I'm using a CMFCShellTreeCtrl derived class called CShellTreeCtrl in an CMFCOutlookBar object to display files and I'd like to filter file types and later be able to drag and drop files from it.

I've managed to display files as well as folders, but struggling to understand how to use IEnumIDList to achieve the file type filtering.

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

There are 1 answers

0
Jak On BEST ANSWER

Got it working with the following code adapted from 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;
}