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

📄 bentreectrl.cpp

📁 一个多窗口的浏览器的程序benbrowse
💻 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 + -