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

📄 explorerlistview.cpp

📁 类似资源管理器的vc源代码,实现起来相当不容易啊,要细心琢磨
💻 CPP
字号:
// ExplorerListView.cpp : implementation file
//

#include "stdafx.h"
#include "CMyExplorer.h"
#include "ExplorerListView.h"
#include "ShellContextMenu.h"
#include "ExplorerTreeView.h"
#include "ShellFileOp.h"

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


CExplorerListView * g_ListView = NULL;
extern CExplorerTreeView * g_TreeView;
/////////////////////////////////////////////////////////////////////////////
// CExplorerListView

IMPLEMENT_DYNCREATE(CExplorerListView, CListView)

CExplorerListView::CExplorerListView()
{
	m_pListCtrl = &GetListCtrl();

	m_dViewType = LVS_LIST;

	g_ListView = this;
}

CExplorerListView::~CExplorerListView()
{
//	m_pListCtrl->SetImageList(NULL,LVSIL_SMALL);
//	m_pListCtrl->SetImageList(NULL,LVSIL_NORMAL);
}


BEGIN_MESSAGE_MAP(CExplorerListView, CListView)
	//{{AFX_MSG_MAP(CExplorerListView)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)
	ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk)
	ON_NOTIFY_REFLECT(LVN_BEGINDRAG, OnBegindrag)
	ON_WM_MENUSELECT()
	ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndlabeledit)
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_REFRESHFILES,OnRefreshList)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CExplorerListView drawing

void CExplorerListView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	// TODO: add draw code here
	
}

/////////////////////////////////////////////////////////////////////////////
// CExplorerListView diagnostics

#ifdef _DEBUG
void CExplorerListView::AssertValid() const
{
	CListView::AssertValid();
}

void CExplorerListView::Dump(CDumpContext& dc) const
{
	CListView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CExplorerListView message handlers

int CExplorerListView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CListView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	//修改属性
	ModifyStyle(0,LVS_EDITLABELS|LVS_SHOWSELALWAYS|LVS_AUTOARRANGE);

	//设置菜单
	SetListViewType(LVS_ICON);

	//注册拖拽
	m_ListTarget.Register(this);

	//初始化系统图标列表
	InitImageList();

	if ( g_TreeView )
	{
		HTREEITEM hSelect = g_TreeView->m_pTreeCtrl->GetSelectedItem();
		LPTREEPARAM ptrItem = (LPTREEPARAM)g_TreeView->m_pTreeCtrl->GetItemData(hSelect);
		SetListContext(ptrItem->lpsf,ptrItem->lpidl);
	}

	
	return 0;
}

void CExplorerListView::OnDestroy() 
{
	CListView::OnDestroy();
	
	// TODO: Add your message handler code here
	
}

void CExplorerListView::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here
	NMITEMACTIVATE * nmia = (NMITEMACTIVATE*)pNMHDR;

	CPoint point(nmia->ptAction);
	int nCurItem = m_pListCtrl->HitTest(point);
	if ( nCurItem==-1 )
		return;

	LPLISTPARAM pliParam = (LPLISTPARAM)m_pListCtrl->GetItemData(nCurItem);
	
	if ( pliParam->uType>0 )
	{
		SHELLEXECUTEINFO si;
		ZeroMemory(&si,sizeof(si));
		si.cbSize = sizeof(si);
		si.hwnd = GetSafeHwnd();
		si.nShow = SW_SHOW;
		si.lpIDList = (LPVOID)pliParam->lpidl;
		si.fMask  = SEE_MASK_INVOKEIDLIST;
		ShellExecuteEx(&si);
	}
	else
	{
//		SetListContext(pliParam->lpsf,pliParam->lpidl);
		g_TreeView->SetTreeContext(pliParam->lpsf,pliParam->lpidl);
	}
	*pResult = 0;
}

void CExplorerListView::OnRclick(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here
	NMITEMACTIVATE * nmia = (NMITEMACTIVATE *) pNMHDR;
	
	POSITION pos = m_pListCtrl->GetFirstSelectedItemPosition();
	if ( pos==NULL )
	{
		//没选中时

		return;
	}

	char * szPath = new char[MAX_PATH];
	CStringArray sPathArray;
	while (pos)
	{
		ZeroMemory(szPath,MAX_PATH);
		int nItem = m_pListCtrl->GetNextSelectedItem(pos);
		LPLISTPARAM pliParam =(LPLISTPARAM) m_pListCtrl->GetItemData(nItem);
		SHGetPathFromIDList(pliParam->lpidl,szPath);
		sPathArray.Add(szPath);
	}
	delete szPath;
	
	CShellContextMenu scm;        
	scm.SetObjects(sPathArray);    
	CPoint point (nmia->ptAction);
	m_pListCtrl->ClientToScreen(&point);
	UINT idCommand = scm.ShowContextMenu(this, point);

	switch( idCommand )
	{
	case 18: //chose delete
		{
			g_TreeView->SendMessage(WM_REFRESHFILES,(WPARAM)g_TreeView->m_hSelItem,0);
			SendMessage(WM_REFRESHFILES,0,0);
			break;
		}
	case 27:  //chose paste
		{
			break;
		}
	}

 	*pResult = 0;
}

void CExplorerListView::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	g_TreeView->m_hMoveSrc = g_TreeView->m_hSelItem;

	POSITION pos = m_pListCtrl->GetFirstSelectedItemPosition();
	if ( pos==NULL )
		return;
	
	char * szSrc = new char[MAX_PATH];
	CStringArray sDragArray;
	while(pos)
	{
		int nItem = m_pListCtrl->GetNextSelectedItem(pos);
		LPLISTPARAM pliItem = (LPLISTPARAM)m_pListCtrl->GetItemData(nItem);
		ZeroMemory(szSrc,MAX_PATH);
		SHGetPathFromIDList(pliItem->lpidl,szSrc);
		
		sDragArray.Add(szSrc);
	}
	delete szSrc;

	//创建拖拽数据源
	int hgblSize = sizeof(DROPFILES);
	for ( int i=0 ; i<sDragArray.GetSize() ; i++ )
	{
		hgblSize += (sDragArray.GetAt(i).GetLength()+1) * sizeof(_TCHAR);
	}
	hgblSize += 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);
	
	for ( i=0 ; i<sDragArray.GetSize() ; i++ )
	{
		strcpy((char*)(pGlobalString), sDragArray.GetAt(i) );
		pGlobalString += ( sDragArray.GetAt(i).GetLength()+1 ) * sizeof(_TCHAR);
	}
	pGlobalString[0] = _T('\0');
	
	GlobalUnlock(hgblData);
	
	COleDataSource *poleSourceObj = new COleDataSource;
	poleSourceObj->CacheGlobalData(CF_HDROP,hgblData);
	DROPEFFECT dropeffect = poleSourceObj->DoDragDrop();
	
	*pResult = 0;
}

void CExplorerListView::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult) 
{
	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
	// TODO: Add your control notification handler code here
	LV_ITEM lvItem = pDispInfo->item;
	LPLISTPARAM pliParam = (LPLISTPARAM)lvItem.lParam;
	char * szSource = new char[MAX_PATH];
	SHGetPathFromIDList(pliParam->lpidl,szSource);
	
	LPTREEPARAM ptrParam = (LPTREEPARAM)g_TreeView->GetSelTreeData();
	char * szDest = new char[MAX_PATH];
	SHGetPathFromIDList(ptrParam->lpidl,szDest);
	strcat(szDest,lvItem.pszText);
	
	CShellFileOp op;
	op.SetOperationFlags(FO_MOVE, this, FOF_NOCONFIRMMKDIR);
	op.AddDestFile(szDest);
	op.AddSourceFile(szSource);
	
	BOOL bSuccess, bAPICalled = FALSE, bAborted = FALSE;
	int  nAPIReturn = 0;
	bSuccess = op.Go ( &bAPICalled, &nAPIReturn, &bAborted );
	if ( bSuccess && !bAborted )
	{
		g_TreeView->SendMessage(WM_REFRESHFILES,(WPARAM)g_TreeView->m_hSelItem,0);
		*pResult = 1;
	}
	else
	{
		*pResult = 0;
	}
}

long CExplorerListView::OnRefreshList(WPARAM wParam, LPARAM lParam)
{
	if ( g_TreeView )
	{
		LPTREEPARAM ltrParam = (LPTREEPARAM)g_TreeView->GetSelTreeData();
		SetListContext(ltrParam->lpsf,ltrParam->lpidl);
	}
	return 0;
}

BOOL CExplorerListView::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class
	if ( pMsg->message==WM_RENDERFORMAT )
	{
		long l = pMsg->lParam;
	}
	if ( pMsg->message==WM_KEYDOWN )
	{
		HWND hWnd = this->GetSafeHwnd();
		switch ( pMsg->wParam )
		{
		case 0x43:     //Ctrl+C
			{
				short ctrl = GetKeyState(VK_CONTROL);
				if ( HIBYTE(ctrl)!=0xFF )
					break;
				
				GetParent()->PostMessage(WM_COMMAND,MAKEWPARAM(0,ID_EDIT_COPY),0);
				break;
			}
		case 0x58:     //Ctrl+X
			{ 
				short ctrl = GetKeyState(VK_CONTROL);
				if ( HIBYTE(ctrl)!=0xFF )
					break;
				
				GetParent()->PostMessage(WM_COMMAND,MAKEWPARAM(0,ID_EDIT_CUT),0);
				break;
			}
		case 0x56:     //Ctrl+V
			{
				short ctrl = GetKeyState(VK_CONTROL);
				if ( HIBYTE(ctrl)!=0xFF )
					break;

				GetParent()->PostMessage(WM_COMMAND,MAKEWPARAM(0,ID_EDIT_PASTE),0);
				break;
			}
		case 0x2e:       //DEL
			{
				CShellFileOp op;
				short lShift = GetKeyState(VK_LSHIFT);
				short rShift = GetKeyState(VK_RSHIFT);
				if ( HIBYTE(lShift)==0xFF || HIBYTE(rShift)==0xFF )
					op.SetOperationFlags(FO_DELETE, this,NULL);
				else
					op.SetOperationFlags(FO_DELETE, this,FOF_ALLOWUNDO);
				
				
				POSITION pos = m_pListCtrl->GetFirstSelectedItemPosition();
				if ( pos==NULL )
					return true;
				char * szSrc = new char[MAX_PATH];
				while(pos)
				{
					int nItem = m_pListCtrl->GetNextSelectedItem(pos);
					LPLISTPARAM pliItem = (LPLISTPARAM)g_ListView->m_pListCtrl->GetItemData(nItem);
					
					ZeroMemory(szSrc,MAX_PATH);
					SHGetPathFromIDList(pliItem->lpidl,szSrc);
					
					op.AddSourceFile(szSrc);
				}
				delete szSrc;

				BOOL bSuccess, bAPICalled = FALSE, bAborted = FALSE;
				int  nAPIReturn = 0;
				bSuccess = op.Go(&bAPICalled, &nAPIReturn, &bAborted);
				
				//refresh
				if ( bSuccess&&!bAborted )
				{
					g_TreeView->SendMessage(WM_REFRESHFILES,(WPARAM)g_TreeView->m_hSelItem,0);
					g_ListView->SendMessage(WM_REFRESHFILES,0,0);
				}
				break;
			}
		}
	}
	if (pMsg->message==WM_DROPFILES)
	{
		short ctrl = HIWORD(pMsg->wParam);
		return 0;
	}
	return CListView::PreTranslateMessage(pMsg);
}


//////////////////////////////////////////////////
// method
///////////////////////////////////////////////////

void CExplorerListView::InitImageList()
{	
	HIMAGELIST himlSmall;
    HIMAGELIST himlLarge;
    SHFILEINFO sfi;

    himlSmall = (HIMAGELIST)SHGetFileInfo((LPCTSTR)_T("C:\\"), 
                                           0,
                                           &sfi, 
                                           sizeof(SHFILEINFO), 
                                           SHGFI_SYSICONINDEX | SHGFI_SMALLICON);

    himlLarge = (HIMAGELIST)SHGetFileInfo((LPCTSTR)_T("C:\\"), 
                                           0,
                                           &sfi, 
                                           sizeof(SHFILEINFO), 
                                           SHGFI_SYSICONINDEX | SHGFI_LARGEICON);

    if (himlSmall && himlLarge)
    {
        ::SendMessage(GetSafeHwnd(), LVM_SETIMAGELIST, (WPARAM)LVSIL_SMALL,
            (LPARAM)himlSmall);
        ::SendMessage(GetSafeHwnd(), LVM_SETIMAGELIST, (WPARAM)LVSIL_NORMAL,
            (LPARAM)himlLarge);
    }

}	

void CExplorerListView::SetListContext(IShellFolder *psfParent, LPITEMIDLIST pidlParent)
{
//	m_pListCtrl->DeleteAllItems();

	DeleteAllItems();

	IEnumIDList  *peidl;
	LPITEMIDLIST pidl, pidlAbs;
	IShellFolder *psf = NULL;

	HRESULT hr = psfParent->EnumObjects(NULL,SHCONTF_FOLDERS ,&peidl);

	if ( NOERROR!=hr )
		return;
	while (NOERROR == hr)
	{
		hr = peidl->Next(1, &pidl, NULL);
		if (hr == S_FALSE || pidl == NULL)
			break;
		pidlAbs = ConcatPidl(pidlParent,pidl);
		psfParent->BindToObject(pidl, NULL, IID_IShellFolder, (void**)&psf);

		SHFILEINFO sfi;
		SHGetFileInfo((LPCTSTR)pidlAbs, 
			0,
			&sfi, 
			sizeof(SHFILEINFO), 
			SHGFI_PIDL|SHGFI_SYSICONINDEX|SHGFI_SMALLICON|
			SHGFI_DISPLAYNAME|SHGFI_ATTRIBUTES);

		LVITEM lvItem;
		memset(&lvItem,0,sizeof(lvItem));
		lvItem.mask     |= LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM ;
		lvItem.iItem     = m_pListCtrl->GetItemCount();
		lvItem.iImage    = sfi.iIcon;
		lvItem.pszText   = sfi.szDisplayName;

		LPLISTPARAM pliParam = (LPLISTPARAM)m_pMalloc->Alloc(sizeof(LISTPARAM));
		pliParam->lpsf    = psf;
		pliParam->lpidl   = pidlAbs;
		pliParam->uType   = 0;
		strcpy(pliParam->szName,sfi.szDisplayName);
		lvItem.lParam = (LPARAM)pliParam;

		m_pListCtrl->InsertItem(&lvItem);

		m_pMalloc->Free(pidl);
	}
	peidl->Release();    //若不Release掉文件会处于被操作的状态

	if ( g_TreeView )
	{
		//我的电脑的子项会得到文件和非文件两套
		//过滤掉文件的项
		if ( ComparePidls(g_TreeView->m_psfDesk, g_TreeView->m_pidlMyComputer, pidlParent) )
			return;
	}

	hr = psfParent->EnumObjects(NULL,SHCONTF_NONFOLDERS ,&peidl);
	if ( NOERROR!=hr )
		return;
	while (NOERROR == hr)
	{
		hr = peidl->Next(1, &pidl, NULL);
		if (hr == S_FALSE || pidl == NULL)
			break;
		pidlAbs = ConcatPidl(pidlParent,pidl);
		psfParent->BindToObject(pidl, NULL, IID_IShellFolder, (void**)&psf);

		SHFILEINFO sfi;
		SHGetFileInfo((LPCTSTR)pidlAbs, 
			0,
			&sfi, 
			sizeof(SHFILEINFO), 
			SHGFI_PIDL|SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_DISPLAYNAME);

		LVITEM lvItem;
		memset(&lvItem,0,sizeof(lvItem));
		lvItem.mask     |= LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM ;
		lvItem.iItem     = m_pListCtrl->GetItemCount();
		lvItem.iImage    = sfi.iIcon;
		lvItem.pszText   = sfi.szDisplayName;

		LPLISTPARAM pliParam = (LPLISTPARAM)m_pMalloc->Alloc(sizeof(LISTPARAM));
		pliParam->lpsf    = psf;
		pliParam->lpidl   = pidlAbs;
		pliParam->uType   = 1;
		strcpy(pliParam->szName,sfi.szDisplayName);
		lvItem.lParam = (LPARAM)pliParam;

		m_pListCtrl->InsertItem(&lvItem);
	}
	peidl->Release();

	m_pListCtrl->SortItems(SortListView, (DWORD)this);
}

int CALLBACK CExplorerListView::SortListView(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
	CListCtrl* pListCtrl = (CListCtrl*)lParamSort;
	LPLISTPARAM     pliParam1 = (LPLISTPARAM)lParam1;
	LPLISTPARAM     pliParam2 = (LPLISTPARAM)lParam2;
	if ( pliParam1->uType==pliParam2->uType )
	{
		return strcmp(pliParam1->szName, pliParam2->szName);
	}
	else if (pliParam1->uType<pliParam2->uType)
	{
		return -1;
	}
	else
	{
		return 1;
	}
}

int CExplorerListView::SetListViewType(DWORD viewType)
{
	if ( m_dViewType==viewType )
		return viewType;
	
	int old = m_dViewType;

	CMenu * pMainMenu = AfxGetApp()->GetMainWnd()->GetMenu();
	CMenu * pMenu     = pMainMenu->GetSubMenu(2);
	
	switch(viewType)
	{
	case LVS_ICON:	
		pMenu->CheckMenuRadioItem(3,5,3,MF_BYPOSITION);
		break;
	case LVS_SMALLICON:
		pMenu->CheckMenuRadioItem(3,5,4,MF_BYPOSITION);
		break;
	case LVS_LIST:	
		pMenu->CheckMenuRadioItem(3,5,5,MF_BYPOSITION);
		break;
	}
	ModifyStyle(m_dViewType, viewType);

	m_dViewType = viewType;

	return old;
}


void CExplorerListView::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu)
{
	CWnd::OnMenuSelect(nItemID, nFlags, hSysMenu);
}

void CExplorerListView::DeleteAllItems()
{
	int nCount = m_pListCtrl->GetItemCount();
	for ( int i=0 ; i<nCount ; i++ )
	{
		LPLISTPARAM pliParam = (LPLISTPARAM)m_pListCtrl->GetItemData(i);
		m_pMalloc->Free(pliParam->lpidl);
		m_pMalloc->Free(pliParam);
	}
	m_pListCtrl->DeleteAllItems();
}

⌨️ 快捷键说明

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