localfilelistctrl.cpp

来自「一个支持FTP,SFTP的客户端程序」· C++ 代码 · 共 2,497 行 · 第 1/5 页

CPP
2,497
字号

  if (anf<r) quicksortbytype(array, direction, anf, r);
  if (l<ende) quicksortbytype(array, direction, l, ende);
}

void CLocalFileListCtrl::quicksortbysize(const BOOL &direction, int anf, int ende)
{
	int l=anf;
	int r=ende;
	CString tmp;
	_int64 ref=m_FileData[m_IndexMapping[(l+r)/2]].nSize;
	CString refname=m_FileData[m_IndexMapping[(l+r)/2]].lName;
	BOOL bRefIsDir=m_FileData[m_IndexMapping[(l+r)/2]].bIsDir;
	do
    {
		if (direction)
		{
			while (lesserbysize (m_FileData[m_IndexMapping[l]].nSize, ref, m_FileData[m_IndexMapping[l]].bIsDir, bRefIsDir, m_FileData[m_IndexMapping[l]].lName, refname) && (l<ende)) l++;
			while (greaterbysize(m_FileData[m_IndexMapping[r]].nSize, ref, m_FileData[m_IndexMapping[r]].bIsDir, bRefIsDir, m_FileData[m_IndexMapping[r]].lName, refname) && (r>anf)) r--;
		}
		else
		{
			while (greaterbysize(m_FileData[m_IndexMapping[l]].nSize, ref, m_FileData[m_IndexMapping[l]].bIsDir, bRefIsDir, m_FileData[m_IndexMapping[l]].lName, refname) && (l<ende)) l++;
			while (lesserbysize (m_FileData[m_IndexMapping[r]].nSize, ref, m_FileData[m_IndexMapping[r]].bIsDir, bRefIsDir, m_FileData[m_IndexMapping[r]].lName, refname) && (r>anf)) r--;
		}
		if (l<=r)
		{
			int tmp=m_IndexMapping[l];
			m_IndexMapping[l]=m_IndexMapping[r];
			m_IndexMapping[r]=tmp;
			l++;
			r--;
		}
    } 
	while (l<=r);

  if (anf<r) quicksortbysize(direction, anf, r);
  if (l<ende) quicksortbysize(direction, l, ende);
}

void CLocalFileListCtrl::quicksortbytime(const BOOL &direction, int anf, int ende)
{
	int l=anf;
	int r=ende;
	CString tmp;
	CTime ref=m_FileData[m_IndexMapping[(l+r)/2]].Time;
	CString refname=m_FileData[m_IndexMapping[(l+r)/2]].lName;
	BOOL bRefIsDir=m_FileData[m_IndexMapping[(l+r)/2]].bIsDir;
	do
    {
		if (direction)
		{
			while (lesserbytime (m_FileData[m_IndexMapping[l]].Time, ref, m_FileData[m_IndexMapping[l]].bIsDir, bRefIsDir, m_FileData[m_IndexMapping[l]].lName, refname) && (l<ende)) l++;
			while (greaterbytime(m_FileData[m_IndexMapping[r]].Time, ref, m_FileData[m_IndexMapping[r]].bIsDir, bRefIsDir, m_FileData[m_IndexMapping[r]].lName, refname) && (r>anf)) r--;
		}
		else
		{
			while (greaterbytime(m_FileData[m_IndexMapping[l]].Time, ref, m_FileData[m_IndexMapping[l]].bIsDir, bRefIsDir, m_FileData[m_IndexMapping[l]].lName, refname) && (l<ende)) l++;
			while (lesserbytime (m_FileData[m_IndexMapping[r]].Time, ref, m_FileData[m_IndexMapping[r]].bIsDir, bRefIsDir, m_FileData[m_IndexMapping[r]].lName, refname) && (r>anf)) r--;
		}
		if (l<=r)
		{
			int tmp=m_IndexMapping[l];
			m_IndexMapping[l]=m_IndexMapping[r];
			m_IndexMapping[r]=tmp;
			l++;
			r--;
		}
    } 
	while (l<=r);

  if (anf<r) quicksortbytime(direction, anf, r);
  if (l<ende) quicksortbytime(direction, l, ende);
}

void CLocalFileListCtrl::SortList(int item, int direction)
{
	UINT nID[4]={IDS_HEADER_FILENAME,IDS_HEADER_FILESIZE,IDS_HEADER_FILETYPE,IDS_HEADER_LASTMODIFIED};

	if (!direction)
	{
		if (item!=m_sortcolumn)
			m_sortdir=1;
		else
		{
			m_sortdir=(++m_sortdir%3);
			if (!m_sortdir)
				m_sortdir++;
		}
			
	}
	else if (direction != -1)
		m_sortdir = direction;

	if (item == -1)
		item = m_sortcolumn;

	CHeaderCtrl *header=GetHeaderCtrl();
	if (header)
	{
		CString headertext;
		headertext.LoadString(nID[m_Columns[m_sortcolumn]]);
		HDITEM *hdi=new HDITEM;
		hdi->pszText=headertext.GetBuffer(0);
		hdi->cchTextMax=0;
		hdi->mask= HDI_TEXT | HDI_FORMAT;
		hdi->fmt=((m_Columns[m_sortcolumn]!=1)?HDF_LEFT:HDF_RIGHT) | HDF_STRING;
		hdi->mask= HDI_TEXT | HDI_IMAGE | HDI_FORMAT;
		hdi->iImage=0; // My ascending image list index
		header->SetItem( m_sortcolumn, hdi );
	
		headertext.ReleaseBuffer();
		headertext.LoadString(nID[m_Columns[item]]);
		hdi->pszText=headertext.GetBuffer(0);
		hdi->mask= HDI_TEXT | HDI_IMAGE | HDI_FORMAT;
		hdi->iImage= m_sortdir; // My ascending image list index
		hdi->fmt=((m_Columns[item]!=1)?HDF_LEFT:HDF_RIGHT) | HDF_IMAGE | HDF_STRING | HDF_BITMAP_ON_RIGHT;
		header->SetItem( item, hdi );
		delete hdi;
		headertext.ReleaseBuffer();
	}
	m_sortcolumn = item;
	int count = GetItemCount();
	if (count <= 1 ||
	  GetItemCount() != m_IndexMapping.size() ||
	  GetItemCount() != m_FileData.size())
		return;
	
	std::set<int> SelectedItemsList;
	int i;
	for (i = 1; i < count; i++)
	{
		if (GetItemState( i, LVIS_SELECTED))
		{
			SelectedItemsList.insert(m_IndexMapping[i]);
			SetItemState( i, 0, LVIS_SELECTED);
		}
	}

	if (!m_Columns[item])
	{ //Sort by filename
		BOOL dir=m_sortdir==1;
		quicksortbyname(dir, 1, count - 1);
	}
	if (m_Columns[item]==2)
	{ //Sort by filetype
	  //Since this is a column that is filled while displaying,
	  //we have to load the filetypes for every file

		std::vector<CString> array;
		array.resize(count + 1);
		array[0] = _T("");
		for (int i = 1; i < count; i++)
		{
			array[i] = GetType(m_FileData[i].lName, m_FileData[i].bIsDir);
			array[i].MakeLower();
		}
		BOOL dir = (m_sortdir == 1);
		quicksortbytype(array, dir, 1, count - 1);
	}
	else if (m_Columns[m_sortcolumn] == 1)
	{
		BOOL dir = (m_sortdir == 1);
		quicksortbysize(dir, 1, count - 1);
	}
	else if (m_Columns[m_sortcolumn] == 3)
	{
		BOOL dir = m_sortdir==1;
		quicksortbytime(dir, 1, count - 1);
	}

	for (i = 1; i < count; i++)
	{
		if (SelectedItemsList.empty())
			break;
		int nIndex = m_IndexMapping[i];
		std::set<int>::iterator iter = SelectedItemsList.find(nIndex);
		if (iter != SelectedItemsList.end())
		{
			SetItemState(i, LVIS_SELECTED, LVIS_SELECTED);
			SelectedItemsList.erase(iter);
		}
	}

	RedrawItems(0, count);
}

void CLocalFileListCtrl::OnContextMenu(CWnd* pWnd, CPoint point) 
{
	if (!GetItemCount())
		return;
	CMenu menu;
	menu.LoadMenu(IDR_LOCALCONTEXTMENU);

	CMenu* pPopup = menu.GetSubMenu(0);
	ASSERT(pPopup != NULL);
	CWnd* pWndPopupOwner = this;
	//while (pWndPopupOwner->GetStyle() & WS_CHILD)
	//	pWndPopupOwner = pWndPopupOwner->GetParent();

	POSITION selpos=GetFirstSelectedItemPosition();
	if (!selpos)
	{
		pPopup->EnableMenuItem(ID_LOCALCONTEXT_UPLOAD, MF_GRAYED);	
		pPopup->EnableMenuItem(ID_LOCALCONTEXT_UPLOADAS, MF_GRAYED);	
		pPopup->EnableMenuItem(ID_LOCALCONTEXT_ADDTOQUEUE, MF_GRAYED);
		pPopup->EnableMenuItem(ID_LOCALCONTEXT_DELETE, MF_GRAYED);	
		pPopup->EnableMenuItem(ID_LOCALCONTEXT_RENAME, MF_GRAYED);	
		pPopup->EnableMenuItem(ID_LOCALCONTEXT_OPEN, MF_GRAYED);
		pPopup->EnableMenuItem(ID_LOCALCONTEXT_PROPERTIES, MF_GRAYED);
		pPopup->EnableMenuItem(ID_LOCALCONTEXT_VIEWEDIT, MF_GRAYED);
		if (point.x==-1 || point.y==-1)
		{
			point.x=5;
			point.y=5;
			ClientToScreen(&point);
		}
	}
	else
	{
		int nItem = GetNextSelectedItem(selpos);
		if (point.x==-1 || point.y==-1)
		{
			CRect rect;
			GetItemRect(nItem,&rect,LVIR_LABEL);
			point.x=rect.left+5;
			point.y=rect.top+5;
			ClientToScreen(&point);
		}
		int index=m_IndexMapping[nItem];
		if (m_Fullpath=="")
		{
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_CREATEDIRECTORY, MF_GRAYED);	
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_RENAME, MF_GRAYED);	
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_DELETE, MF_GRAYED);	
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_UPLOAD, MF_GRAYED);	
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_UPLOADAS, MF_GRAYED);	
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_ADDTOQUEUE, MF_GRAYED);
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_VIEWEDIT, MF_GRAYED);
		}
		else if (!nItem)
		{
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_UPLOAD, MF_GRAYED);	
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_UPLOADAS, MF_GRAYED);	
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_ADDTOQUEUE, MF_GRAYED);
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_DELETE, MF_GRAYED);	
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_RENAME, MF_GRAYED);	
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_PROPERTIES, MF_GRAYED);
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_VIEWEDIT, MF_GRAYED);
		}
		if (m_FileData[index].bIsDir)
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_VIEWEDIT, MF_GRAYED);
		
		nItem = GetNextSelectedItem(selpos);
		while (nItem!=-1)
		{
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_PROPERTIES, MF_GRAYED);
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_RENAME, MF_GRAYED);
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_OPEN, MF_GRAYED);
			pPopup->EnableMenuItem(ID_LOCALCONTEXT_VIEWEDIT, MF_GRAYED);
			int index=m_IndexMapping[nItem];
			if (!nItem)
			{
				pPopup->EnableMenuItem(ID_LOCALCONTEXT_UPLOAD,MF_GRAYED);	
				pPopup->EnableMenuItem(ID_LOCALCONTEXT_UPLOADAS,MF_GRAYED);	
				pPopup->EnableMenuItem(ID_LOCALCONTEXT_ADDTOQUEUE,MF_GRAYED);
			}
			nItem = GetNextSelectedItem(selpos);
		}
	}
		
	pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
		pWndPopupOwner);
}

void CLocalFileListCtrl::OnLocalcontextOpen() 
{
	POSITION selpos=GetFirstSelectedItemPosition();
	if (!selpos)
		return;
	
	int nItem = GetNextSelectedItem(selpos);
	int index=m_IndexMapping[nItem];

	if (m_FileData[index].bIsDir)
	{
		CString newpath;
		CString text=GetItemText(nItem,0);
		if (text=="..")
		{
			newpath=m_Fullpath;
			newpath.TrimRight('\\');
			int pos=newpath.ReverseFind('\\');
			ASSERT(pos!=-1);
			newpath=newpath.Left(pos+1);
		}
		else
			newpath=m_Fullpath+m_FileData[index].Name+"\\";
		m_pOwner->SetLocalFolder(newpath);
		m_pOwner->SetLocalFolderOut(newpath);
	}
	else
	{
		CString file=m_Fullpath+m_FileData[index].Name;
		SHELLEXECUTEINFO sei = {0};
		sei.cbSize = sizeof(SHELLEXECUTEINFO);
		sei.lpFile = file;
		sei.nShow = SW_SHOWNORMAL;
		BOOL b = ShellExecuteEx(&sei);
	}
}

void CLocalFileListCtrl::OnLocalcontextUpload() 
{
	POSITION selpos=GetFirstSelectedItemPosition();
	CMainFrame *pMainFrame=DYNAMIC_DOWNCAST(CMainFrame,GetParentFrame());
	while (selpos)
	{
		int nItem = GetNextSelectedItem(selpos);
		if (!nItem || m_Fullpath=="")
			continue;
		int index=m_IndexMapping[nItem];
		if (m_FileData[index].bIsDir)
			pMainFrame->UploadDir(m_Fullpath+m_FileData[index].Name+"\\*.*", m_FileData[index].Name+"\\", TRUE, m_transferuser, m_transferpass);
		else
			pMainFrame->AddQueueItem(FALSE, m_FileData[index].Name, "", m_Fullpath, CServerPath(), TRUE, m_transferuser, m_transferpass);
	}
	pMainFrame->TransferQueue(2);
}

void CLocalFileListCtrl::OnLocalcontextAddtoqueue() 
{
	POSITION selpos=GetFirstSelectedItemPosition();
	CMainFrame *pMainFrame=DYNAMIC_DOWNCAST(CMainFrame,GetParentFrame());
	while (selpos)
	{
		int nItem = GetNextSelectedItem(selpos);
		if (!nItem || m_Fullpath=="")
			continue;
		int index=m_IndexMapping[nItem];
		if (m_FileData[index].bIsDir)
			pMainFrame->UploadDir(m_Fullpath+m_FileData[index].Name+"\\*.*", m_FileData[index].Name+"\\", FALSE, m_transferuser, m_transferpass);
		else
			pMainFrame->AddQueueItem(FALSE, GetItemText(nItem,0), "", m_Fullpath, CServerPath(), FALSE, m_transferuser, m_transferpass);
	}
}

void CLocalFileListCtrl::OnLocalcontextDelete() 
{
	POSITION selpos=GetFirstSelectedItemPosition();
	CMainFrame *pMainFrame=DYNAMIC_DOWNCAST(CMainFrame,GetParentFrame());
	
	if (!selpos)
		return;
	int len=1;
	while (selpos)
	{
		int nItem = GetNextSelectedItem(selpos);
		if (!nItem || m_Fullpath=="")
			continue;
		int index=m_IndexMapping[nItem];
		len+=m_Fullpath.GetLength()+m_FileData[index].Name.GetLength()+1;
	}

	LPTSTR buffer = new TCHAR[len];
	memset(buffer, 0, len*sizeof(TCHAR));
	selpos=GetFirstSelectedItemPosition();
	ASSERT(selpos);
	int bufpos=0;
	std::list<CString> FileList;
	BOOL bDirDeleted=FALSE;
	while (selpos)
	{
		int nItem = GetNextSelectedItem(selpos);
		if (!nItem || m_Fullpath=="")
			continue;
		int index=m_IndexMapping[nItem];
		FileList.push_back(m_FileData[index].lName);
		if (m_FileData[index].bIsDir)
			bDirDeleted=TRUE;
		_tcscpy(buffer+bufpos, m_Fullpath+m_FileData[index].Name);
		bufpos+=m_Fullpath.GetLength()+m_FileData[index].Name.GetLength()+1;
	}

	SHFILEOPSTRUCT op;
	memset(&op,0,sizeof(op));
	op.hwnd=m_hWnd;
	op.wFunc=FO_DELETE;
	op.fFlags=(GetKeyState(VK_SHIFT)&128)?0:FOF_ALLOWUNDO;
	op.pFrom=buffer;
	SHFileOperation(&op);
	delete [] buffer;
	if (bDirDeleted)
		pMainFrame->RefreshViews(1);
	else
	{
		m_bUpdating = TRUE;
		for (std::list<CString>::const_iterator iter=FileList.begin(); iter!=FileList.end(); iter++)
			RefreshFile(m_Fullpath+*iter);
		m_bUpdating = FALSE;
		UpdateStatusBar();
	}
}

void CLocalFileListCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	if (nChar==46)
		OnLocalcontextDelete();
	else if (nChar==VK_F2)
	{
		// To Use F2 as hot Key to get EditCtrl on the ListView it must have 
		// the Style LVS_EDITLABELS
		ASSERT( GetStyle() & LVS_EDITLABELS );
		// don't do an Edit Label when the multiple Items are selected
		if( GetSelectedCount( ) == 1 )
		{
			UINT nListSelectedItem = GetSelectedItem();
			VERIFY( EditLabel( nListSelectedItem ) != NULL );
		}
		else
			CListCtrl::OnKeyDown( nChar, nRepCnt, nFlags );
	}
	else if (nChar==VK_BACK)
	{
		if (GetItemCount() && m_IndexMapping.size())
		{
			int nIndex=m_IndexMapping[0];
			if (m_FileData[nIndex].bIsDir)
			{
				if (m_Fullpath!="")
				{
					CString newpath;
					newpath=m_Fullpath;
					newpath.TrimRight('\\');
					int pos=newpath.ReverseFind('\\');
					newpath=newpath.Left(pos+1);
					m_pOwner->SetLocalFolder(newpath);
					m_pOwner->SetLocalFolderOut(newpath);
				}
			}
		}
	}
	CListCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CLocalFileListCtrl::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) 
{
	//Start of a Drag&Drop operation
	*pResult = 0;

	if (m_Fullpath == _T("") || m_Fullpath == _T("\\"))
		return;

	POSITION selpos=GetFirstSelectedItemPosition();
	while (selpos)
	{
		int nItem = GetNextSelectedItem(selpos);
		if (!nItem)
			return;
	}
	EnsureVisible(((LPNMLISTVIEW)pNMHDR)->iItem, FALSE);
	
	//Let the main window handle the rest
	CMainFrame *pMainFrame=DYNAMIC_DOWNCAST(CMainFrame,GetParentFrame());
	pMainFrame->OnBegindrag(this, ((LPNMLISTVIEW)pNMHDR)->ptAction);
}

void CLocalFileListCtrl::OnDropFiles(HDROP hDropInfo) 
{
	if (!GetItemCount())
	{
		DragFinish(hDropInfo);
		return;
	}
	int dropcount=DragQueryFile(hDropInfo,0xFFFFFFFF,0,0);
	LPTSTR fullnames=0;
	int fulllen=0;
	for (int i=0;i<dropcount;i++)
	{
		int len=DragQueryFile(hDropInfo,i,0,0)+1;
		fullnames=(LPTSTR)realloc(fullnames,(fulllen+len+1)*sizeof(TCHAR));
		DragQueryFile(hDropInfo,i,&fullnames[fulllen],len);
		fulllen+=len;
	}
	fullnames[fulllen]=0;
	CString path=m_Fullpath;

	SHFILEOPSTRUCT opstruct;
	opstruct.hwnd=m_hWnd;
	opstruct.wFunc=FO_COPY;
	opstruct.pFrom=fullnames;
	opstruct.pTo=path;
	opstruct.fFlags=FOF_ALLOWUNDO;
	SHFileOperation(&opstruct);
	DragFinish(hDropInfo);
	free(fullnames);
	CMainFrame *pMainFrame=DYNAMIC_DOWNCAST(CMainFrame,GetParentFrame());
	pMainFrame->RefreshViews(1);
}

⌨️ 快捷键说明

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