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 + -
显示快捷键?