基于VC++的MFC类库实现的简单FTP客户端

YoungTime

发布日期: 2018-10-31 22:08:14 浏览量: 603
评分:
star star star star star star star star star_border star_border
*转载请注明来自write-bug.com

1 FTP客户端设计思想

在WINDOWS环境下,使用VC++开发工具实现一个FTP客户端软件。在本次FTP的设计中主要使用WinInet API编程,无需考虑基本的通信协议和底层的数据传输工作,MFC提供的WinInet类是对WinInet API函数封装而来的,它为用户提供了更加方便的编程接口。而在该设计中,使用的类包括 CInternetSession类、CFtpConnection类和CFtpFileFind类,其中,CInternetSession用于创建一个Internet会话; CftpConnection完成文件操作; CftpFileFind负责检索某一个目录下的所有文件和子目录。

程序的功能:

  • 登陆到FTP服务器

  • 检索FTP服务器上的目录和文件

  • 根据FTP服务器给的权限,会相应地提供:文件的上传、下载、重命名、删除等功能

2 Ftp客户端的各个子模块主要函数功能分析及流程图

2.1 对程序的外观进行修改

2.1.1 添加背景图

为CMyFtpView类窗口,添加一个位图背景显示,首先为CmyFtpView添加WM_ERASEBKGND消息响应函数OnEraseBkgnd。该函数的前提是所需的位图已经导入资源中。

2.1.2 添加时钟显示功能

首先为CMainFrame类,设置一个定时器,然后为该类响应WM_TIMER消息,在OnTimer函数中实现功能。

2.1.3 修改菜单栏、状态栏

在资料对话框或源程序代码中采取针对性的操作,得以实现。

2.2 连接到FTP服务器功能的实现

2.2.1 生成连接对话框

新建一个对话框(CConnectDlg)用来输入服务器的站点,用户名和密码信息,然后通过该对话框连接到服务器.主要的函数void CConnectDlg::OnConnect() 实现的功能就是更新当前的输入。

2.2.2 连接CMyFtpView::OnConnect()

该函数是菜单项“连接”的响应函数,主要生成“连接”CConnectDlg对话框,从而建立FTP连接。

2.2.3 连接时间void CMyFtpView::OnTimer

对CMyFtpView定时器,所发送的WM_TIMER消息进行响应,主要用于监视FTP连接是否成功连接。

2.3 FTP客户端文件的显示查询实现

2.3.1 查询函数OnQuary

该函数是“查询”按钮BN_CLICKED的响应函数,主要调用ListContent函数为实现查询的功能

2.3.2 显示当前目录下所有的子目录与文件ListContent

参数所代表的是要查询的目录名,实现的方法主要是通过CftpFileFind类对象得以实现,返回给用户的信息有:目录或文件名、文件最后修改的时间以及文件的大小和类型。

流程图如下所示:

2.3.3 下一级目录函数OnNextdirectory

该函数是“下一级目录”BN_CLICKED的响应函数,当用户选中一个子目录时,点击按纽就会进入该目录,调用了主要函数:GetCurrentDirectory 、SetCurrentDirectory、ListContent。

流程图如下所示:

2.3.4 上一级目录函数OnLasttdirectory

该函数是“上一级目录”BN_CLICKED的响应函数,点击按纽就会返回到该目录的上一级目录,调用了主要函数:GetCurrentDirectory 、SetCurrentDirectory、ListContent。

流程图如下所示:

2.4 FTP客户端部分功能实现

2.4.1 下载函数OnDownLoad

为了下载列表中的某一个文件,首先判断是否选中了项目,否则提示没有选择文件,然后得到选择的项目的类型是否是文件,,如果是文件,则得到下载的文件名,下载文件(调用CFtpConnect类中的GetFile函数下载文件)如果选中的是目录,则弹出对话框,不能下载目录。

流程图如下所示:

2.4.2 上传函数OnUpLoad

上传函数首先得获得想要上传的本地文件的路径名和文件名,弹出打开对话框,找到所要上传的文件后使用PutFile函数上传文件(调用CFtpConnect类中的PutFile函数),等函数上传完后提示是否上传成功,最后调用查询函数,显示新的文件列表。

流程图如下所示:

2.4.3 删除函数OnDelete

删除函数首先判断是否选择项目,如果没有,则弹出对话框没有选择文件。选择了项目后,得到选择项的类型,如果是目录,则提示不能删除目录,然后用m_pConnection->Remove删除文件并提示是否删除成功,最后调用查询函数,更新文件列表。

2.4.4 重命名函数OnRename:

重命名文件需要新建立一个对话框(CNewNameDlg),后选择要重命名的文件,没有选择项目,提示没有选择文件,激活控件后,弹出新建的对话框,输入新的文件名后用m_pConnection->Rename重新命名文件,最后调用查询函数,更新文件列表。

3 主要的数据结构分析

CMyFtpView类

  1. CConnectDlg m_ConDlg; //用于连接
  2. CFtpDlg m_FtpDlg; //用于创建一个CFtpDlg对话框,进行操作控制
  3. CString m_FtpWebSite; //服务器站点,用于输入服务器的站点名称或IP地址
  4. CString m_UserName; //登陆服务器的用户名称
  5. CString m_UserPwd; //登陆服务器的密码
  6. CInternetSession * m_pSession; //通过CConnectDlg 的设置,得到一个Internet会话
  7. CFtpConnection* m_pConnection; //通过m_pSession来实现一个FTP连接

CFtpDlg类

  1. CButton m_BtnQuery; //查询按扭
  2. CButton m_BtnUpLoad; //上传按扭
  3. CButton m_BtnDownLoad; //下载按扭
  4. CString m_NewFileName; //保存文件的新名称
  5. CListCtrl m_FtpFile; //用于显示目录和文件信息
  6. CFtpConnection* m_pConnection; //代表所建立的FTP连接
  7. CFtpFileFind* m_pFileFind; // CFtpFileFind指针,用于查找文件

4 Ftp客户端的各个子模块设计过程及代码分析

4.1 对程序的外观进行修改

4.1.1 删除工具栏

在CmainFrame的OnCreate函数中,删除与工具栏m_wndToolBar相关的代码,因为在本程序中没有提供相应的工具栏。

4.1.2 修改菜单

将原有的菜单项删除,增加“连接”和“退出客户端”子菜单项,(去掉Pop-up前的勾,同时赋以ID值),同时,为“连接”和“退出客户端”子菜单项添加COMMAND消息响应,响应的类分别为CMyFtpView类和CMainFrame类.响应函数为OnConnect和OnExit,其中:

OnExit函数代码如下:

  1. void CMainFrame::OnExit()
  2. {
  3. //退出程序的响应函数
  4. if(IDYES==MessageBox("确定要退出客户端吗?",
  5. "警告",MB_YESNO|MB_ICONWARNING))
  6. CFrameWnd::OnClose();
  7. }

4.1.3 添加位图背景

为CMyFtpView类窗口,添加一个位图背景显示,首先为CmyFtpView添加WM_ERASEBKGND消息响应函数,代码如下:

  1. //用于添加背景图
  2. BOOL CMyFtpView::OnEraseBkgnd(CDC* pDC)
  3. {
  4. CBitmap bitmap;
  5. //前提IDB_BITMAP2代表的位图已经导入资源中
  6. bitmap.LoadBitmap(IDB_BITMAP2);
  7. CDC dcCompatible;
  8. dcCompatible.CreateCompatibleDC(pDC);
  9. //创建与当前DC(pDC)兼容的DC,先用dcCompatible准备图像,再将数据复制到实际DC中
  10. dcCompatible.SelectObject(&bitmap);
  11. CRect rect;
  12. GetClientRect(&rect); //得到目的DC客户区大小
  13. BITMAP bmp; // BITMAP结构体,用于保存位图的信息
  14. bitmap.GetBitmap(&bmp);
  15. //将兼容DC中的位图Copy到目标DC中
  16. pDC->StretchBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0, bmp.bmWidth, bmp.bmHeight,SRCCOPY);
  17. return true;
  18. }

修改主窗口的大小,在PreCreateWindow函数中添加:cs.cx=450; cs.cy=550;

4.1.4 修改状态栏

使之只具有时间显示窗格,首先MainFrame.cpp中修改indicators,如下:

  1. static UINT indicators[] =
  2. {
  3. ID_SEPARATOR, // status line indicator
  4. IDS_TIMER,
  5. };

同时,在资源视图的String Table中添加字符串资源:IDS_TIMER,Caption为:时间。

然后,添加时钟显示功能:

  • 在CMainFrame的OnCreate中添加代码:SetTimer(1,1000,NULL)来设置一个定时器

  • 为CMainFrame添加WM_TIMER的响应函数,代码如下:

  1. void CMainFrame::OnTimer(UINT nIDEvent)
  2. {
  3. //用于在状态栏显示当前时间
  4. CTime t=CTime::GetCurrentTime();
  5. CString str=t.Format("%H:%M:%S");
  6. CClientDC dc(this);
  7. CSize sz=dc.GetTextExtent(str);//得到Str的长度,用于控制时间窗格
  8. m_wndStatusBar.SetPaneInfo(1,IDS_TIMER,SBPS_NORMAL,sz.cx);
  9. m_wndStatusBar.SetPaneText(1,str);//将当前时间显示在时间窗格中
  10. CFrameWnd::OnTimer(nIDEvent);
  11. }

4.1.5 改变应用程序窗口标题

标题改为“FTP客户端”在CmyFtpApp的InitInstance函数中添加代码:m_pMainWnd->SetWindowText(“FTP客户端”);

4.2 连接到FTP服务器功能的实现

4.2.1 插入一个对话框

对各控件进行变量设置(注:在IDC_EDIT3编辑框的Styles选项中,选中PassWord),如下图所示:

4.2.2 新建一个类管理对话框

在打开ClassWizard时,系统提示是否新建一个类管理对话框,选择“是”,类名为:CconnectDlg,基类为:CDialog。

4.2.3 CConnectDlg函数

对按钮“连接”的鼠标的点击,进行响应,函数如下:

  1. void CConnectDlg::OnConnect()
  2. {
  3. UpdateData();
  4. CDialog::OnOK();
  5. }

4.2.4 添加public成员变量

首先在CMyFtpView.h中添加public成员变量:

  1. CConnectDlg m_ConDlg; //管理连接对话框
  2. CFtpDlg m_FtpDlg; //管理CFtpDlg
  3. CString m_FtpWebSite; //保存Ftp服务器站点
  4. Cstring m_UserName; //保存用户名
  5. CString m_UserPwd; //保存用户密码
  6. CInternetSession* m_pSession; //用于Internet连接
  7. CFtpConnection* m_pConnection; //用于建立Ftp连接
  8. // 注: CFtpDlg为后建立的新类

并在构造函数中初如化:

  1. CMyFtpView::CMyFtpView()
  2. {
  3. m_FtpWebSite = _T("");
  4. m_UserName = _T("");
  5. m_UserPwd = _T("");
  6. m_pSession = NULL;
  7. m_pConnection = NULL;
  8. }

4.2.5 修改CMyFtpView类的OnConnect函数:

代码如下:

  1. void CMyFtpView::OnConnect()
  2. {
  3. //生成一个模态对话框
  4. if (IDOK==m_ConDlg.DoModal())
  5. {
  6. m_pConnection = NULL;
  7. m_pSession = NULL;
  8. m_FtpWebSite = m_ConDlg.m_FtpWebSite;
  9. m_UserName = m_ConDlg.m_UserName;
  10. m_UserPwd = m_ConDlg.m_UserPwd;
  11. m_pSession=new CInternetSession(AfxGetAppName(),
  12. 1,
  13. PRE_CONFIG_INTERNET_ACCESS);
  14. try
  15. {
  16. //试图建立FTP连接
  17. SetTimer(1,1000,NULL); //设置定时器,一秒发一次WM_TIMER
  18. CString str="正在连接中....";
  19. ((CMainFrame*)GetParent())->SetMessageText(str);
  20. m_pConnection=m_pSession->GetFtpConnection(m_FtpWebSite,
  21. m_UserName,m_UserPwd);
  22. }
  23. catch (CInternetException* e)
  24. {
  25. //错误处理
  26. e->Delete();
  27. m_pConnection=NULL;
  28. }
  29. }
  30. }

4.2.6 添加响应函数:

为CMyFtpView类添加WM_TIMER消息的响应函数,代码如下:

  1. void CMyFtpView::OnTimer(UINT nIDEvent)
  2. {
  3. static int time_out=1; //用于判断是否超时
  4. time_out++; //每秒增加一次
  5. if (m_pConnection == NULL)
  6. {
  7. CString str="正在连接中....";
  8. ((CMainFrame*)GetParent())->SetMessageText(str); //在状态栏中显示,连接状态
  9. if (time_out>=60) //设置超时的时间为1分钟
  10. {
  11. ((CMainFrame*)GetParent())->SetMessageText("连接超时!");
  12. KillTimer(1); //关闭定时器
  13. MessageBox("连接超时!","超时",MB_OK); //提醒用户
  14. }
  15. }
  16. else //如果连接成功,执行如下
  17. {
  18. CString str="连接成功!";
  19. ((CMainFrame*)GetParent())->SetMessageText(str);
  20. KillTimer(1);
  21. //连接成功之后,不用定时器来监视连接情况
  22. //同时跳出操作对话框
  23. //将FTP连接交给CFtpDlg
  24. m_FtpDlg.m_pConnection = m_pConnection;
  25. //创建非模态对话框CFtpDlg
  26. m_FtpDlg.Create(IDD_DIALOG2,this);
  27. m_FtpDlg.ShowWindow(SW_SHOW);
  28. }
  29. CView::OnTimer(nIDEvent);
  30. }

4.3 FTP客户端主要功能的实现

4.3.1新插入一个对话框资源:

新插入一个对话框资源,界面如下:

各控件变量信息如下图所示:

4.3.2 建立新类CFtpDlg管理该对话框

建立新类CFtpDlg管理该对话框,基类:CDialog。

构造函数代码:

  1. CFtpDlg::CFtpDlg(CWnd* pParent /*=NULL*/)
  2. : CDialog(CFtpDlg::IDD, pParent)
  3. {
  4. m_pConnection = NULL;
  5. m_pFileFind = NULL;
  6. }

4.3.3 初始化对话框

为CFtpDlg添加WM_INITDIALOG响应函数OnInitDialog,代码如下:

  1. BOOL CFtpDlg::OnInitDialog()
  2. {
  3. CDialog::OnInitDialog();
  4. //设置CListCtrl对象的属性
  5. m_FtpFile.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
  6. //设置列
  7. m_FtpFile.InsertColumn(0,"文件名",LVCFMT_CENTER,200);
  8. m_FtpFile.InsertColumn(1,"日期",LVCFMT_CENTER,100);
  9. m_FtpFile.InsertColumn(2,"字节数",LVCFMT_CENTER,100);
  10. //初如化CftpFileFind类对象m_pFileFind
  11. m_pFileFind = new CFtpFileFind(m_pConnection);
  12. //调用OnQuary函数查询FTP服务器当前目录下的目录和文件信息
  13. OnQuary();
  14. return TRUE;
  15. }

4.3.4 查询函数OnQuary

为查询按纽添加BN_CLICKED响应函数OnQuary,代码如下:

  1. void CFtpDlg::OnQuary()
  2. {
  3. ListContent("*");
  4. }

手动为CFtpDlg添加函数ListContent:

  1. void CFtpDlg::ListContent(LPCTSTR DirName)
  2. {
  3. m_FtpFile.DeleteAllItems();
  4. BOOL bContinue;
  5. bContinue=m_pFileFind->FindFile(DirName);
  6. if (!bContinue)
  7. {
  8. //查找完毕,失败
  9. m_pFileFind->Close();
  10. m_pFileFind=NULL;
  11. }
  12. CString strFileName;
  13. CString strFileTime;
  14. CString strFileLength;
  15. while (bContinue)
  16. {
  17. bContinue = m_pFileFind->FindNextFile();
  18. strFileName = m_pFileFind->GetFileName(); //得到文件名
  19. //得到文件最后一次修改的时间
  20. FILETIME ft;
  21. m_pFileFind->GetLastWriteTime(&ft);
  22. CTime FileTime(ft);
  23. strFileTime = FileTime.Format("%y/%m/%d");
  24. if (m_pFileFind->IsDirectory())
  25. {
  26. //如果是目录不求大小,用<DIR>代替
  27. strFileLength = "<DIR>";
  28. }
  29. else
  30. {
  31. //得到文件大小
  32. if (m_pFileFind->GetLength64() <1024)
  33. {
  34. strFileLength.Format("%d B",m_pFileFind->GetLength64());
  35. }
  36. else
  37. {
  38. if (m_pFileFind->GetLength64() < (1024*1024))
  39. strFileLength.Format("%3.3f KB",
  40. (LONGLONG)m_pFileFind->GetLength64()/1024.0);
  41. else
  42. {
  43. if (m_pFileFind->GetLength64()<(1024*1024*1024))
  44. strFileLength.Format("%3.3f MB", (LONGLONG)m_pFileFind->GetLength64()/(1024*1024.0));
  45. else
  46. strFileLength.Format("%1.3f GB", (LONGLONG)m_pFileFind->GetLength64()/(1024.0*1024*1024));
  47. }
  48. }
  49. }
  50. int i=0;
  51. m_FtpFile.InsertItem(i,strFileName,0);
  52. m_FtpFile.SetItemText(i,1,strFileTime);
  53. m_FtpFile.SetItemText(i,2,strFileLength);
  54. i++;
  55. }
  56. }

4.3.5 下一级目录函数OnNextdirectory

为”下一级目录”按纽添加BN_CLICKED响应函数OnNextdirectory,代码如下:

  1. void CFtpDlg::OnNextdirectory()
  2. {
  3. static CString strCurrentDirectory, strSub; //声明2个静态变量,
  4. // strCurrentDirectory表示当前目录名,strSub表示选定的文件名
  5. //首先得到当前目录,保存在strCurrentDirectory
  6. m_pConnection->GetCurrentDirectory(strCurrentDirectory);
  7. strCurrentDirectory+="/"; //在当前取得的目录名后添加“/”
  8. //得到所选择的文本,即所要进入的下一级目录名
  9. int i=m_FtpFile.GetNextItem(-1,LVNI_SELECTED); //判断文件是否选中
  10. strSub = m_FtpFile.GetItemText(i,0);//将选中的文件名保存至strSub
  11. if (i==-1)
  12. {
  13. AfxMessageBox("没有选择目录!",MB_OK | MB_ICONQUESTION);
  14. }
  15. else
  16. { //判断是不是目录
  17. if ("<DIR>"!=m_FtpFile.GetItemText(i,2))//显示文件的第三列非<DIR>
  18. {
  19. AfxMessageBox("不是子目录!",MB_OK | MB_ICONSTOP);
  20. }
  21. else
  22. {
  23. //设置当前目录
  24. m_pConnection->SetCurrentDirectory(strCurrentDirectory+strSub);
  25. //对当前目录进行查询,更新ClistCtrl控件的内容
  26. ListContent("*");
  27. }
  28. }
  29. }

4.3.6 上一级目录函数OnLasttdirectory

为”上一级目录”按纽添加BN_CLICKED响应函数OnLastdirectory,代码如下:

  1. //返回上一级目录
  2. void CFtpDlg::OnLastdirectory()
  3. {
  4. static CString strCurrentDirectory; //声明为静态变量
  5. m_pConnection->GetCurrentDirectory(strCurrentDirectory);
  6. if (strCurrentDirectory == "/")
  7. {
  8. AfxMessageBox("已经是根目录了!",MB_OK | MB_ICONSTOP);
  9. }
  10. else
  11. {
  12. //调用函数GetLastDiretory,得到上一级目录名
  13. GetLastDiretory(strCurrentDirectory);
  14. //设置当前目录为上一级目录
  15. m_pConnection->SetCurrentDirectory(strCurrentDirectory);
  16. //对当前目录进行查询,更新ClistCtrl控件的内容
  17. ListContent("*");
  18. }
  19. }

为CFtpDlg类添加一工具函数GetLastDiretory用于得到上一级目录的名称。

  1. //用于得到上一级目录的字符串表示
  2. void CFtpDlg::GetLastDiretory(CString &str)
  3. {
  4. int LastIndex=0;//定义一个初始整形变量
  5. for (int i=0; i<str.GetLength(); i++)//定义i取得当前地址字符串长度
  6. {
  7. if (str.GetAt(i)=='/')//追溯至数组的最后一个“/”
  8. LastIndex = i;//得到当前的数值“i”
  9. }
  10. //删除最后一个’/’之后的字符串
  11. str = str.Left(LastIndex);//自带的left()函数:返回参数前的所有字符串
  12. if (LastIndex == 0)//当追溯的本身即为根目录
  13. str="/";
  14. }

4.4 FTP客户端部分功能的实现

4.4.1 下载函数OnDownLoad

为”下载”按纽添加BN_CLICKED响应函数OnDownLoad,代码如下:

  1. void CFtpDlg::OnDownload()
  2. {
  3. int i=m_FtpFile.GetNextItem(-1,LVNI_SELECTED);
  4. //先判断是否已经选中文件
  5. if (i==-1) //如果没有被选中
  6. {
  7. //弹出对话框提示没有选择文件
  8. AfxMessageBox("没有选择文件!",MB_OK | MB_ICONQUESTION);
  9. }
  10. else
  11. {
  12. //如果选中了文件,则得到选择项的类型,判断是不是文件
  13. CString strType=m_FtpFile.GetItemText(i,2);
  14. if (strType!="<DIR>") //选择的是文件
  15. {
  16. CString strDestName; //下载后的文件名
  17. CString strSourceName; //原文件名
  18. //得到所要下载的文件名
  19. strSourceName = m_FtpFile.GetItemText(i,0);
  20. CFileDialog dlg(FALSE,"",strSourceName);
  21. //弹出SAVE AS对话框
  22. if (dlg.DoModal()==IDOK)
  23. {
  24. //获得下载文件在本地机上存储的路径和名称
  25. strDestName=dlg.GetPathName();
  26. //调用CFtpConnect类中的GetFile函数下载文件
  27. if (m_pConnection->GetFile(strSourceName,strDestName))
  28. AfxMessageBox("下载成功!",MB_OK|MB_ICONINFORMATION);
  29. else
  30. AfxMessageBox("下载失败!",MB_OK|MB_ICONSTOP);
  31. }
  32. }
  33. else
  34. {
  35. //选择的是目录
  36. AfxMessageBox("不能下载目录!\n请重选!",MB_OK|MB_ICONSTOP);
  37. }
  38. }
  39. }

4.4.2 上传函数OnUpLoad

为”上传”按纽添加BN_CLICKED响应函数OnUpload,代码如下:

  1. void CFtpDlg::OnUpload()
  2. {
  3. //获得当前输入
  4. CString strSourceName; //原文件名
  5. CString strDestName;
  6. CFileDialog dlg(TRUE,"","*.*");
  7. if (dlg.DoModal()==IDOK)
  8. {
  9. //获得待上传的本地机文件路径和文件名
  10. strSourceName = dlg.GetPathName();
  11. strDestName = dlg.GetFileName();
  12. //调用CFtpConnect类中的PutFile函数上传文件
  13. if (m_pConnection->PutFile(strSourceName,strDestName))
  14. AfxMessageBox("上传成功!",MB_OK|MB_ICONINFORMATION);
  15. else
  16. AfxMessageBox("上传失败!",MB_OK|MB_ICONSTOP);
  17. }
  18. //更新ClistCtrl的内容
  19. OnQuary();
  20. }

4.4.3 删除函数OnDelete

为”删除”按纽添加BN_CLICKED响应函数OnDelete,代码如下:

  1. //删除选择的文件
  2. void CFtpDlg::OnDelete()
  3. {
  4. int i=m_FtpFile.GetNextItem(-1,LVNI_SELECTED);
  5. if (i==-1)
  6. {
  7. AfxMessageBox("没有选择文件!",MB_OK | MB_ICONQUESTION);
  8. }
  9. else
  10. {
  11. CString strFileName;
  12. strFileName = m_FtpFile.GetItemText(i,0);
  13. if ("<DIR>"==m_FtpFile.GetItemText(i,2))
  14. {
  15. AfxMessageBox("不能删除目录!",MB_OK | MB_ICONSTOP);
  16. }
  17. else
  18. {
  19. if (m_pConnection->Remove(strFileName))
  20. AfxMessageBox("删除成功!",MB_OK|MB_ICONINFORMATION);
  21. else
  22. AfxMessageBox("无法删除!",MB_OK|MB_ICONSTOP);
  23. }
  24. }
  25. OnQuary();
  26. }

4.4.4 重命名函数OnRename

新插入一个对话框资源,界面如下:

控件变量信息如下图所示:

改写对话框的OnOK函数,代码如下:

  1. void CNewNameDlg::OnOK()
  2. {
  3. UpdateData();
  4. CDialog::OnOK();
  5. }

为”重命名”按纽添加BN_CLICKED响应函数OnRename,代码如下:

  1. void CFtpDlg::OnRename()
  2. {
  3. CString strNewName;
  4. CString strOldName;
  5. //得到CListCtrl被选中的项
  6. int i=m_FtpFile.GetNextItem(-1,LVNI_SELECTED);
  7. if (i==-1)
  8. {
  9. AfxMessageBox("没有选择文件!",MB_OK | MB_ICONQUESTION);
  10. }
  11. else
  12. {
  13. strOldName = m_FtpFile.GetItemText(i,0);//得到所选择的文件名
  14. CNewNameDlg dlg;
  15. if (dlg.DoModal()==IDOK)
  16. {
  17. strNewName=dlg.m_NewFileName;
  18. if (m_pConnection->Rename(strOldName,strNewName))
  19. AfxMessageBox("重命名成功!",MB_OK|MB_ICONINFORMATION);
  20. else
  21. AfxMessageBox("无法重命名!",MB_OK|MB_ICONSTOP);
  22. }
  23. }
  24. OnQuary();
  25. }

4.4.5 退出函数OnExit

为”退出”按纽添加BN_CLICKED响应函数OnExit,代码如下:

  1. void CFtpDlg::OnExit()
  2. {
  3. m_pConnection = NULL;
  4. m_pFileFind = NULL;
  5. DestroyWindow(); //销毁对话框资源
  6. }

5 测试程序

5.1 连接操作

5.2 连接成功后

此后可根据FTP服务器所提供的权限进行相应的操作。

6 整个设计过程中遇到的主要问题

6.1 如果已经连上了某服务器,而在没有退出程序之前,再点连接,就会有问题了

  • 原因

    CFtpDlg在调用OnExit函数的时候仅仅是隐藏了对话框,并没有销毁它,导致了m_FtpDlg的重复创建m_FtpDlg.Create(IDD_DIALOG2,this);此行代码是问题关键,点退出时,并没有销费

  • 解决之道

    OnExit函数中调用DestryWindow,而不是CDialg::OnCancel;

6.2 在进入下一级目录的函数编写过程中,只能进入第二层目录

  • 原因

    假设当前目录为 “/”,进入第一层子目录”FTP”之后,当前目录变为“/FTP”,再想进入FTP目录下的”MyFtp”子目录的时候,之前的代码,仅仅是实现了“/FTP”+”MyFtp”简单加法,即当前目录为”/FTPMyFtp”,虽然是不对的。

  • 解决之道

    在获取子目录名称之前,使当前目录所代表的字符串加上符号‘/’ ,代码表示为:

  1. strCurrentDirectory+="/";

6.3 在返回上一级目录的函数编写过程中,无法返回到根目录

  • 原因

    比如:在”/FTP”之下,返回到上一级目录,原代码将导致当前目录strCurrentDirectory为空,如果运行m_pConnection->SetCurrentDirectory(strCurrentDirectory),显然也是不对的

  • 解决之道

    在GetLastDiretory中添加判断:当前目录是否为空,如果是,则设strCurrentDirectory=”/”;代码实现为:

  1. if (LastIndex == 0)
  2. str="/";

7 总结

在这次课程设计中,我们小组通过从各个方面查找资料,了解了WinInet API编程的基本知识,熟悉了MFC编程中的一些控件知识,通过这次设计锻炼了我们组员的团队协作能力。

通过对FTP这种大型的设计,我们组成员深感我们平时的编程习惯与良好的编程习惯相差甚远,小组成员决定在以后的编程过程中养成良好的编程习惯,这样有助于自己所编的程序清晰明了便于该错还有助于别人来立解你的程序。同时通过这次课程设计我们形成了通过从各方面查找资料来丰富自己的知识的能力。

上传的附件 cloud_download 基于VC++的MFC类库实现的简单FTP客户端.7z ( 44.79mb, 24次下载 )
error_outline 下载需要10点积分

keyboard_arrow_left上一篇 : 基于SSM的网上购物系统的设计与开发 基于Android的网络聊天软件的设计与实现 : 下一篇keyboard_arrow_right



YoungTime
2018-10-31 22:11:28
使用MFC实现的一个FTP客户端软件
DJming
2019-05-15 14:47:23
LINK : fatal error LNK1104: cannot open file "Release/MyFtp.exe"出现这种错误怎么版呀

发送私信

最合适你的人,是不需要奔跑着去追赶,拼了命去靠近的

5
文章数
9
评论数
eject