📄 bentreectrl.cpp
字号:
// BenTreeCtrl.cpp : implementation file
//
#include "stdafx.h"
#include "..\benbenBrowser.h"
#include "BenTreeCtrl.h"
#include <intshcut.h>
#include <Wininet.h>
#include "..\MainFrm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include <Shlwapi.h>
#include <atlbase.h>
#include <wininet.h>
/////////////////////////////////////////////////////////////////////////////
// CBenTreeCtrl
CBenTreeCtrl::CBenTreeCtrl()
{
m_pMalloc=NULL;
SHGetMalloc(&m_pMalloc);
}
CBenTreeCtrl::~CBenTreeCtrl()
{
if (m_pMalloc)
m_pMalloc->Release();
m_historylist.RemoveAll();
}
BEGIN_MESSAGE_MAP(CBenTreeCtrl, CTreeCtrl)
//{{AFX_MSG_MAP(CBenTreeCtrl)
ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding)
ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged)
ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBenTreeCtrl message handlers
// helper struct that holds tree item data
void CBenTreeCtrl::FillTreeView(LPSHELLFOLDER lpsf, LPITEMIDLIST lpifq, HTREEITEM hParent)
{
TV_ITEM tvi; // tree view item
TV_INSERTSTRUCT tvins; // tree view insert structure
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];
HWND hwnd = ::GetParent (this->m_hWnd);
LPTSTR lpszURL = NULL;
// Allocate a shell memory object.
hr = ::SHGetMalloc (&lpMalloc);
if (FAILED (hr))
return;
try
{
if (SUCCEEDED (hr))
{
// Get the IEnumIDList object for the given folder.
//now get all the file (maybe the internet shorts) in this folder
hr = lpsf->EnumObjects (hwnd, SHCONTF_NONFOLDERS|SHCONTF_INCLUDEHIDDEN ,&lpe);
if (SUCCEEDED (hr))
{
// Enumerate through the list of folder and nonfolder objects.
while (S_OK == lpe->Next (1, &lpi, &ulFetched))
{
tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
GetShortcutTarget(lpsf,lpi, &lpszURL);
m_historylist.AddTail(lpszURL);
// Get some memory for the ITEMDATA structure.
lptvid = (LPTVITEMDATA) lpMalloc->Alloc (
sizeof (TVITEMDATA));
if (! lptvid)
goto Done; // Error - could not allocate memory
// Now get the friendly name to put in the tree view control.
if (! GetName (lpsf, lpi, SHGDN_NORMAL, szBuff))
goto Done; // Error - could not get friendly name
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);
// Add the item to the tree.
hPrev = InsertItem (szBuff,tvi.iImage,tvi.iSelectedImage,hParent,TVI_SORT);
SetItemData(hPrev,m_historylist.GetCount());
//to know is the url cached?
DWORD dwEntrySize = 0;
if((strncmp(lpszURL, "file:", 5) != 0))
{
if (!GetUrlCacheEntryInfoEx(lpszURL,NULL,&dwEntrySize, NULL, NULL, NULL, 0))
{
if (GetLastError()==ERROR_FILE_NOT_FOUND)
{
SetItemState(hPrev, TVIS_CUT, TVIS_CUT);
}
}
}
lpszURL=NULL;
}
}
//now get all the folders in this floder
hr = lpsf->EnumObjects (hwnd, SHCONTF_FOLDERS |SHCONTF_INCLUDEHIDDEN ,
&lpe);
if (SUCCEEDED (hr))
{
hPrev=TVI_FIRST;
// Enumerate through the list of folder and nonfolder objects.
while (S_OK == lpe->Next (1, &lpi, &ulFetched))
{
// Determine what type of object you have.
tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE |
TVIF_PARAM;
tvi.cChildren = 1;
tvi.mask |= TVIF_CHILDREN;
// Get some memory for the ITEMDATA structure.
lptvid = (LPTVITEMDATA) lpMalloc->Alloc (
sizeof (TVITEMDATA));
if (! lptvid)
goto Done; // Error - could not allocate memory
// Now get the friendly name to
// put in the tree view control.
if (! GetName (lpsf, lpi, SHGDN_NORMAL, szBuff))
goto Done; // Error - could not get friendly name
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; // pointer to parent folder
lpsf->AddRef ();
lptvid->lpifq = ConcatPidls (lpifq, lpi);
tvi.lParam = (LPARAM)lptvid;
// Populate the tree view insert structure.
// The item is the one filled above.
// Insert it after the last item inserted at this level,
// and indicate that this is a root entry.
tvins.item = tvi;
tvins.hInsertAfter = hPrev;
tvins.hParent = hParent;
// Add the item to the tree.
hPrev = InsertItem (&tvins);
}
// Free the task allocator for this item.
lpMalloc->Free (lpifqThisItem);
lpifqThisItem = 0;
lpi = 0;
}
}
else
return;
Done:
if (lpe)
lpe->Release ();
// The following two if statements will be TRUE only if you got here
// on an error condition from the goto statement. Otherwise, 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 ();
}
catch(...)
{
if (lpi && lpMalloc)
lpMalloc->Free (lpi);
if (lpifqThisItem && lpMalloc)
lpMalloc->Free (lpifqThisItem);
if (lpMalloc)
lpMalloc->Release ();
}
}
BOOL CBenTreeCtrl::GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST lpi, DWORD dwFlags, LPSTR lpFriendlyName)
{
BOOL bSuccess=TRUE;
STRRET str;
if (NOERROR==lpsf->GetDisplayNameOf(lpi,dwFlags, &str))
{
switch (str.uType)
{
case STRRET_WSTR:
WideCharToMultiByte(CP_ACP, // CodePage
0, // dwFlags
str.pOleStr, // lpWideCharStr
-1, // cchWideChar
lpFriendlyName, // lpMultiByteStr
MAX_PATH,
//sizeof(lpFriendlyName), // cchMultiByte, wrong. sizeof on a pointer, psk, psk
NULL, // lpDefaultChar,
NULL); // lpUsedDefaultChar
break;
case STRRET_OFFSET:
_tcscpy(lpFriendlyName, (LPSTR)lpi+str.uOffset);
break;
case STRRET_CSTR:
_tcscpy(lpFriendlyName, (LPSTR)str.cStr);
break;
default:
bSuccess = FALSE;
break;
}
}
else
bSuccess = FALSE;
return bSuccess;
}
LPITEMIDLIST CBenTreeCtrl::ConcatPidls(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
{
LPITEMIDLIST pidlNew;
UINT cb1;
UINT cb2;
if (pidl1) //May be NULL
cb1 = GetSize(pidl1) - sizeof(pidl1->mkid.cb);
else
cb1 = 0;
cb2 = GetSize(pidl2);
pidlNew = CreateS(cb1 + cb2);
if (pidlNew)
{
if (pidl1)
memcpy(pidlNew, pidl1, cb1);
memcpy(((LPSTR)pidlNew) + cb1, pidl2, cb2);
}
return pidlNew;
}
UINT CBenTreeCtrl::GetSize(LPCITEMIDLIST pidl)
{
UINT cbTotal = 0;
if (pidl)
{
cbTotal += sizeof(pidl->mkid.cb); // Null terminator
while (pidl->mkid.cb)
{
cbTotal += pidl->mkid.cb;
pidl = Next(pidl);
}
}
return cbTotal;
}
LPITEMIDLIST CBenTreeCtrl::CopyITEMID(LPMALLOC lpMalloc, LPITEMIDLIST lpi)
{
LPITEMIDLIST lpiTemp;
lpiTemp=(LPITEMIDLIST)lpMalloc->Alloc(lpi->mkid.cb+sizeof(lpi->mkid.cb));
CopyMemory((PVOID)lpiTemp, (CONST VOID *)lpi, lpi->mkid.cb+sizeof(lpi->mkid.cb));
return lpiTemp;
}
void CBenTreeCtrl::GetNormalAndSelectedIcons(LPITEMIDLIST lpifq, LPTV_ITEM lptvitem)
{
lptvitem->iImage = GetIcon(lpifq, SHGFI_PIDL |
SHGFI_SYSICONINDEX |
SHGFI_SMALLICON);
lptvitem->iSelectedImage = GetIcon(lpifq, SHGFI_PIDL |
SHGFI_SYSICONINDEX |
SHGFI_SMALLICON |
SHGFI_OPENICON);
return;
}
int CBenTreeCtrl::GetIcon(LPITEMIDLIST lpi, UINT uFlags)
{
try
{
SHFILEINFO sfi;
ZeroMemory(&sfi,sizeof(sfi));
if (uFlags == 0)
uFlags |= (SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
uFlags |= SHGFI_PIDL;
LPCSTR lpiA=(LPCSTR)lpi;
SHGetFileInfo((LPCSTR)lpi,0,&sfi,sizeof(SHFILEINFO), uFlags);
return sfi.iIcon;
}
catch(...)
{
}
return 0;
}
LPITEMIDLIST CBenTreeCtrl::CreateS(UINT cbSize)
{
//HRESULT hrr = SHGetMalloc(&m_pMalloc);
//if (FAILED(hrr))
// return 0;
try
{
LPMALLOC lpMalloc;
HRESULT hr;
LPITEMIDLIST pidl=NULL;
hr=SHGetMalloc(&lpMalloc);
if (FAILED(hr))
return 0;
pidl=(LPITEMIDLIST)lpMalloc->Alloc(cbSize);
if (pidl)
memset(pidl, 0, cbSize); // zero-init for external task alloc
if (lpMalloc) lpMalloc->Release();
return pidl;
}
catch(...)
{
}
return NULL;
}
LPITEMIDLIST CBenTreeCtrl::Next(LPCITEMIDLIST pidl)
{
LPSTR lpMem=(LPSTR)pidl;
lpMem+=pidl->mkid.cb;
return (LPITEMIDLIST)lpMem;
}
void CBenTreeCtrl::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
*pResult = 0;
try
{
HTREEITEM item= GetSelectedItem( );
if(!GetChildItem(item)&&ItemHasChildren(item))
{
LPTVITEMDATA lptvid; //Long pointer to TreeView item data
HRESULT hr;
LPSHELLFOLDER lpsf2=NULL;
static char szBuff[MAX_PATH];
TV_SORTCB tvscb;
if ((pNMTreeView->itemNew.state & TVIS_EXPANDEDONCE))
return;
SetRedraw(FALSE);
lptvid=(LPTVITEMDATA)pNMTreeView->itemNew.lParam;
if (lptvid)
{
hr=lptvid->lpsfParent->BindToObject(lptvid->lpi,
0, IID_IShellFolder,(LPVOID *)&lpsf2);
if (SUCCEEDED(hr))
{
FillTreeView(lpsf2,
lptvid->lpifq,
pNMTreeView->itemNew.hItem);
}
SortChildrenCB(&tvscb/*, FALSE*/);
}
SetRedraw();
}
}
catch(...)
{
}
}
bool CBenTreeCtrl::InitSystemImageLists()
{
try
{
SHFILEINFO sfi;
HIMAGELIST hImageList = (HIMAGELIST)::SHGetFileInfo( _T("C:\\"), 0, &sfi,
sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_SMALLICON );
if( hImageList ) {
SetImageList( CImageList::FromHandle( hImageList ), TVSIL_NORMAL );
return TRUE;
}
}
catch(...)
{
}
return FALSE;
}
void CBenTreeCtrl::PopulateTree2(LPCTSTR pszPath)
{
try
{
DeleteAllItems();
LPITEMIDLIST pidl=NULL;
LPSHELLFOLDER psfDesktop=NULL;
LPSHELLFOLDER pSubFolder=NULL;
HRESULT hr = SHGetDesktopFolder(&psfDesktop);
CString m_sRootPath;
{
if (pszPath && *pszPath != '\0')
{
hr = SHPathToPidlEx(pszPath,&pidl,psfDesktop);
if (SUCCEEDED(hr))
{
hr = psfDesktop->BindToObject(pidl, 0, IID_IShellFolder,(LPVOID*)&pSubFolder);
if (SUCCEEDED(hr))
m_sRootPath = pszPath;
}
}
else
{
hr = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP , &pidl);
}
}
LPCTSTR pszTitle=NULL;
SHFILEINFO fileInfo;
ZeroMemory(&fileInfo,sizeof(fileInfo));
int nImage=0, nSelImage=0;
if (pidl)
{
SHGetFileInfo((LPCTSTR)pidl, NULL, &fileInfo, sizeof(fileInfo), SHGFI_PIDL|SHGFI_ATTRIBUTES|SHGFI_DISPLAYNAME);
pszTitle = fileInfo.szDisplayName;
TV_ITEM ass;
GetNormalAndSelectedIcons(pidl,&ass);
if (nImage < 0)
nImage = 0;
if (nSelImage < 0)
nSelImage = 0;
}
if (SUCCEEDED(hr))
{
m_historylist.RemoveAll();
FillTreeView(pSubFolder,pidl,TVI_ROOT);
SetRedraw();
}
if (pSubFolder)
pSubFolder->Release();
if (psfDesktop)
psfDesktop->Release();
}
catch(...)
{
}
return ;
}
STDMETHODIMP CBenTreeCtrl::SHPathToPidlEx(LPCTSTR szPath, LPITEMIDLIST *ppidl, LPSHELLFOLDER pFolder)
{
try
{
OLECHAR wszPath[MAX_PATH] = {0};
ULONG nCharsParsed = 0;
LPSHELLFOLDER pShellFolder = NULL;
BOOL bFreeOnExit = FALSE;
#ifdef UNICODE
lstrcpy(wszPath,szPath);
#else
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, -1, wszPath, MAX_PATH);
#endif
// Use the desktop's IShellFolder by default
if(pFolder == NULL)
{
SHGetDesktopFolder(&pShellFolder);
bFreeOnExit = TRUE;
}
else
pShellFolder = pFolder;
HRESULT hr = pShellFolder->ParseDisplayName(NULL, NULL, wszPath, &nCharsParsed, ppidl, NULL);
if(bFreeOnExit)
pShellFolder->Release();
return hr;
}
catch(...)
{
}
return FALSE;
}
STDMETHODIMP CBenTreeCtrl::GetShortcutTarget(IShellFolder* pFolder, LPCITEMIDLIST pidl, LPTSTR* lpszURL)
{
IShellLink* pShellLink;
*lpszURL = NULL; // Assume failure
// Get a pointer to the IShellLink interface from the given folder
try
{
HRESULT hr = pFolder->GetUIObjectOf(NULL, 1, &pidl, IID_IShellLink, NULL, (LPVOID*)&pShellLink);
if (SUCCEEDED(hr))
{
WIN32_FIND_DATA wfd;
hr = pShellLink->Resolve(NULL, SLR_NO_UI);
if (NOERROR == hr)
{
// Get the path to the link target.
*lpszURL = (LPTSTR)m_pMalloc->Alloc(MAX_PATH); // Must remember to Free later
hr = pShellLink->GetPath(*lpszURL, MAX_PATH - 1, (WIN32_FIND_DATA*)&wfd, SLGP_UNCPRIORITY);
}
pShellLink->Release();
}
if(SUCCEEDED(hr))
return TRUE;
else
return FALSE;
}
catch(...)
{
}
return FALSE;
}
void CBenTreeCtrl::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
*pResult = 0;
}
void CBenTreeCtrl::OnClick(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
*pResult = 0;
try
{
HTREEITEM item;
CPoint pt;
GetCursorPos(&pt);
ScreenToClient(&pt);
item = HitTest(pt);
if(!item)
return;
int data=GetItemData(item);
if(data>0&&!ItemHasChildren(item))
{
if(data<=m_historylist.GetCount())
{
short ctrl_key=GetKeyState(VK_CONTROL);
int type=1;
if(ctrl_key&128)
type=0;
CString URL=m_historylist.GetAt(m_historylist.FindIndex(data-1));
CMainFrame *pfame=(CMainFrame *)AfxGetApp()->m_pMainWnd;
pfame->NavigateToUrl(URL,type);
}
}
}
catch(...)
{
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -