📄 shelltreectrl.cpp
字号:
// ShellTreeCtrl.cpp : implementation file
//
#include "stdafx.h"
#include "GreenBrowser.h"
#include "ShellTreeCtrl.h"
#include "MainFrm.h"
#include "setscdlg.h"
#include "inputalias.h"
#include "ShellTree.h"
#include "ShellTreeCtrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//#pragma optimize( "s", on )
/////////////////////////////////////////////////////////////////////////////
// CShellTreeCtrl
CShellTreeCtrl::CShellTreeCtrl()
{
m_bDispFile = TRUE;
m_strFilter = AfxGetApp()->GetProfileString("Settings", "FileTypes", "*.htm;*.html;*.shtm;*.shtml;*.mht;*.txt;");
if(m_strFilter.Right(1) != ";")
m_strFilter += ";";
}
CShellTreeCtrl::~CShellTreeCtrl()
{
try{
AfxGetApp()->WriteProfileString("Settings", "FileTypes", m_strFilter);
}catch(...){}
}
BEGIN_MESSAGE_MAP(CShellTreeCtrl, CTreeCtrl)
//{{AFX_MSG_MAP(CShellTreeCtrl)
ON_NOTIFY_REFLECT(NM_RCLICK, GetContextMenu)
ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnFolderExpanding)
ON_NOTIFY_REFLECT(TVN_DELETEITEM, OnDeleteShellItem)
ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CShellTreeCtrl message handlers
/****************************************************************************
*
* FUNCTION: PopulateTree()
*
* PURPOSE: Processes the File.Fill/RefreshTree command
*
****************************************************************************/
void CShellTreeCtrl::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: 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 CShellTreeCtrl::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;
char szBuff[256];
char szFileName[2048];
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 | SHCONTF_INCLUDEHIDDEN , &lpe);
if (SUCCEEDED(hr))
{
// Enumerate throught the list of folder and non-folder objects.
while (S_OK==lpe->Next(1, &lpi, &ulFetched))
{
//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);
if (m_bDispFile || (ulAttrs & (SFGAO_HASSUBFOLDER | SFGAO_FOLDER)))
{
//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.
if (m_bDispFile || (ulAttrs & SFGAO_FOLDER ))
{
tvi.mask= TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
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;
}
//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.
//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 (!GetName(lpsf, lpi, SHGDN_FORPARSING, szFileName))
if(SHGetPathFromIDList(lpi,szFileName))
{
if(!(ulAttrs & SFGAO_FOLDER) && m_bDispFile)
if(!MatchExtensionFilter(szFileName))
continue;
}
else
if(!(ulAttrs & SFGAO_FOLDER) && m_bDispFile)
if(!MatchExtensionFilter(szBuff))
continue;
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;
}
lpMalloc->Free(lpi); //Free the pidl that the shell gave us.
lpi=0;
}
}
}
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.
*
****************************************************************************/
void CShellTreeCtrl::GetNormalAndSelectedIcons(LPITEMIDLIST lpifq,
LPTV_ITEM lptvitem)
{
//Note that we don't check the return value here because if GetIcon()
//fails, then we're in big trouble...
lptvitem->iImage = GetItemIcon(lpifq, SHGFI_PIDL |
SHGFI_SYSICONINDEX |
SHGFI_SMALLICON);
lptvitem->iSelectedImage = GetItemIcon(lpifq, SHGFI_PIDL |
SHGFI_SYSICONINDEX |
SHGFI_SMALLICON |
SHGFI_OPENICON);
return;
}
/****************************************************************************
*
* FUNCTION: TreeViewCompareProc(LPARAM, LPARAM, LPARAM)
*
* PURPOSE: Callback routine for sorting the tree
*
****************************************************************************/
int CALLBACK CShellTreeCtrl::TreeViewCompareProc(LPARAM lparam1,
LPARAM lparam2, LPARAM lparamSort)
{
LPTVITEMDATA lptvid1=(LPTVITEMDATA)lparam1;
LPTVITEMDATA lptvid2=(LPTVITEMDATA)lparam2;
HRESULT hr;
hr = lptvid1->lpsfParent->CompareIDs(0,lptvid1->lpi,lptvid2->lpi);
if (FAILED(hr))
return 0;
return (short)SCODE_CODE(GetScode(hr));
}
/////////////////////////////////////////////////////////////////////////////
// CShellTreeCtrl message handlers
/****************************************************************************
*
* FUNCTION: OnFolderExpanding(NMHDR* pNMHDR, LRESULT* pResult)
*
* PURPOSE: Reponds to an TVN_ITEMEXPANDING message in order to fill up
* subdirectories. Pass the parameters from OnItemExpanding() to
* this function. You need to do that or your folders won't
* expand.
*
* OTHER: It can also be used to update a corresponding listview. Seem MFCENUM
*
* MESSAGEMAP: TVN_ITEMEXPANDING
*
****************************************************************************/
void CShellTreeCtrl::OnFolderExpanding(NMHDR* pNMHDR, LRESULT* pResult)
{
LPTVITEMDATA lptvid; //Long pointer to TreeView item data
HRESULT hr;
LPSHELLFOLDER lpsf2=NULL;
static char szBuff[MAX_PATH];
TV_SORTCB tvscb;
NM_TREEVIEW* pnmtv = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
if ((pnmtv->itemNew.state & TVIS_EXPANDEDONCE))
{
return;
}
lptvid=(LPTVITEMDATA)pnmtv->itemNew.lParam;
if (lptvid)
{
hr=lptvid->lpsfParent->BindToObject(lptvid->lpi,
0, IID_IShellFolder,(LPVOID *)&lpsf2);
if (SUCCEEDED(hr))
{
FillTreeView(lpsf2,
lptvid->lpifq,
pnmtv->itemNew.hItem);
}
tvscb.hParent = pnmtv->itemNew.hItem;
tvscb.lParam = 0;
tvscb.lpfnCompare = TreeViewCompareProc;
SortChildrenCB(&tvscb /*, FALSE*/);
}
*pResult = 0;
}
/****************************************************************************
*
* FUNCTION: GetContextMenu(NMHDR* pNMHDR, LRESULT* pResult)
*
* PURPOSE: Diplays a popup menu for the folder selected. Pass the
* parameters from Rclick() to this function.
*
* MESSAGEMAP: NM_RCLICK;
*
****************************************************************************/
void CShellTreeCtrl::GetContextMenu(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
POINT pt;
LPTVITEMDATA lptvid; //Long pointer to TreeView item data
LPSHELLFOLDER lpsf2=NULL;
static char szBuff[MAX_PATH];
TV_HITTESTINFO tvhti;
TV_ITEM tvi;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -