localfilelistctrl.cpp

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

CPP
2,497
字号
		name.MakeLower();
		
		for (i=0;i<static_cast<int>(m_FileData.size());i++)
		{
			if (name==m_FileData[i].lName)
				break;
		}

		bDir=TRUE;
	}
	else
	{
		name=file.Mid(pos+1);
		name.MakeLower();
	
		for (i=0;i<static_cast<int>(m_FileData.size());i++)
		{
			if (name==m_FileData[i].lName)
				break;
		}
		hFind = FindFirstFile( file, &find);	
	}
	
	unsigned int nIndex=i;
	if (!hFind || hFind==INVALID_HANDLE_VALUE)
	{
		//File does not exist
		if (nIndex!=m_FileData.size())
		{ //But file is still visible in list
			if (!bDir && m_FileData[nIndex].bIsDir)
			{
				FindClose(hFind);
				return;
			}
			if (bDir && !m_FileData[nIndex].bIsDir)
			{
				FindClose(hFind);
				return;
			}
			
			m_FileData.erase(m_FileData.begin()+nIndex);
			unsigned int j;
			for (j=0; j<static_cast<int>(m_IndexMapping.size()); j++)
			{
				if (m_IndexMapping[j]==nIndex)
					break;
			}
			ASSERT(j!=m_IndexMapping.size());
			m_IndexMapping.erase(m_IndexMapping.begin()+j);
			for (i=1;i<static_cast<int>(m_IndexMapping.size());i++)
			{
				if (m_IndexMapping[i]>nIndex)
					m_IndexMapping[i]--;
			}
			SetItemState( j, 0, LVIS_SELECTED);
			for (int nItem=j+1;nItem<GetItemCount();nItem++)
			{
				if (GetItemState( nItem, LVIS_SELECTED))
				{
					SetItemState( nItem, 0, LVIS_SELECTED);
					SetItemState( nItem-1, LVIS_SELECTED, LVIS_SELECTED);
				}
			}
			
			SetItemCount(GetItemCount()-1);
		}
	}
	else
	{
		if (!bDir)
		{
			if (find.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY || !_tcscmp(find.cFileName, _T(".")) || !_tcscmp(find.cFileName, _T("..")) )
			{
				FindClose(hFind);
				return;
			}
		}
		else if (!(find.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
		{
			FindClose(hFind);
			return;
		}

		t_FileData FileData;
		int count=GetItemCount();
		int datapos;
		BOOL bSelected=FALSE;
		if (nIndex!=m_FileData.size())
		{ //File is already visible in list
			if (!bDir && m_FileData[nIndex].bIsDir)
			{
				FindClose(hFind);	
				return;
			}
			else if (bDir && !m_FileData[nIndex].bIsDir)
			{
				FindClose(hFind);	
				return;
			}
			m_FileData[nIndex].Name=find.cFileName;
			m_FileData[nIndex].lName=find.cFileName;
			m_FileData[nIndex].lName.MakeLower();
			m_FileData[nIndex].nSize=bDir ? -1 : ((_int64)find.nFileSizeLow + ((_int64)find.nFileSizeHigh<<32));
			m_FileData[nIndex].Time=find.ftLastWriteTime;
			FileData=m_FileData[nIndex];
			unsigned int j;
			for (j=0; j<static_cast<int>(m_IndexMapping.size()); j++)
			{
				if (m_IndexMapping[j]==nIndex)
					break;
			}
			ASSERT(j!=m_IndexMapping.size());
			m_IndexMapping.erase(m_IndexMapping.begin()+j);
			if (GetItemState( j, LVIS_SELECTED))
				bSelected=TRUE;
			SetItemState( j, 0, LVIS_SELECTED);
			for (int nItem=j+1;nItem<GetItemCount();nItem++)
			{
				if (GetItemState( nItem, LVIS_SELECTED))
				{
					SetItemState( nItem, 0, LVIS_SELECTED);
					SetItemState( nItem-1, LVIS_SELECTED, LVIS_SELECTED);
				}
			}
			datapos=nIndex;
			count--;
		}
		else
		{
			FileData.Name=find.cFileName;
			FileData.lName=find.cFileName;
			FileData.lName.MakeLower();
			FileData.bIsDir=bDir;
			FileData.nSize=bDir ? -1 : ((_int64)find.nFileSizeLow + ((_int64)find.nFileSizeHigh<<32));
			FileData.Time=find.ftLastWriteTime;
			m_FileData.push_back(FileData);
			datapos=count;
			SetItemCount(GetItemCount()+1);
		}
		CString filetype;
		if (m_Columns[m_sortcolumn]==2)
		{
			filetype=GetType(FileData.lName, FileData.bIsDir);
			filetype.MakeLower();
		}
		
		if (count>1)
		{ //Binary search for optimal position to insert file sorted.
			int anf=1;
			int ende=count-1;
			
			int mitte;
			while(anf<=ende)
			{
				mitte=(anf+ende)/2;
				
				t_FileData CompareData=m_FileData[m_IndexMapping[mitte]];
				BOOL res;
				if (!m_Columns[m_sortcolumn]) //Chose compare function based on column and direction
					if (m_sortdir==1)
						res=lesser(CompareData.lName, FileData.lName, CompareData.bIsDir, FileData.bIsDir);
					else
						res=greater(CompareData.lName, FileData.lName, CompareData.bIsDir, FileData.bIsDir);
				else if (m_Columns[m_sortcolumn]==1)
					if (m_sortdir==1)
						res=lesserbysize(CompareData.nSize, FileData.nSize, CompareData.bIsDir, FileData.bIsDir, CompareData.lName, FileData.lName);
					else
						res=greaterbysize(CompareData.nSize, FileData.nSize, CompareData.bIsDir, FileData.bIsDir, CompareData.lName, FileData.lName);
				else if (m_Columns[m_sortcolumn]==2)
				{
					CString typecompare=GetType(CompareData.lName, CompareData.bIsDir);
					typecompare.MakeLower();
					if (m_sortdir==1)
						res=lesserbytype(typecompare, filetype, CompareData.bIsDir, FileData.bIsDir, CompareData.lName, FileData.lName);
					else
						res=greaterbytype(typecompare, filetype, CompareData.bIsDir, FileData.bIsDir, CompareData.lName, FileData.lName);
				}
				else if (m_Columns[m_sortcolumn]==3)
					if (m_sortdir==1)
						res=lesserbytime(CompareData.Time, FileData.Time, CompareData.bIsDir, FileData.bIsDir, CompareData.lName, FileData.lName);
					else
						res=greaterbytime(CompareData.Time, FileData.Time, CompareData.bIsDir, FileData.bIsDir, CompareData.lName, FileData.lName);
						
				if (res)
					anf=mitte+1;
				else
				{
					ende=mitte-1;
					mitte--;
				}
			}
			m_IndexMapping.insert(m_IndexMapping.begin()+mitte+1, datapos);
			for (int nItem=GetItemCount()-1; nItem>(mitte+1); nItem--)
			{
				if (GetItemState( nItem-1, LVIS_SELECTED))
				{
					SetItemState( nItem-1, 0, LVIS_SELECTED);
					SetItemState( nItem, LVIS_SELECTED, LVIS_SELECTED);
				}
			}
			if (bSelected)
				SetItemState( mitte+1, LVIS_SELECTED, LVIS_SELECTED);
		}
		else
			m_IndexMapping.push_back(count);
	}
	if (hFind && hFind!=INVALID_HANDLE_VALUE)
		FindClose(hFind);
	RedrawItems(0, GetItemCount());
	UpdateStatusBar();
}

CString CLocalFileListCtrl::GetType(CString lName, BOOL bIsDir)
{
	CString type;
	std::map<CString, CString>::iterator typeIter=m_TypeCache.find(m_Fullpath+lName);
	if (typeIter==m_TypeCache.end())
	{
		CString str=PathFindExtension(lName);
		str.MakeLower();
		std::map<CString, CString>::iterator permTypeIter=m_permanentTypeCache.find(str);
		if (permTypeIter!=m_permanentTypeCache.end())
		{
			m_TypeCache[m_Fullpath+lName]=permTypeIter->second;
			type=permTypeIter->second;
		}
		else
		{
			SHFILEINFO shFinfo;
			CString path;
			path=m_Fullpath+lName;
			if (m_Fullpath=="")
				path+="\\";
			memset(&shFinfo,0,sizeof(SHFILEINFO));
			if (SHGetFileInfo(path,
				bIsDir?FILE_ATTRIBUTE_DIRECTORY:FILE_ATTRIBUTE_NORMAL,
				&shFinfo,
				sizeof( shFinfo ),
				SHGFI_TYPENAME))
			{
				type=shFinfo.szTypeName;
				if (type=="")
				{
					type=PathFindExtension(lName);
					if (type!="") 
						type=type.Mid(1);
					type.MakeUpper();
					if (type!="")
						type+="-file";
					else
						type="File";
				}
				else
				{
					CString str2=PathFindExtension(lName);
					if (!bIsDir && str2!="")
					{
						str2.MakeLower();
						m_permanentTypeCache[str2]=type;
					}
				}
			}
			else
			{
				type=PathFindExtension(lName);
				if (type!="") 
					type=type.Mid(1);
				type.MakeUpper();
				if (type!="")
					type+="-file";
				else
					type="File";
			}
			m_TypeCache[m_Fullpath+lName]=type;		
		}
	}
	else
		type=typeIter->second;
	return type;
}

void CLocalFileListCtrl::OnLocalcontextViewEdit()
{
	if (m_Fullpath=="")
		return;

	POSITION selpos=GetFirstSelectedItemPosition();
	if (!selpos)
		return;
	
	int nItem = GetNextSelectedItem(selpos);
	if (!nItem)
		return;
	
	int index=m_IndexMapping[nItem];

	if (m_FileData[index].bIsDir)
		return;

	CString file=m_FileData[index].lName;

	int pos=file.ReverseFind('.');
	if (pos!=-1)
	{
		CString fext=file.Mid(pos+1);
		fext.MakeLower();
		//Parse the file associations
		CString CustomAssociations=COptions::GetOption(OPTION_VIEWEDITCUSTOM);
		
		CString ext;
		CString prog;
		BOOL bDoExt=TRUE;
		while (CustomAssociations!="")
		{
			int pos=CustomAssociations.Find( _T(";") );
			if (bDoExt)
			{
				if (!pos || pos==-1 || pos==CustomAssociations.GetLength()-1)
					break;
				ext+=CustomAssociations.Left(pos);
				CustomAssociations=CustomAssociations.Mid(pos+1);
				if (CustomAssociations.Left(1)== _T(" "))
				{
					ext+=_T(";");
					CustomAssociations=CustomAssociations.Mid(1);
				}
				else
					bDoExt=FALSE;
			}
			else
			{
				if (!pos || pos==CustomAssociations.GetLength()-1)
					break;
				if (pos!=-1)
				{
					prog+=CustomAssociations.Left(pos);
					CustomAssociations=CustomAssociations.Mid(pos+1);
				}
				else
				{
					prog=CustomAssociations;
					CustomAssociations="";
				}
				if (CustomAssociations.Left(1)== _T(" "))
				{
					prog+=_T(";");
					CustomAssociations=CustomAssociations.Mid(1);
					if (CustomAssociations!="")
						continue;
				}
				
				ext.MakeLower();
				if (fext==ext)
				{ //We've found a file aassociation for this extension
					CString cmdLine;
					file=m_Fullpath+file;
					if (file.Find( _T(" ") )!=-1)
						file=_T("\"") + file + _T("\"");
					cmdLine=prog + _T(" ") + file;
					PROCESS_INFORMATION ProcessInformation;  
					STARTUPINFO startupinfo={0};
					startupinfo.cb=sizeof(startupinfo);
					LPTSTR str=new TCHAR[cmdLine.GetLength()+1];
					_tcscpy(str, cmdLine);
					if (CreateProcess(0, str, 0, 0, 0, 0, 0, 0, &startupinfo, &ProcessInformation))
					{
						CloseHandle(ProcessInformation.hThread);
						CloseHandle(ProcessInformation.hProcess);
					}
					delete [] str;
					return;;
				}
				ext="";
				prog="";
				bDoExt=TRUE;
			}
		}
	}
	//File has no extension or custom file association could not be found
	CString defprog=COptions::GetOption(OPTION_VIEWEDITDEFAULT);
	if (defprog=="")
	{
		AfxMessageBox(IDS_ERRORMSG_VIEWEDIT_NODEFPROG, MB_ICONEXCLAMATION);
		return;
	}
	CString cmdLine;
	file=m_Fullpath+file;
	if (file.Find( _T(" ") )!=-1)
		file=_T("\"") + file + _T("\"");
	cmdLine=defprog + _T(" ") + file;
	PROCESS_INFORMATION ProcessInformation;  
	STARTUPINFO startupinfo={0};
	startupinfo.cb=sizeof(startupinfo);
	LPTSTR str=new TCHAR[cmdLine.GetLength()+1];
	_tcscpy(str, cmdLine);
	if (CreateProcess(0, str, 0, 0, 0, 0, 0, 0, &startupinfo, &ProcessInformation))
	{
		CloseHandle(ProcessInformation.hThread);
		CloseHandle(ProcessInformation.hProcess);
	}
	delete [] str;
}

BOOL CLocalFileListCtrl::UpdateStatusBar()
{
	if (m_bUpdating)
		return FALSE;

	CString str;
	POSITION selpos = GetFirstSelectedItemPosition();
	
	int dircount = 0;
	int filecount = 0;
	_int64 size = 0;

	while (selpos)
	{
		int nItem = GetNextSelectedItem(selpos);
		if (!nItem)
			continue;

		int nIndex = m_IndexMapping[nItem];
		if (m_FileData[nIndex].bIsDir)
				dircount++;
			else
			{
				filecount++;
				size += m_FileData[nIndex].nSize;
			}
	}

	if (dircount || filecount)
	{
		if (!dircount)
			if (filecount == 1)
				str.Format(IDS_DIRINFO_SELECTED_FILE, size);
			else
				str.Format(IDS_DIRINFO_SELECTED_FILES, filecount, size);
		else if (!filecount)
			if (dircount == 1)
				str.LoadString(IDS_DIRINFO_SELECTED_DIR);
			else
				str.Format(IDS_DIRINFO_SELECTED_DIRS, dircount);
		else if (dircount == 1)
			if (filecount == 1)
				str.Format(IDS_DIRINFO_SELECTED_DIRANDFILE, size);
			else
				str.Format(IDS_DIRINFO_SELECTED_DIRANDFILES, filecount, size);
		else
			if (filecount == 1)
				str.Format(IDS_DIRINFO_SELECTED_DIRSANDFILE, dircount, size);
			else
				str.Format(IDS_DIRINFO_SELECTED_DIRSANDFILES, dircount, filecount, size);
		return m_pOwner->SetStatusBarText(str);
	}

	if (m_FileData.size() <= 1)
		str.LoadString(IDS_DIRINFO_EMPTY);
	else
	{
		for (unsigned int i=1; i<m_FileData.size(); i++)
			if (m_FileData[i].bIsDir)
				dircount++;
			else
			{
				filecount++;
				size += m_FileData[i].nSize;
			}
		if (!dircount)
			if (filecount == 1)
				str.Format(IDS_DIRINFO_FILE, size);
			else
				str.Format(IDS_DIRINFO_FILES, filecount, size);
		else if (!filecount)
			if (dircount == 1)
				str.LoadString(IDS_DIRINFO_DIR);
			else
				str.Format(IDS_DIRINFO_DIRS, dircount);
		else if (dircount == 1)
			if (filecount == 1)
				str.Format(IDS_DIRINFO_DIRANDFILE, size);
			else
				str.Format(IDS_DIRINFO_DIRANDFILES, filecount, size);
		else
			if (filecount == 1)
				str.Format(IDS_DIRINFO_DIRSANDFILE, dircount, size);
			else
				str.Format(IDS_DIRINFO_DIRSANDFILES, dircount, filecount, size);			
	}
	
	return m_pOwner->SetStatusBarText(str);
}

void CLocalFileListCtrl::OnItemchanged(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	// TODO: Code f黵 die Behandlungsroutine der Steuerelement-Benachr

⌨️ 快捷键说明

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