dirtreectrl.cpp

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

CPP
1,174
字号
		hChild = GetNextItem( hChild, TVGN_NEXT );
	}
    
	if ( !bFound )
		return FALSE;*/

	strTempPath += "\\nul";
	if ( find.FindFile( strTempPath ) )
		return TRUE;
     
	return FALSE;
}

void CDirTreeCtrl::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	if (!m_dont_notify)
	{
		m_pOwner->SetLocalFolderOut(GetFullPath(pNMTreeView->itemNew.hItem));
	}
	*pResult = 0;
}

void CDirTreeCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	CTreeCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}

int CDirTreeCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CTreeCtrl::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	GetSysImgList()	;
		
	return 0;
}

void CDirTreeCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	if (nChar==VK_F2)
	{
		// To Use F2 as hot Key to get EditCtrl on the ListView it must have 
		// the Style TVS_EDITLABELS
		ASSERT( GetStyle() & TVS_EDITLABELS );
		// don't do an Edit Label when the multiple Items are selected
		//Don't allow to rename "My Computer"
		if (GetRootItem()==GetSelectedItem())
			return;
		//Don't allow to rename the drives
		if (GetRootItem()==GetParentItem(GetSelectedItem()))
			return;
		VERIFY( EditLabel( GetSelectedItem() ) != NULL );
	}

	CTreeCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
}

#define VK_A		65
BOOL CDirTreeCtrl::PreTranslateMessage(MSG* pMsg) 
{
	// If edit control is visible in tree view control, sending a
	// WM_KEYDOWN message to the edit control will dismiss the edit
	// control.  When ENTER key was sent to the edit control, the parent
	// window of the tree view control is responsible for updating the
	// item's label in TVN_ENDLABELEDIT notification code.
	if ( pMsg->message == WM_KEYDOWN )
	{
		CEdit* edit = GetEditControl();
		if (edit)
		{
			if( GetKeyState( VK_CONTROL )&128 && pMsg->wParam == VK_A )
			{
				edit->SetSel(0, -1);
				return TRUE;
			}
			if( pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_CONTROL || pMsg->wParam == VK_INSERT || pMsg->wParam == VK_SHIFT )
			{
				edit->SendMessage(WM_KEYDOWN, pMsg->wParam, pMsg->lParam);
				return TRUE;
			}
		}
	}
	if (pMsg->message == WM_RBUTTONDOWN)
	{
		if (pMsg->hwnd!=GetSafeHwnd())
			return FALSE;
		/*CEdit* edit = GetEditControl();
		if (edit)
			return FALSE;*/
		HTREEITEM olditem=GetSelectedItem();
		CPoint point=pMsg->pt;
		ScreenToClient(&point);
		HTREEITEM item=HitTest(point,0);
		if (item)
		{
			if (item!=olditem)
			{
				SelectItem(item);
				ExpandItem(item,TVE_EXPAND);
				m_pOwner->SetLocalFolderOut(GetFullPath(item));
				SetFocus();
			}
			
		}
		return TRUE;
	}
	return CTreeCtrl::PreTranslateMessage(pMsg);
}

void CDirTreeCtrl::OnBeginlabeledit(NMHDR* pNMHDR, LRESULT* pResult) 
{
	TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
	
	GetEditControl()->LimitText( 255 );
	
	*pResult = 0;
}

void CDirTreeCtrl::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult) 
{
	TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
	if (pTVDispInfo->item.pszText)
	{
		CString newname=pTVDispInfo->item.pszText;
		if ((newname.Find('/')!=-1)||(newname.Find('\\')!=-1)||
			(newname.Find(':')!=-1)||(newname.Find('*')!=-1)||
			(newname.Find('?')!=-1)||(newname.Find('"')!=-1)||
			(newname.Find('<')!=-1)||(newname.Find('>')!=-1)||
			(newname.Find('|')!=-1))
		{
			AfxMessageBox(IDS_ERRORMSG_FILENAMEINVALID,MB_ICONEXCLAMATION);
			*pResult=FALSE;
			return;
		}
		if (newname=="")
		{
			*pResult=FALSE;
			return;
		}
		SHFILEOPSTRUCT op;
		memset(&op,0,sizeof(op));
		CString from=GetFullPath(pTVDispInfo->item.hItem);
		from.TrimRight(_T("\\"));
		op.pFrom=from;
		CString to=from.Left(from.ReverseFind('\\')+1)+pTVDispInfo->item.pszText;
		op.pTo=to;
		op.hwnd=AfxGetMainWnd()->m_hWnd;
		op.wFunc=FO_RENAME;
		op.fFlags=FOF_ALLOWUNDO;
		if (!SHFileOperation(&op))
		{
			*pResult = TRUE;
			to.TrimRight(_T("\\"));
			to+=_T("\\");
			m_pOwner->SetLocalFolderOut(to);
			return;
		}
	}
	
	*pResult = FALSE;	
}

void CDirTreeCtrl::OnContextMenu(CWnd* pWnd, CPoint point) 
{
	if (!GetCount())
		return;
	CMenu menu;
	menu.LoadMenu(IDR_LOCALTREECONTEXTMENU);

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

	HTREEITEM hTreeItem=GetSelectedItem();
	if (!hTreeItem)
	{
		pPopup->EnableMenuItem(ID_LOCALTREECONTEXT_UPLOAD,MF_GRAYED);	
		pPopup->EnableMenuItem(ID_LOCALTREECONTEXT_UPLOADAS,MF_GRAYED);	
		pPopup->EnableMenuItem(ID_LOCALTREECONTEXT_ADDTOQUEUE,MF_GRAYED);
		pPopup->EnableMenuItem(ID_LOCALTREECONTEXT_DELETE,MF_GRAYED);	
		pPopup->EnableMenuItem(ID_LOCALTREECONTEXT_RENAME,MF_GRAYED);	
	}
	else
	{
		if (point.x==-1 || point.y==-1)
		{
			CRect rect;
			GetItemRect(hTreeItem,&rect,TRUE);
			point.x=rect.left+5;
			point.y=rect.top+5;
			ClientToScreen(&point);
		}
	
		if (!GetParentItem(hTreeItem) || !GetParentItem(GetParentItem(hTreeItem)))
		{
			pPopup->EnableMenuItem(ID_LOCALTREECONTEXT_UPLOAD, MF_GRAYED);	
			pPopup->EnableMenuItem(ID_LOCALTREECONTEXT_UPLOADAS, MF_GRAYED);	
			pPopup->EnableMenuItem(ID_LOCALTREECONTEXT_ADDTOQUEUE, MF_GRAYED);		
			pPopup->EnableMenuItem(ID_LOCALTREECONTEXT_DELETE, MF_GRAYED);	
			pPopup->EnableMenuItem(ID_LOCALTREECONTEXT_RENAME, MF_GRAYED);	
		}
	}
	pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,pWndPopupOwner);
}

void CDirTreeCtrl::OnLocaltreecontextAddtoqueue() 
{
	HTREEITEM item;
	if (m_hDragSource)
		item = m_hDragSource;
	else
		item = GetSelectedItem();

	if (!item)
		return;
	if (!GetParentItem(item))
		return;
	CString path = GetFullPath(item);
	CMainFrame *pMainFrame=DYNAMIC_DOWNCAST(CMainFrame,GetParentFrame());
	
	path.TrimRight(_T("\\"));
	
	pMainFrame->UploadDir(path + "\\*.*", GetItemText(item) + "\\", FALSE, m_transferuser, m_transferpass);
}

void CDirTreeCtrl::OnLocaltreecontextDelete() 
{
	HTREEITEM item = GetSelectedItem();	

	if (!item)
		return;
	if (!GetParentItem(item) || !GetParentItem(GetParentItem(item)))
		return;
	CString path=GetFullPath(item);	
	path.TrimRight(_T("\\"));
	HTREEITEM parentitem=GetParentItem(item);

	
	LPTSTR buffer=new TCHAR[path.GetLength()+2];
	memset(buffer,0,path.GetLength()*sizeof(TCHAR)+2*sizeof(TCHAR));
	_tcscpy(buffer,path);
	
	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;
	if (!SHFileOperation(&op) && !op.fAnyOperationsAborted)
	{
		SelectItem(parentitem);
		DeleteItem(item);
	}
	SetFocus();
	delete buffer;
}

void CDirTreeCtrl::OnLocaltreecontextRename() 
{
	HTREEITEM item=GetSelectedItem();
	if (!item)
		return;
	if (!GetParentItem(item) || !GetParentItem(GetParentItem(item)))
		return;
	EditLabel(item);
}

void CDirTreeCtrl::OnLocaltreecontextUpload() 
{
	HTREEITEM item;
	if (m_hDragSource)
		item = m_hDragSource;
	else
		item = GetSelectedItem();

	if (!item)
		return;
	if (!GetParentItem(item))
		return;
	CString path=GetFullPath(item);
	CMainFrame *pMainFrame=DYNAMIC_DOWNCAST(CMainFrame,GetParentFrame());
	
	path.TrimRight(_T("\\"));
	pMainFrame->UploadDir(path + "\\*.*", GetItemText(item) + "\\", TRUE, m_transferuser, m_transferpass);
	pMainFrame->TransferQueue(2);
}

void CDirTreeCtrl::OnLocaltreecontextUploadas() 
{
	CTransferAsDlg dlg;
	if (dlg.DoModal()==IDOK)
	{
		m_transferuser=dlg.m_User;
		m_transferpass=dlg.m_Pass;
		if (dlg.m_bTransferNow)
			OnLocaltreecontextUpload();
		else
			OnLocaltreecontextAddtoqueue();
	}
	m_transferuser="";
	m_transferpass="";
}

void CDirTreeCtrl::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) 
{
	*pResult = 0;

	NM_TREEVIEW *pNMTreeView = (NM_TREEVIEW *)pNMHDR;

	CMainFrame *pMainFrame = DYNAMIC_DOWNCAST(CMainFrame, GetParentFrame());

	HTREEITEM hItem = pNMTreeView->itemNew.hItem;
	if (!hItem)
		return;

	CString path = GetFullPath(hItem);
	if (path == "" || path == "\\")
		return;

	EnsureVisible(hItem);

	m_hDragSource = hItem;
	
	//Let the main window handle the rest
	pMainFrame->OnBegindrag(this, pNMTreeView->ptDrag);
}

BOOL CDirTreeCtrl::DragPosition(CImageList *pImageList, CWnd* pDragWnd, CPoint point)
{
	ScreenToClient(&point);
	HTREEITEM hItem = HitTest(point);

	if (pDragWnd == this && hItem)
	{
		CString dragPath = GetFullPath(m_hDragSource);
		CString path = GetFullPath(hItem);
		if (dragPath.GetLength() < path.GetLength() &&
			path.Left(dragPath.GetLength()) == dragPath)
		{
			DragLeave(pImageList);
			return FALSE;
		}
	}
	if (hItem)
	{
		if (hItem != m_hDragHilited)
		{
			pImageList->DragShowNolock(false);
			if (m_hDragHilited)
			{
				SetItemState(m_hDragHilited, 0, LVIS_DROPHILITED);
			}
			m_hDragHilited = hItem;
			SetItemState(hItem, TVIS_DROPHILITED, TVIS_DROPHILITED);
			UpdateWindow();
			pImageList->DragShowNolock(true);
		}
	}
	else
		DragLeave(pImageList);

	return TRUE;
}

void CDirTreeCtrl::DragLeave(CImageList *pImageList)
{
	if (!m_hDragHilited)
		return;

	if (pImageList)
		pImageList->DragShowNolock(false);
	SetItemState(m_hDragHilited, 0, TVIS_DROPHILITED);
	UpdateWindow();
	if (pImageList)
		pImageList->DragShowNolock(true);
	m_hDragHilited = NULL;
}

void CDirTreeCtrl::OnDragEnd(int target, CPoint point)
{
	m_transferuser = m_transferpass = "";
	if (target == 1)
		OnLocaltreecontextAddtoqueue();
	else if (!target)
		OnLocaltreecontextUpload();
	else if (target == 2 || target == 3)
	{
		CString to;
		if (target == 2)
		{
			if (!m_hDragHilited)
				return;
			if (m_hDragSource == m_hDragHilited)
				return;
			to = GetFullPath(m_hDragHilited);
		}
		else
		{
			CMainFrame *pMainFrame = DYNAMIC_DOWNCAST(CMainFrame, GetParentFrame());
			to = reinterpret_cast<CLocalFileListCtrl *>(pMainFrame->GetLocalPane2()->GetListCtrl())->GetDropTarget();
			if (to == "" || to == "\\")
				return;
		}


		CString from = GetFullPath(m_hDragSource);
		if (from.GetLength() < to.GetLength() &&
			to.Left(from.GetLength()) == from)
			return;

		from.TrimRight('\\');
		to.TrimRight('\\');
		
		if (to == "")
			return;

		LPTSTR pFrom = new TCHAR[from.GetLength() + 2];
		_tcscpy(pFrom, from);
		pFrom[from.GetLength() + 1] = 0;
		LPTSTR pTo = new TCHAR[to.GetLength() + 2];
		_tcscpy(pTo, to);
		pTo[to.GetLength() + 1] = 0;
		SHFILEOPSTRUCT op;
		op.hwnd = m_hWnd;
		op.wFunc = FO_MOVE;
		op.pFrom = pFrom;
		op.pTo = pTo;
		op.fFlags = 0;
		op.hNameMappings = NULL;
		op.lpszProgressTitle = NULL;
		
		SHFileOperation(&op);

		delete [] pFrom;
		delete [] pTo;

		RefreshDir(GetParentItem(m_hDragSource));
		if (target == 2)
			RefreshDir(m_hDragHilited);
		else
			RefreshDir(to);

		CMainFrame *pMainFrame = DYNAMIC_DOWNCAST(CMainFrame, GetParentFrame());
		CLocalFileListCtrl *pList = reinterpret_cast<CLocalFileListCtrl *>(pMainFrame->GetLocalPane2()->GetListCtrl());
		if (pList->GetFolder() == (to + "\\"))
			pList->SetFolder(to);

		int pos = from.ReverseFind('\\');
		if (pos < 2)
			return;
		from = from.Left(pos + 1);
		if (pList->GetFolder() == from)
			pList->SetFolder(from);
	}
}

CString CDirTreeCtrl::GetDropTarget() const
{
	return GetFullPath(m_hDragHilited);
}

// Struct for children list
// Unfortunately declared outside scope of RefreshDir due to linkage problems 
// (at least in VC++ 6)
struct t_children
{
	HTREEITEM hItem;
	CString text;
};

void CDirTreeCtrl::RefreshDir(HTREEITEM hRefreshItem)
{
	if (!hRefreshItem)
		return;

	CString path = GetFullPath(hRefreshItem);

	//
	// Displaying the Path in the TreeCtrl
	//
	CFileFind find;
	CString   strPathFiles = path;
	BOOL      bFind;
	std::vector<CString> strDirArray;
	
	if ( strPathFiles.Right(1) != "\\" )
		strPathFiles += "\\";
	strPathFiles += "*.*";

	bFind = find.FindFile( strPathFiles );

	while ( bFind )
	{
		bFind = find.FindNextFile();
		if ( find.IsDirectory() && !find.IsDots() )
		{		
			strDirArray.push_back( find.GetFilePath() );
		}
	}

	// Get children list which is already sorted
	std::vector<t_children> childrenArray;
	HTREEITEM hChildItem = GetChildItem(hRefreshItem);
	while (hChildItem)
	{
		t_children child;
		child.hItem = hChildItem;
		child.text = GetItemText(hChildItem);
		childrenArray.push_back(child);
		hChildItem = GetNextSiblingItem(hChildItem);
	}

	SortArray(strDirArray);
	
	SetRedraw(FALSE);
	CWaitCursor wait;
    
	// Search for new/deleted entries
	unsigned int j = 0;
	for (UINT i = 0; i < strDirArray.size(); i++)
	{
		CString subPath = GetSubPath(strDirArray[i]);
		int comp;
		if (j < childrenArray.size())
			comp = subPath.CollateNoCase(childrenArray[j].text);
		else
			comp = -1;
		if (!comp)
			j++;
		else if (comp < 0)
		{
			HTREEITEM hItem = AddItem( hRefreshItem, strDirArray[i] );
			if (FindSubDir(strDirArray[i]))
				InsertItem(_T(""), 0, 0, hItem);
		}
		else
		{
			i--;

			DeleteItem(childrenArray[j].hItem);
			j++;
		}
	}
	SortChildren(hRefreshItem);
    
	SetRedraw(TRUE);

}

void CDirTreeCtrl::RefreshDir(CString dir)
{
	if (dir == "")
		return;

	if (dir.Right(1) != _T("\\"))
		dir += "\\";
	
	HTREEITEM hParent = GetRootItem();
	while (dir != _T(""))
	{
		int pos = dir.Find(_T("\\"));
		if (pos == -1)
			return;

		CString sub = dir.Left(pos);
		dir = dir.Mid(pos + 1);

		HTREEITEM hItem = GetChildItem(hParent);
		while (hItem)
		{
			if (!GetItemText(hItem).CollateNoCase(sub))
			{
				hParent = hItem;
				break;
			}
			hItem = GetNextSiblingItem(hItem);
		}
		if (!hItem)
			return;
	}
	if (hParent != GetRootItem())
		RefreshDir(hParent);
}

⌨️ 快捷键说明

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