⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shelltree.cpp

📁 一个完整的编辑器的代码(很值得参考
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include "stdafx.h"
#include "shelltree.h"
#include "shfileinfo.h"
#include "fpattern.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#pragma warning ( disable : 4711 )
////////////////////////////////////////////////////////////////////////////////
// CShellTree
//

CShellTree::CShellTree ()
{
  m_flags = SHLT_FOLDERS;
}

CShellTree:: ~ CShellTree ()
{
}

BEGIN_MESSAGE_MAP (CShellTree, CTreeCtrl)
//{{AFX_MSG_MAP(CShellTree)
ON_MESSAGE (SHLT_GETFLAGS, OnGetFlags)
ON_MESSAGE (SHLT_MODIFYFLAGS, OnModifyFlags)
ON_MESSAGE (SHLT_MODIFYPATTERN, OnModifyPattern)
//}}AFX_MSG_MAP
END_MESSAGE_MAP ()

#pragma warning ( disable : 4100 )
LRESULT CShellTree::OnGetFlags (WPARAM wParam, LPARAM lParam)
{
  return GetFlags ();
}
#pragma warning ( default : 4100 )

LRESULT CShellTree::
OnModifyFlags (WPARAM wParam, LPARAM lParam)
{
  ModifyFlags (wParam, lParam);
  return 0;
}

#pragma warning ( disable : 4100 )
LRESULT CShellTree::
OnModifyPattern (WPARAM wParam, LPARAM lParam)
{
  ModifyPattern ((LPCTSTR) lParam);
  return 0;
}
#pragma warning ( default : 4100 )

DWORD CShellTree::
GetFlags ()
const
{
  return m_flags;
}

void CShellTree::ModifyFlags (DWORD dwRemove, DWORD dwAdd)
{
  DWORD flags = m_flags;

  m_flags &= ~dwRemove;
  m_flags |= dwAdd;
  if (m_flags != flags)
    PopulateTree ();
}

void CShellTree::
ModifyPattern (CString pattern)
{
  CString part;
  int pos, len = pattern.GetLength ();

  m_patterns.RemoveAll ();
  while ((pos = pattern.Find (_T (','))) != -1)
    {
      part = pattern.Left (pos);
      if (!part.IsEmpty () && fpattern_isvalid (part))
        {
          m_patterns.AddTail (part);
        }
      len -= pos + 1;
      pattern = pattern.Right (len);
    }
  if (pattern.IsEmpty () && fpattern_isvalid (pattern))
    {
      m_patterns.AddTail (pattern);
    }
  if (m_flags & SHLT_FILES)
    PopulateTree ();
}

/****************************************************************************
 *
 *    FUNCTION: PopulateTree()
 *
 *    PURPOSE:  Processes the File.Fill/RefreshTree command
 *
 ****************************************************************************/
void CShellTree::
PopulateTree ()
{

  LPSHELLFOLDER lpsf = NULL;
  LPITEMIDLIST lpi = NULL;
  HRESULT hr;
  TV_SORTCB tvscb;

  // Get a pointer to the desktop folder.
  hr = SHGetDesktopFolder (&lpsf);

  if (SUCCEEDED (hr))
    {
      // Initialize the tree view to be empty.
      DeleteAllItems ();

      // Fill in the tree view from the root.
      FillTreeView (lpsf, NULL, TVI_ROOT);
      //TunnelFillTree(lpsf, NULL, TVI_ROOT);
      // Release the folder pointer.
      lpsf->Release ();
    }
  tvscb.hParent = TVI_ROOT;
  tvscb.lParam = 0;
  tvscb.lpfnCompare = TreeViewCompareProc;

  // Sort the items in the tree view
  SortChildrenCB (&tvscb /*, FALSE */ );

  HTREEITEM hItem;
  hItem = GetRootItem ();
  Expand (hItem, TVE_EXPAND);
  Select (GetRootItem (), TVGN_CARET);
}

/****************************************************************************
 *
 *  FUNCTION:   PopulateTree()
 *
 *  PURPOSE:    Processes the File.Fill/RefreshTree command
 *              This overload  has the ability to open from a
 *              special folderlocation like SHBrowseForFolder()
 *
 *  WARNING:    TunnelTree() will not work if you use a special
 *              folderlocation
 *
 ****************************************************************************/
void CShellTree::
PopulateTree (int nFolder)
{

  LPSHELLFOLDER lpsf = NULL, lpsf2 = NULL;
  LPITEMIDLIST lpi = NULL;
  HRESULT hr;
  TV_SORTCB tvscb;

  // Get a pointer to the desktop folder.
  hr = SHGetDesktopFolder (&lpsf);

  if (SUCCEEDED (hr))
    {
      // Initialize the tree view to be empty.
      DeleteAllItems ();

      if (!SUCCEEDED (SHGetSpecialFolderLocation (
                          m_hWnd, nFolder, &lpi)))
        {
          lpi = NULL;
          FillTreeView (lpsf, NULL, TVI_ROOT);
        }
      else
        {
          hr = lpsf->BindToObject (lpi,
                                   0, IID_IShellFolder, (LPVOID *) & lpsf2);

          if (SUCCEEDED (hr))
            {
              // Fill in the tree view from the root.
              FillTreeView (lpsf2, lpi, TVI_ROOT);
              lpsf2->Release ();
            }
          else
            FillTreeView (lpsf, NULL, TVI_ROOT);
        }

      // Release the folder pointer.
      lpsf->Release ();
    }
  tvscb.hParent = TVI_ROOT;
  tvscb.lParam = 0;
  tvscb.lpfnCompare = TreeViewCompareProc;

  // Sort the items in the tree view
  SortChildrenCB (&tvscb /*, FALSE */ );

  HTREEITEM hItem;
  hItem = GetRootItem ();
  Expand (hItem, TVE_EXPAND);
  Select (GetRootItem (), TVGN_CARET);
}

/****************************************************************************
 *
 *  FUNCTION: FillTreeView( LPSHELLFOLDER lpsf,
 *                          LPITEMIDLIST  lpifq,
 *                          HTREEITEM     hParent)
 *
 *  PURPOSE: Fills a branch of the TreeView control.  Given the
 *           shell folder, enumerate the subitems of this folder,
 *           and add the appropriate items to the tree.
 *
 *  PARAMETERS:
 *    lpsf         - Pointer to shell folder that we want to enumerate items
 *    lpifq        - Fully qualified item id list to the item that we are enumerating
 *                   items for.  In other words, this is the PIDL to the item
 *                   identified by the lpsf parameter.
 *    hParent      - Parent node
 *
 *  COMMENTS:
 *    This function enumerates the items in the folder identifed by lpsf.
 *    Note that since we are filling the left hand pane, we will only add
 *    items that are folders and/or have sub-folders.  We *could* put all
 *    items in here if we wanted, but that's not the intent.
 *
 ****************************************************************************/
void CShellTree::
FillTreeView (LPSHELLFOLDER lpsf, LPITEMIDLIST lpifq, HTREEITEM hParent)
{
  TV_ITEM tvi;                  // TreeView Item.

  TV_INSERTSTRUCT tvins;        // TreeView Insert Struct.

  HTREEITEM hPrev = NULL;       // Previous Item Added.

  LPSHELLFOLDER lpsf2 = NULL;
  LPENUMIDLIST lpe = NULL;
  LPITEMIDLIST lpi = NULL, lpiTemp = NULL, lpifqThisItem = NULL;
  LPTVITEMDATA lptvid = NULL;
  LPMALLOC lpMalloc = NULL;
  ULONG ulFetched;
  UINT uCount = 0;
  HRESULT hr;
  TCHAR szBuff[256];
  HWND hwnd =::GetParent (m_hWnd);

  // Allocate a shell memory object.
  hr =::SHGetMalloc (&lpMalloc);
  if (FAILED (hr))
    return;

  if (SUCCEEDED (hr))
    {
      // Get the IEnumIDList object for the given folder.
      hr = lpsf->EnumObjects (hwnd, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &lpe);

      if (SUCCEEDED (hr))
        {
          // Enumerate throught the list of folder and non-folder objects.
          while (S_OK == lpe->Next (1, &lpi, &ulFetched))
            {
              uCount++;
              //Create a fully qualified path to the current item
              //The SH* shell api's take a fully qualified path pidl,
              //(see GetIcon above where I call SHGetFileInfo) whereas the
              //interface methods take a relative path pidl.
              ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER;

              // Determine what type of object we have.
              lpsf->GetAttributesOf (1, (const struct _ITEMIDLIST **) &lpi, &ulAttrs);

              //:original                if(ulAttrs & (SFGAO_HASSUBFOLDER | SFGAO_FOLDER))
              if (m_flags & SHLT_FOLDERS && ulAttrs & SFGAO_FOLDER ||
                    m_flags & SHLT_FILES && !(ulAttrs & (SFGAO_FOLDER | SFGAO_LINK)) ||
                    m_flags & SHLT_LINKS && ulAttrs & SFGAO_LINK)
                {
                  //We need this next if statement so that we don't add things like
                  //the MSN to our tree.  MSN is not a folder, but according to the
                  //shell it has subfolders.
                  //:original                   if(ulAttrs & SFGAO_FOLDER)
                  {
                    tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;

                    //:original                      if(ulAttrs & SFGAO_HASSUBFOLDER)
                    if (ulAttrs & (SFGAO_FOLDER | SFGAO_HASSUBFOLDER))
                      {
                        //This item has sub-folders, so let's put the + in the TreeView.
                        //The first time the user clicks on the item, we'll populate the
                        //sub-folders.
                        tvi.cChildren = 1;
                        tvi.mask |= TVIF_CHILDREN;
                      }

                    //Now get the friendly name that we'll put in the treeview.
                    if (!GetName (lpsf, lpi, SHGDN_NORMAL, szBuff))
                      goto Done;    // Error - could not get friendly name.

                    if (!(ulAttrs & (SFGAO_FOLDER | SFGAO_LINK)))
                      {
                        POSITION pos = m_patterns.GetHeadPosition ();

                        if (pos)
                          {
                            CString pattern;

                            do
                              {
                                pattern = m_patterns.GetNext (pos);
                                if (fpattern_matchn (pattern, szBuff))
                                  goto found;
                              }
                            while (pos);
                            goto next;
found:
                            ;
                          }
                      }

                    //OK, let's get some memory for our ITEMDATA struct
                    lptvid = (LPTVITEMDATA) lpMalloc->Alloc (sizeof (TVITEMDATA));
                    if (!lptvid)
                      goto Done;    // Error - could not allocate memory.

                    tvi.pszText = szBuff;
                    tvi.cchTextMax = MAX_PATH;

                    lpifqThisItem = ConcatPidls (lpifq, lpi);

                    //Now, make a copy of the ITEMIDLIST
                    lptvid->lpi = CopyITEMID (lpMalloc, lpi);

                    GetNormalAndSelectedIcons (lpifqThisItem, &tvi);

                    lptvid->lpsfParent = lpsf;  //Store the parent folders SF

                    lpsf->AddRef ();

                    lptvid->lpifq = ConcatPidls (lpifq, lpi);

                    tvi.lParam = (LPARAM) lptvid;

                    // Populate the TreeVeiw Insert Struct
                    // The item is the one filled above.
                    // Insert it after the last item inserted at this level.
                    // And indicate this is a root entry.
                    tvins.item = tvi;
                    tvins.hInsertAfter = hPrev;
                    tvins.hParent = hParent;

                    // Add the item to the tree
                    hPrev = InsertItem (&tvins);
                  }
                  // Free this items task allocator.
                  lpMalloc->Free (lpifqThisItem);
                  lpifqThisItem = 0;
                }
next:
              lpMalloc->Free (lpi);     //Free the pidl that the shell gave us.

              lpi = 0;
            }
          if (!uCount)
            {
              tvi.hItem = hParent;
              tvi.cChildren = 0;
              tvi.mask = TVIF_HANDLE | TVIF_CHILDREN;
              SetItem (&tvi);
            }
        }

    }
  else
    return;

Done:

  if (lpe)
    lpe->Release ();

  //The following 2 if statements will only be TRUE if we got here on an
  //error condition from the "goto" statement.  Otherwise, we free this memory
  //at the end of the while loop above.
  if (lpi && lpMalloc)
    lpMalloc->Free (lpi);
  if (lpifqThisItem && lpMalloc)
    lpMalloc->Free (lpifqThisItem);

  if (lpMalloc)
    lpMalloc->Release ();
}


/****************************************************************************
 *
 *    FUNCTION: GetNormalAndSelectedIcons(LPITEMIDLIST lpifq, LPTV_ITEM lptvitem)
 *
 *    PURPOSE:  Gets the index for the normal and selected icons for the current item.
 *
 *    PARAMETERS:
 *    lpifq    - Fully qualified item id list for current item.
 *    lptvitem - Pointer to treeview item we are about to add to the tree.
 *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -