📄 explorertreeview.cpp
字号:
// ExplorerTreeView.cpp : implementation file
//
#include "stdafx.h"
#include "CMyExplorer.h"
#include "ExplorerTreeView.h"
#include "ExplorerListView.h"
#include "ShellContextMenu.h"
#include "ShellFileOp.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CExplorerTreeView * g_TreeView = NULL;
extern CExplorerListView * g_ListView;
/////////////////////////////////////////////////////////////////////////////
// CExplorerTreeView
IMPLEMENT_DYNCREATE(CExplorerTreeView, CTreeView)
CExplorerTreeView::CExplorerTreeView()
{
g_TreeView = this;
m_pTreeCtrl = &GetTreeCtrl();
m_psfDesk = NULL;
m_pidlDesk = NULL;
m_pidlMyComputer = NULL;
m_hDesktop = NULL;
m_hMyComputer = NULL;
m_hSelItem = NULL;
m_hMoveSrc = NULL;
m_pSelLiParam = NULL;
}
CExplorerTreeView::~CExplorerTreeView()
{
// m_pTreeCtrl->SetImageList(NULL,TVSIL_NORMAL);
}
BEGIN_MESSAGE_MAP(CExplorerTreeView, CTreeView)
//{{AFX_MSG_MAP(CExplorerTreeView)
ON_WM_CREATE()
ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding)
ON_NOTIFY_REFLECT(TVN_SELCHANGING, OnSelchanging)
ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBegindrag)
ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)
//}}AFX_MSG_MAP
ON_MESSAGE(WM_REFRESHFILES,OnRefreshTree)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CExplorerTreeView drawing
void CExplorerTreeView::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
// TODO: add draw code here
}
/////////////////////////////////////////////////////////////////////////////
// CExplorerTreeView diagnostics
#ifdef _DEBUG
void CExplorerTreeView::AssertValid() const
{
CTreeView::AssertValid();
}
void CExplorerTreeView::Dump(CDumpContext& dc) const
{
CTreeView::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CExplorerTreeView message handlers
int CExplorerTreeView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CTreeView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
m_pTreeCtrl->ModifyStyle(0,TVS_HASBUTTONS|TVS_SHOWSELALWAYS);
InitExplorerTree();
InitImageList();
int i = m_TreeTarget.Register(this);
return 0;
}
void CExplorerTreeView::OnRclick(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
CPoint pt;
GetCursorPos(&pt);
m_pTreeCtrl->ScreenToClient(&pt);
HTREEITEM hItem = m_pTreeCtrl->HitTest(pt,NULL);
if ( hItem==NULL )
return;
LPTREEPARAM ptrParam = (LPTREEPARAM)m_pTreeCtrl->GetItemData(hItem);
CShellContextMenu scm;
scm.SetObjects(ptrParam->lpidl);
m_pTreeCtrl->ClientToScreen(&pt);
UINT idCommand = scm.ShowContextMenu(this, pt);
switch( idCommand )
{
case 18: //chose delete
{
HTREEITEM hParentItem = m_pTreeCtrl->GetParentItem(hItem);
SendMessage(WM_REFRESHFILES,(WPARAM)hParentItem,0);
g_ListView->SendMessage(WM_REFRESHFILES,0,0);
break;
}
case 27: //chose paste
{
SendMessage(WM_REFRESHFILES,(WPARAM)hItem,0);
g_ListView->SendMessage(WM_REFRESHFILES,0,0);
break;
}
}
*pResult = 0;
}
void CExplorerTreeView::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
TV_ITEM tvItem = pNMTreeView->itemNew;
if ( pNMTreeView->action==2 ) //展开
{
SendMessage(WM_REFRESHFILES,(WPARAM)tvItem.hItem,0);
SetSubItemFolder(tvItem);
}
*pResult = 0;
}
void CExplorerTreeView::OnSelchanging(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
TV_ITEM tvItem = pNMTreeView->itemNew;
m_hSelItem = tvItem.hItem;
LPTREEPARAM pliParam = (LPTREEPARAM)tvItem.lParam;
if ( g_ListView )
{
g_ListView->SetListContext(pliParam->lpsf,pliParam->lpidl);
}
*pResult = 0;
}
void CExplorerTreeView::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
TV_ITEM tvItem = pNMTreeView->itemNew;
HTREEITEM hItem = tvItem.hItem;
m_hMoveSrc = m_pTreeCtrl->GetParentItem(hItem);
HTREEITEM hSel = m_pTreeCtrl->GetSelectedItem();
LPTREEPARAM ptrItem = (LPTREEPARAM)tvItem.lParam;
char * szSrc = new char[MAX_PATH];
ZeroMemory(szSrc,MAX_PATH);
SHGetPathFromIDList(ptrItem->lpidl,szSrc);
//创建拖拽数据源
int hgblSize = sizeof(DROPFILES) + ( strlen(szSrc)+2 )* sizeof(_TCHAR);
HGLOBAL hgblData = ::GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE,hgblSize);
if (hgblData == NULL)
return;
LPDROPFILES pDropFiles = (LPDROPFILES)GlobalLock(hgblData);
pDropFiles->pFiles = sizeof(DROPFILES);
pDropFiles->fWide = FALSE;
LPSTR pGlobalString = (LPSTR)(pDropFiles) + sizeof(DROPFILES);
strcpy((char*)(pGlobalString), szSrc);
pGlobalString += ( strlen(szSrc)+1 ) * sizeof(_TCHAR);
pGlobalString[0] = _T('\0');
GlobalUnlock(hgblData);
delete szSrc;
COleDataSource *poleSourceObj = new COleDataSource;
poleSourceObj->CacheGlobalData(CF_HDROP,hgblData);
DROPEFFECT dropeffect = poleSourceObj->DoDragDrop();
*pResult = 0;
}
HTREEITEM CExplorerTreeView::FindSubItemByPath(HTREEITEM hParent, LPSTR szPathName)
{
HTREEITEM hNextItem,hChildItem = m_pTreeCtrl->GetChildItem(hParent);
char * szPath = new char[MAX_PATH];
while( hChildItem )
{
ZeroMemory(szPath,MAX_PATH);
LPTREEPARAM ptrParam = (LPTREEPARAM)m_pTreeCtrl->GetItemData(hChildItem);
SHGetPathFromIDList(ptrParam->lpidl,szPath);
if ( strcmp(szPathName,szPath)==0 )
{
delete szPath;
return hChildItem;
}
hNextItem = m_pTreeCtrl->GetNextItem(hChildItem, TVGN_NEXT);
hChildItem = hNextItem;
}
delete szPath;
return NULL;
}
long CExplorerTreeView::OnRefreshTree(WPARAM wParam, LPARAM lParam)
{
HTREEITEM hRefresh;
if ( wParam==0 )
hRefresh = m_hSelItem;
else
hRefresh = (HTREEITEM)wParam;
if ( hRefresh==m_hDesktop )
return 0;
//删除多余项
char * szPathName = new char[MAX_PATH];
HTREEITEM hNextItem,hChildItem = m_pTreeCtrl->GetChildItem(hRefresh);
while( hChildItem )
{
ZeroMemory(szPathName,MAX_PATH);
LPTREEPARAM ptrParam = (LPTREEPARAM)m_pTreeCtrl->GetItemData(hChildItem);
SHGetPathFromIDList(ptrParam->lpidl,szPathName);
//路径不为空、且不存在时才能删除
//系统的文件夹路径为空,不能删
if ( strlen(szPathName)!=0 && GetFileAttributes(szPathName)==INVALID_FILE_ATTRIBUTES )
{
hNextItem = m_pTreeCtrl->GetNextItem(hChildItem, TVGN_NEXT);
if ( hChildItem==m_hSelItem )
m_pTreeCtrl->SelectItem(hRefresh);
LPTREEPARAM ptrParam = (LPTREEPARAM)m_pTreeCtrl->GetItemData(hChildItem);
m_pMalloc->Free(ptrParam);
m_pTreeCtrl->DeleteItem(hChildItem);
}
else
{
hNextItem = m_pTreeCtrl->GetNextItem(hChildItem, TVGN_NEXT);
}
hChildItem = hNextItem;
}
delete szPathName;
//添加新项
IEnumIDList * peidl;
LPITEMIDLIST pidl, pidlAbs;
IShellFolder * psf = NULL;
LPTREEPARAM ptrParent = (LPTREEPARAM)m_pTreeCtrl->GetItemData(hRefresh);
IShellFolder * psfParent = ptrParent->lpsf;
LPITEMIDLIST pidlParent = ptrParent->lpidl;
HRESULT hr = psfParent->EnumObjects(NULL,SHCONTF_FOLDERS,&peidl);
if ( NOERROR!=hr )
return 0;
while (NOERROR == hr)
{
hr = peidl->Next(1, &pidl, NULL);
if (hr == S_FALSE || pidl == NULL)
break;
pidlAbs = ConcatPidl(pidlParent,pidl);
hr = psfParent->BindToObject(pidl, NULL, IID_IShellFolder, (void**)&psf);
if (hr == S_FALSE || psf == NULL)
break;
char * szPathName = new char[MAX_PATH];
ZeroMemory(szPathName,MAX_PATH);
SHGetPathFromIDList(pidlAbs,szPathName);
if ( FindSubItemByPath(hRefresh,szPathName)==NULL )
{
SHFILEINFO sfi;
SHGetFileInfo((LPCTSTR)pidlAbs,
0,
&sfi,
sizeof(SHFILEINFO),
SHGFI_PIDL|SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_DISPLAYNAME);
TV_INSERTSTRUCT TCItem;
TCItem.hParent = hRefresh;
if ( hRefresh==m_hMyComputer )
TCItem.hInsertAfter = TVI_LAST;
else
TCItem.hInsertAfter = TVI_SORT;
TCItem.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
TCItem.item.pszText = sfi.szDisplayName;
TCItem.item.iImage = sfi.iIcon;
TCItem.item.iSelectedImage = sfi.iIcon;
LPTREEPARAM ptrItem = (LPTREEPARAM)m_pMalloc->Alloc(sizeof(TREEPARAM));
ptrItem->lpsf = psf;
ptrItem->lpidl = pidlAbs;
ptrItem->uParam = 1;
TCItem.item.lParam = (LPARAM)ptrItem;
HTREEITEM hCur = m_pTreeCtrl->InsertItem(&TCItem);
AddChildren(psf,pidlAbs, hCur, false);
}
delete szPathName;
}
peidl->Release();
return 0;
}
BOOL CExplorerTreeView::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if ( pMsg->message==WM_KEYDOWN )
{
switch ( pMsg->wParam )
{
case 0x2e: //DEL
{
CShellFileOp op;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -