📄 ftptreedlg.cpp
字号:
// FTPTREEDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "FTPTREE.h"
#include "FTPTREEDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// 对话框数据
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CFTPTREEDlg 对话框
CFTPTREEDlg::CFTPTREEDlg(CWnd* pParent /*=NULL*/)
: CDialog(CFTPTREEDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
CFTPTREEDlg::~CFTPTREEDlg()
{
// clean up any objets that are still lying around
if (m_pConn != NULL)
{
m_pConn->Close();
delete m_pConn;
}
if (m_pIS != NULL)
{
m_pIS->Close();
delete m_pIS;
}
}
void CFTPTREEDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_FTPSITE, m_comboWebSite);
DDX_Control(pDX, IDC_FTPTREE, m_TreeCtl);
}
BEGIN_MESSAGE_MAP(CFTPTREEDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(ID_BROWSE_SITE, OnBnClickedBrowseSite)
ON_WM_GETMINMAXINFO()
ON_WM_SIZE()
ON_NOTIFY(TVN_ITEMEXPANDING, IDC_FTPTREE, OnTvnItemexpandingFtptree)
ON_WM_DESTROY()
END_MESSAGE_MAP()
// CFTPTREEDlg 消息处理程序
BOOL CFTPTREEDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 将\“关于...\”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO:在此添加额外的初始化代码
CRect rect;
GetWindowRect(rect);
m_OrigSize.cx = rect.Width();
m_OrigSize.cy = rect.Height();
// 初始化变量m_pFtpConnection
m_pConn = NULL;
CString str;
if (!str.LoadString(IDS_APPNAME))
str = _T("AppUnknown");
//创建Internet会话,直到对话框关闭
m_pIS = new CInternetSession(str, 1, PRE_CONFIG_INTERNET_ACCESS);
// 如果会话创建失败,提示并关闭程序
if (!m_pIS)
{
AfxMessageBox(IDS_BAD_SESSION, MB_OK);
OnCancel();
}
//添加目录树控件中使用的位图资源
CImageList* pImageList = new CImageList();
pImageList->Create(16, 15, TRUE, 3, 2);
CBitmap bitmap;
for (UINT iCnt=IDB_BITMAP1; iCnt<=IDB_BITMAP3; iCnt++)
{
bitmap.LoadBitmap(iCnt);
pImageList->Add(&bitmap, (COLORREF)0xFFFFFF);
bitmap.DeleteObject();
}
m_TreeCtl.SetImageList(pImageList, TVSIL_NORMAL);
//初始化目录树控件
PopulateTree();
//初始化组合框,因为在属性设置时为组合框添加两个默认值,在这里显示第一个默认值
m_comboWebSite.GetLBText(0, str);
m_comboWebSite.SetWindowText(str);
return TRUE;
}
void CFTPTREEDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// 如果向对话框添加最小化按钮,则需要下面的代码来绘制该图标。
// 对于使用文档/视图模型的 MFC 应用程序,这将由框架自动完成。
void CFTPTREEDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标显示。
HCURSOR CFTPTREEDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CFTPTREEDlg::OnBnClickedBrowseSite()
{
// TODO:在此添加控件通知处理程序代码
CString strFtpSite;
CString strServerName;
CString strObject;
INTERNET_PORT nPort;
DWORD dwServiceType;
//假如FTP连接已经建立则首先关闭该连接
if (m_pConn != NULL)
m_pConn->Close();
delete m_pConn;
m_pConn = NULL;
m_comboWebSite.GetWindowText(strFtpSite);
//更新组合框,并使最近使用的URL处于最顶端
int nListCount = m_comboWebSite.GetCount();
CString strTemp;
while (nListCount > 0)
{
m_comboWebSite.GetLBText(--nListCount, strTemp);
if (strFtpSite.Compare(strTemp) == 0)
{
m_comboWebSite.DeleteString(nListCount);
nListCount = 0;
}
}
m_comboWebSite.InsertString(0, strFtpSite);
//组合框最多可以有5项
if (m_comboWebSite.GetCount() > 5)
{
m_comboWebSite.DeleteString(5);
}
// 检查URL的合法性 --
if (!AfxParseURL(strFtpSite, dwServiceType, strServerName, strObject, nPort))
{
CString strFtpURL = _T("ftp://");
strFtpURL += strFtpSite;
if (!AfxParseURL(strFtpURL, dwServiceType, strServerName, strObject, nPort))
{
AfxMessageBox(IDS_INVALID_URL, MB_OK);
PopulateTree();
return;
}
}
CWaitCursor cursor; // 显示等待光标
// 替换组合框中的URL地址显示
m_comboWebSite.SetWindowText(strFtpSite);
m_comboWebSite.SetEditSel(-1,-1);
// 现在建立一个匿名FTP连接
if ((dwServiceType == INTERNET_SERVICE_FTP) && !strServerName.IsEmpty())
{
try
{
m_pConn = m_pIS->GetFtpConnection(strServerName);
}
catch (CInternetException* pEx)
{
// 出现异常,提示用户
TCHAR szErr[1024];
if (pEx->GetErrorMessage(szErr, 1024))
AfxMessageBox(szErr, MB_OK);
else
AfxMessageBox(IDS_EXCEPTION, MB_OK);
pEx->Delete();
m_pConn = NULL;
}
}
else
{
AfxMessageBox(IDS_INVALID_URL, MB_OK);
}
// 如果FTP连接创建成功,则显示根目录结构,否则在目录树控件中显示错误信息。
if (m_pConn != NULL)
{
PopulateTree(m_pConn, strObject);
}
else
{
PopulateTree();
}
}
void CFTPTREEDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
// TODO:在此添加消息处理程序代码和/或调用默认值
CDialog::OnGetMinMaxInfo(lpMMI);
static BOOL bSetSize;
if (bSetSize)
{
lpMMI->ptMinTrackSize.x = m_OrigSize.cx;
lpMMI->ptMinTrackSize.y = m_OrigSize.cy;
}
else
{
bSetSize = TRUE;
}
}
void CFTPTREEDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
// TODO:在此添加消息处理程序代码
// resize the tree control to appropriately match the new size
if ((cx > 0) && (cy > 0))
{
CRect rect;
if (m_TreeCtl.m_hWnd != NULL)
{
m_TreeCtl.GetWindowRect(rect);
ScreenToClient(rect);
m_TreeCtl.MoveWindow(rect.left, rect.top,
cx-(2*rect.left), cy-rect.top-rect.left);
}
}
}
void CFTPTREEDlg::OnTvnItemexpandingFtptree(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
//在MFC消息映射中,定义了统一的格式NMHDR来发送附加数据,
//随同消息传递到相应的消息处理函数;将系统定义的NMHDR型
//参数pNMHDR强制赋值给NM_TREEVIEW型变量pNMTreeView;
// 寻找被展开的项
if (pNMTreeView->hdr.code == TVN_ITEMEXPANDING)
{
HTREEITEM hIT = pNMTreeView->itemNew.hItem;
CString cstr, strPath;
// 创建htreeitem路径
strPath = m_TreeCtl.GetItemText(hIT);
while (hIT != m_TreeCtl.GetRootItem())
{
hIT = m_TreeCtl.GetParentItem(hIT);
if (hIT == m_TreeCtl.GetRootItem())
cstr.Format(_T("/%s"), (LPCTSTR)strPath);
else
cstr.Format(_T("%s/%s"), (LPCTSTR)m_TreeCtl.GetItemText(hIT), (LPCTSTR)strPath);
strPath = cstr;
}
// 调用函数ExploreDir
ExploreDir(strPath, pNMTreeView->itemNew.hItem);
}
*pResult = 0;
}
void CFTPTREEDlg::PopulateTree(CFtpConnection* pConn, const CString& strDir)
{
CWaitCursor cursor; // 显示等待光标
// 删除控件中所有内容
m_TreeCtl.DeleteAllItems();
// 如果FTP连接为NULL,显示错误信息
if (!pConn)
{
//改变控件类型
ModifyStyle(TVS_LINESATROOT, 0);
TV_INSERTSTRUCT tvstruct;
tvstruct.hParent = NULL;
tvstruct.hInsertAfter = TVI_FIRST;
tvstruct.item.iImage = 0;
tvstruct.item.iSelectedImage = 0;
tvstruct.item.pszText = _T("未创建与FTP服务器的连接!");
tvstruct.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
m_TreeCtl.InsertItem(&tvstruct);
m_pConn = NULL;
}
else
{
m_pConn = pConn;
CString cstr = _T("/");
//将根目录插入树状结构
TV_INSERTSTRUCT tvstruct;
tvstruct.hParent = NULL;
tvstruct.hInsertAfter = TVI_LAST;
tvstruct.item.iImage = 1;
tvstruct.item.iSelectedImage = 1;
tvstruct.item.pszText = _T("/");
tvstruct.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
HTREEITEM hThisItem = m_TreeCtl.InsertItem(&tvstruct);
// 根目录需要调用Expand()展开子项
// Expand() will call ExploreDir() to find the root's real children
tvstruct.hParent = hThisItem;
m_TreeCtl.InsertItem(&tvstruct);
m_TreeCtl.Expand(m_TreeCtl.GetRootItem(), TVE_EXPAND);
//如果没有子项,取消TVS_LINESATROOT风格
if (!m_TreeCtl.ItemHasChildren(m_TreeCtl.GetRootItem()))
{
ModifyStyle(TVS_LINESATROOT, 0);
return;
}
// 如果有子项,则设置TVS_LINESATROOT风格
ModifyStyle(0, TVS_LINESATROOT);
if (!strDir)
return;
//只要有子项就反复展开
int nIndex;
CString strTemp;
CString strSrc = strDir;
HTREEITEM hTI = m_TreeCtl.GetRootItem();
while (!strSrc.IsEmpty())
{
nIndex = strSrc.Find(_T("/"));
if (nIndex < 0)
{
cstr = strSrc;
strSrc.Empty();
}
else if (nIndex > 0)
{ // 跟踪没有列出的目录
cstr = strSrc.Left(nIndex);
strTemp = strSrc.Right(strSrc.GetLength() - (nIndex+1));
strSrc = strTemp;
}
if(!cstr.IsEmpty() && (nIndex != 0))
{
// 检查CStr是文件还是目录
hTI = m_TreeCtl.GetChildItem(hTI);
while ((hTI != NULL) && (cstr != m_TreeCtl.GetItemText(hTI)))
{
hTI = m_TreeCtl.GetNextItem(hTI, TVGN_NEXT);
}
if ((hTI != NULL) && (cstr == m_TreeCtl.GetItemText(hTI)))
{
if (m_TreeCtl.ItemHasChildren(hTI))
m_TreeCtl.Expand(hTI, TVE_EXPAND);
else
{
m_TreeCtl.SelectItem(hTI);
TV_ITEM tv;
tv.hItem = hTI;
tv.mask = TVIF_HANDLE | TVIF_STATE;
tv.stateMask = TVIS_BOLD;
if (m_TreeCtl.GetItem(&tv))
{
tv.mask = TVIF_HANDLE | TVIF_STATE;
tv.stateMask = TVIS_BOLD;
tv.state = TVIS_BOLD;
m_TreeCtl.SetItem(&tv);
}
strSrc.Empty();
}
}
else strSrc.Empty();
}
else // nIndex == 0
{
strTemp = strSrc.Right(strSrc.GetLength() - 1);
strSrc = strTemp;
}
} // 结束展开
}
}
void CFTPTREEDlg::ExploreDir(const CString& strDir, HTREEITEM hParent)
{
TV_INSERTSTRUCT tvstruct;
CString strSearchDir;
//删除该目录中所有的子项
HTREEITEM hIT = m_TreeCtl.GetChildItem(hParent);
HTREEITEM hTemp;
while (hIT != NULL)
{ hTemp = m_TreeCtl.GetNextSiblingItem(hIT);
m_TreeCtl.DeleteItem(hIT);
hIT = hTemp;
}
// 查找该目录中所有的文件
if (hParent != m_TreeCtl.GetRootItem())
{
strSearchDir = strDir + _T("/*");
}
else
{
strSearchDir = _T("/*");
}
//声明CftpFileFind类变量ftpFind;
CFtpFileFind ftpFind(m_pConn);
//查找文件
BOOL bContinue = ftpFind.FindFile(strSearchDir);
if (!bContinue)
{
// 如果目录为空,关闭文件
ftpFind.Close();
return;
}
BOOL bDir = FALSE;
HTREEITEM hThisItem;
CString strFileName;
while (bContinue) // 为目录中每一项设置并插入一个tvstruct
{ // 继续查找
bContinue = ftpFind.FindNextFile();
strFileName = ftpFind.GetFileName();
if (ftpFind.IsDirectory())
{ // 找到一个目录
bDir = TRUE;
tvstruct.item.iImage = 1;
tvstruct.item.iSelectedImage = 1;
}
else
{
tvstruct.item.iImage = 2;
tvstruct.item.iSelectedImage = 2;
}
tvstruct.hParent = hParent;
tvstruct.hInsertAfter = TVI_LAST;
tvstruct.item.pszText = (LPTSTR)(LPCTSTR)strFileName; // 返回一个CString
tvstruct.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
hThisItem = m_TreeCtl.InsertItem(&tvstruct);
}
ftpFind.Close();
// 如果找到非空目录,则创建一个临时子项
if (bDir)
{
CFtpFileFind* pTempFtpFind = NULL;
CString strFullSearchPath;
int nImage, nSelectedImage;
hThisItem = m_TreeCtl.GetChildItem(hParent);
while (hThisItem != NULL)
{
m_TreeCtl.GetItemImage(hThisItem, nImage, nSelectedImage);
if (nImage == 1) //为目录
{
strFileName = m_TreeCtl.GetItemText(hThisItem);
// 创建完整的路径
strFullSearchPath = strDir + _T("/") + strFileName + _T("/*");
pTempFtpFind = new CFtpFileFind(m_pConn);
if (pTempFtpFind->FindFile(strFullSearchPath))
{
tvstruct.hParent = hThisItem;
tvstruct.hInsertAfter = TVI_LAST;
tvstruct.item.iImage = 1;
tvstruct.item.iSelectedImage = 1;
tvstruct.item.pszText = _T("1");;
tvstruct.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
m_TreeCtl.InsertItem(&tvstruct);
}
pTempFtpFind->Close();
delete pTempFtpFind;
}
hThisItem = m_TreeCtl.GetNextSiblingItem(hThisItem);
}
}
return;
}
void CFTPTREEDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: 在此添加消息处理程序代码
CImageList *pimagelist;
pimagelist = m_TreeCtl.GetImageList(TVSIL_NORMAL);
pimagelist->DeleteImageList();
delete pimagelist;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -