VisualC++网络编程案例实战之FTP客户端实现之二.ppt
第5章 FTP客户端实现之二前面的章节4实现过一个FTP客户端程序,那么为什么这里又要实现呢?区别有二,FTP客户端所基于的应用程序框架不同,第4章基于对话框,本章将基于SDI开发;开发时的精力分配不同,第4章的精力主要集中在与FTP服务器的“交流”上,本章将把这种底层的工作交给MFC封装的类来实现,主要精力会集中在界面的美化上。5.1 FTP客户端简介这节将会带领大家快速了解下本章将要实现的FTP客户端的各种功能。包括:以树形视图浏览本地文件夹资源、列表方式显示FTP服务器上的文件资源、用过拖动文件的方式实现文件的上传和下载。5.1.1 树形结构的应用在主窗体的左侧视图中显示选定本地文件夹内的所有文件资源,结构为树形,可以动态的改变本地文件夹的选择,如图5.1所示。前方有加号说明路径中还有子路径,单击加号打开此路径,加号变减号,子文件将显示在子树中。鼠标移过此视图时树子项会加亮显示。图标H表示文件夹、图标F表示文件。图5.1.本地文件夹资源显示5.1.2 列表结构的应用在主窗体的右侧视图中,将以列表图标的形式显示FTP服务器下的所有文件资源,如图5.2所示。图5.2 FTP服务器上文件资源5.1.3 信息框的应用在主窗体的正中央有个信息的显示框,是用于描述用户的一些操作,如图5.3所示。图5.3 信息显示框5.1.4 浮动对话框的应用主程序的最顶端是用来填写本地文件夹路径和连接FTP服务器的浮动对话框,如图5.4所示。图5.4 浮动对话框那么,最后来看一下本章FTP客户端的全貌吧,如图5.5所示。图5.5 FTP客户端全貌5.2 关键技术讲解这节主要介绍本章要用到的所有关键技术,包括如何制作浮动对话框,然后像工具栏一样加到菜单之下;如何将客户区分栏;如何实现对树形和列表视图项目的拖动。我们创建的工程是基于SDI的,命名为FtpClient。在向导的第6步,我们选择CFtpClientView基于CListView类,如图5.6所示。图5.6 修改CFtpClientView的基类5.2.1 制作、使用浮动对话框浮动对话框,顾名思义就是可以浮动在主窗体之上。制作方法如下:(1)在资源视图中插入对话框资源,修改ID为IDD_FLOAT_DLG,修改属性:去掉对话框的边缘,将style改为child,如图5.7所示。图5.7 对话框属性设置(2)为对话框拖放控件,然后进行设计,怎么好看怎么摆放吧!我的设计如图5.8所示。你们在前面见过了,但还是想让大家看看,因为我增加了新内容。图5.8 浮动对话框界面设计(3)在CMainFrame中添加一个浮动对话框的变量m_myDlg。在CMainFrame的OnCreate()成员函数中完成两个任务:去掉由向导为我们添加的工具栏和状态栏,它们影响到了我们程序的美观;添加显示我们刚才设计的对话框的代码。程序中去掉了工具栏和状态栏的功能,所以你可以将代表两个工具的对象m_wndStatusBar、m_wndToolBar也注释掉,它们就定义在类CMainFrame的头文件中,如下:不注释掉也并不会影响程序的编译执行,读者可自由处理。通过调用类CDialogBar的成员函数Create(),装载我们设计的对话框资源模版、创建对话框窗口、设置它的样式,最后关联窗口到CDialogBar对象m_myDlg上。函数原型如下:virtual BOOL Create(CWnd*pParentWnd,UINT nIDTemplate,UINT nStyle,UINT nID);参数含义如下:pParentWnd:指向装载浮动对话框的父窗口的指针,我们直接使用了this。其它成员函数如EnableDocking()的使用很简单,代码中已经加入了注释,就不做详解讲解了。那么,编译运行程序就会发现工具栏、状态栏消失了,取而代之的是我们自己设计的浮动对话框,用鼠标尝试拖动它,会有如图5.9所示效果。图5.9 拖动浮动对话框你当然可以任意移动它,甚至是单击它上面的关闭按钮来关闭它,不过关闭了以后就比较麻烦了,因为我们需要重新启动程序来让它再次显示。本程序没有实现再次显示浮动窗口功能,读者可以自己实现下。5.2.2 客户区的分割我们需要将整个客户区分割为3个部分:用于显示用户操作的信息窗口、用于显示本地文件夹资源的树形视图窗口和用于显示FTP服务器上文件资源的列表视图窗口。效果如图5.10所示。图5.10 窗口分割效果图为类CMainFrame添加两个成员变量,如下:类CSplitterWnd提供了分割窗口的功能,就是一个窗口包含多个窗格。为类CMainFrame添加虚函数OnCreateClient()的实现,程序编写如下:调用类CSplitterWnd的成员函数CreateStatic()创建静态的分割窗口,函数原型如下:virtual BOOL CreateStatic(CWnd*pParentWnd,int nRows,int nCols,DWORD dwStyle=WS_CHILD|WS_VISIBLE,UINT nID=AFX_IDW_PANE_FIRST);参数含义如下:pParentWnd:分割窗口的父框架窗口。第一次分割窗口时,父窗口是框架CMainFrame,分割成2行1列。第二次分割窗口时,是嵌入在第一次分割的窗口中的,所以父窗口为m_splitter1,分割为1行2列,嵌套的窗口ID通过类CSplitterWnd的成员函数IdFromRowCol()获得。类CSplitterWnd的成员函数CreateView()为静态分割窗口创建窗格,原型如下:virtual BOOL CreateView(int row,int col,CRuntimeClass*pViewClass,SIZE sizeInit,CCreateContext*pContext);参数含义如下:row:指定放置新视图的窗口行。调用类CSplitterWnd的成员函数SetRowInfo()和SetColumnInfo()分别设置分割窗口的行高取值范围、列宽取值范围。函数原型如下:void SetRowInfo(int row,int cyIdeal,int cyMin);void SetColumnInfo(int col,int cxIdeal,int cxMin);参数含义如下:row、col:指定分割窗口的行、列,用于定位。在函数OnCreateClient()中,我们将3个视图CMsgShow、CFileTree和CFtpClientView指定到相应的分割窗格中。前两个是我们利用类向导添加的新类,分别基于类CEditView和CTreeView,最后一个是我们创建工程时由向导为我们创建的视图类,基于类CListView。至此客户区分割的操作代码填加完毕。5.2.3 树形视图项目拖动效果我们可以通过捕获3个事件来添加拖动效果的代码,他们是:鼠标左键选中项目并且开始拖动、鼠标移动和鼠标左键抬起。1.选中视图项我们需要用类向导添加一个新类CFileTree,基于CTreeView,如图5.11所示。图5.11 添加新类CFileTree在类CFileTree的实现文件,添加文件包含指令如下:#include MainFrm.h#include FtpClientView.h在利用类向导为它添加函数OnBegindrag(),如图5.12所示。图5.12 为类CFileTree添加消息响应为函数OnBegindrag()添加代码,如下:函数OnBegindrag()中的变量是类CFileTree的公有成员变量,定义如下:成员变量在类CFreeTree的构造函数初始化如下:类CTreeCtrl的成员函数GetTreeCtrl()返回树视图控件的引用。函数OnBegindrag()中结构NM_TREEVIEW定义如下:typedef struct _NM_TREEVIEW NMHDR hdr;UINT action;TV_ITEM itemOld;TV_ITEM itemNew;POINT ptDrag;NM_TREEVIEW;参数含义如下:hdr:另一个包含通知消息信息的结构NMHDR。我们要从这个结构中获取两个信息:itemNew.hItem和ptDrag。前者是个结构TV_ITEM,用来指定或返回树视图项的属性。结构TV_ITEM的字段hItem放的是这个结构指向树视图项的句柄HTREEITEM,被保存在了m_hItemDragS变量中。然后用到类CTreeCtrl的1个成员函数和CImageList的2个成员函数完成图像拖动的准备工作,它们是:CreateDragImage()用来为指定的树视图项创建拖动时的位图、BeginDrag()标志拖动位图操作的开始、DragEnter()用来在拖动操作期间在指定的位置显示位图和锁定更新。函数BeginDrag()的原型如下:BOOL BeginDrag(int nImage,CPoint ptHotSpot);参数含义如下:nImage:索引号从0开始的位图号,用来指定位图。函数DragEnter()的原型如下:static BOOL PASCAL DragEnter(CWnd*pWndLock,CPoint point);参数含义如下:pWndLock:指向拥有拖动图像的窗口指针。若参数赋值为NULL,这个函数拖动图像的坐标是相对于桌面窗口的,即屏幕坐标的左上角。所以我们在使用函数DragEnter()的时候,用到类CWnd的成员函数ClientToScreen(),将给定的客户区点坐标转换为屏幕点坐标。最后我们同样调用类CWnd的成员函数SetCapture(),以后不管鼠标的位置在哪里,所有的鼠标后续输入都会被送到当前的窗口处理。至此,鼠标左键选中项目并且开始拖动事件的捕捉和处理代码填写和解释完毕。2.图像随鼠标移动利用类向导为类CFileTree添加下一个事件:鼠标移动。如图5.13所示。图5.13 添加鼠标移动事件为函数OnMouseMove()添加代码,如下:函数OnMouseMove()首先调用AfxGetMainWnd(),获取指向当前程序主框架CMainFrame的指针,保存在变量mFrm中,通过此变量调用其成员变量m_splitter2的成员函数,既类CSplitterWnd的成员函数GetPane(),得到指定行列窗格的指针。这里获取的是列表视图窗格的指针,保存在变量pEView中。我们要在类CFileTree中添加一个自定义的成员函数GetCtrlRect(),如图5.14所示。图5.14 添加自定义的成员函数添加如下很简单的一段代码就行:简单的封装了两个函数,分别完成功能:获取树视图窗口的矩形大小,即窗口大小。然后将坐标转换为相对屏幕的坐标值。同样需要在类CFtpClientView中添加这样一个自定义的函数GetCtrlRect(),代码一样,功能当然也一样,如下:函数OnMouseMove()接下来完成的功能是:创建两个“区域”。实例化两个类CRgn的对象listRgn和treeRgn,调用类CRgn的成员函数CreateRectRgn()创建两个矩形区域,分别覆盖了树形结构视图、列表结构视图。函数CreateRectRgn()的原型如下:BOOL CreateRectRgn(int x1,int y1,int x2,int y2);参数含义如下:x1、y1:指定矩形区域左上角点的坐标位置。函数OnMouseMove()最后会判断:鼠标是否处于拖动的状态,是在树形结构视图区域或者列表结构视图区域中吗.通过类CRgn的成员函数PtInRegion()判断指定的点是否在指定的区域范围内。在指定的区域范围内,并且当前正处在拖动的状态下时,就该调用拖动操作的第4个函数了,它是类CImageList的成员函数DragMove(),原型如下:static BOOL PASCAL DragMove(CPoint pt);pt是拖动操作时,鼠标新的位置点。这个函数移动图像到指定的新的坐标点,也就是图像会随着鼠标移动效果的展现。若是不满足刚才的判断条件呢?是不是就什么都不做了?当然不是,还有另一个有趣的效果需要实现。我们通过类CTreeCtrl的成员函数HitTest()判断:鼠标点相对树视图控件的位置,若是在控件内部的话,会返回指定位置树视图项的句柄,当指定位置不在在任何一个树视图项上,则返回NULL。即我们的鼠标在树视图窗口上“划过”,相应的树视图项就会有“被选中”的效果。通过调用类CTreeCtrl的成员函数SelectDropTarget(),重绘树视图相应项,以一种表明树视图项被选中的样式,参数是树视图项的句柄就行。那么,鼠标移动图像的代码也填写和解释完毕了。3.鼠标图像释放利用类向导为类CFileTree添加最后一个事件:鼠标左键弹起。如图5.15所示。图5.15 添加鼠标左键弹起事件为函数OnLButtonUp()添加代码,如下:函数OnLButtonUp()会调用AfxGetMainWnd()获取本程序主框架的指针,并保存在变量mFrm中,用mFrm通过其数据成员m_splitter2获取列表视图窗格的指针。当确定鼠标是在拖动图像的时候左键才弹起的,即m_bDragging为true时,我们用最后2个函数来完成拖动操作。它们是类CImageList的成员函数:DragLeave()用来解锁参数指定的窗口、隐藏图像、允许窗口更新;EndDrag()用来结束拖动操作。函数原型如下:static BOOL PASCAL DragLeave(CWnd*pWndLock);static void PASCAL EndDrag();通过函数ReleaseCapture()释放鼠标的捕获。然后就是我们应该很熟悉的操作了,获取列表视图矩形大小、创建覆盖列表视图的区域、判断鼠标点移动到了创建的区域范围之内时,添加任意的操作。5.2.4 列表视图项目拖动效果与树形视图项目拖动效果类似,我们可以通过捕获3个事件来添加拖动效果的代码,他们是:鼠标左键选中项目并且开始拖动、鼠标移动和鼠标左键抬起。首先需要在类CFtpClientView的实现文件头部添加文件包含指令如下:#include MainFrm.h#include FileTree.h在类CFtpClientView的头文件添加类的声明,代码如下:class CFtpClientDoc;1.选中视图项利用类向导为类CFtpClientView添加函数OnBegindrag(),如图5.16所示。图5.16 为类CFileTree添加消息响应为函数OnBegindrag()添加代码,如下:函数OnBegindrag()中的变量是类CFtpClientView的公有成员变量,定义如下:成员变量在类CFtpClientView的构造函数初始化如下:函数OnBegindrag()会调用类CListCtrl的2个成员函数:GetNextItem()和CreateDragImage()。GetNextItem()用来检索满足指定条件的列表项,函数原型如下:int GetNextItem(int nItem,int nFlags)const;参数含义如下:nItem:开始检索时起始列表项的索引,若为-1将会匹配满足nFlags所指条件的第一个列表项,所指定的列表项不会被检索。CreateDragImage()用来为指定的列表项创建拖动图像,函数原型如下:CImageList*CreateDragImage(int nItem,LPPOINT lpPoint);参数含义如下:nItem:要创建拖动图像的列表项的索引。函数OnBegindrag()剩下的操作,我们应该很熟悉了才对,包括:调用类CImageList的成员函数BeginDrag(),标志开始拖动图像;调用类CImageList的成员函数DragEnter(),锁定视图的更新;调用类CWnd的成员函数SetCapture()捕获鼠标后续的所有事件。2.图像随鼠标移动利用类向导为类CFtpClientView添加下一个事件:鼠标移动。如图5.17所示。图5.17 添加鼠标移动事件为函数OnMouseMove()添加代码,如下:函数OnMouseMove()的实现过程同样包括:获取树形视图、列表视图窗口矩形大小,创建覆盖树形视图、列表视图窗口的区域,检测鼠标处于拖动图像状态,而且在树形视图或列表视图的区域范围内,调用类CImageList的成员函数DragMove()拖动图像。3.鼠标图像释放利用类向导为类CFtpClientView添加最后一个事件:鼠标左键弹起。如图5.18所示。图5.18 添加鼠标左键弹起事件为函数OnLButtonUp()添加代码,如下:函数OnLButtonUp()实现的功能包括:解锁拖动窗口、结束拖动操作、释放鼠标的捕获、获取树视图矩形大小、创建覆盖树视图的区域、判定鼠标点在树视图区域之内。5.3 实现FTP客户端这个实例是通过WinInet API来实现FTP客户端的,因此无需考虑底层的通信协议和数据传输工作,所以我们把近一半的精力用在了华丽的程序界面上。5.3.1 WinInet类介绍MFC提供的WinInet类是对WinInet API的封装,为我们提供了更加方便的编程接口。主要用到两个类:CInternetSession和CFtpConnection。1.CInternetSession类用来创建或者初始化一个或多个同步的网络会话。它的构造函数原型如下:CInternetSession(LPCTSTR pstrAgent=NULL,DWORD_PTR dwContext=1,DWORD dwAccessType=PRE_CONFIG_INTERNET_ACCESS,LPCTSTR pstrProxyName=NULL,LPCTSTR pstrProxyBypass=NULL,DWORD dwFlags=0);我们的实例程序直接使用了所有的默认参数值。当我们要在服务器上执行指定的服务,如FTP服务,必须要先建立连接,用到的成员函数是GetFtpConnection()。函数原型如下:CFtpConnection*GetFtpConnection(LPCTSTR pstrServer,LPCTSTR pstrUserName=NULL,LPCTSTR pstrPassword=NULL,INTERNET_PORT nPort=INTERNET_INVALID_PORT_NUMBER,BOOL bPassive=FALSE);参数含义如下:pstrServer:包含FTP服务器IP地址的字符串。bPassive:为这个会话指定被动或主动的模式,默认为主动模式。返回一个指向类CFtpConnection的指针。2.CFtpConnection类此类主要用于管理FTP服务连接,并允许用户直接操作服务器目录和文件。我们主要用到了此类的2个成员函数:PutFile()用来上传文件,GetFile()用来下载文件。函数原型如下:BOOL PutFile(LPCTSTR pstrLocalFile,LPCTSTR pstrRemoteFile,DWORD dwFlags=FTP_TRANSFER_TYPE_BINARY,DWORD_PTR dwContext=1);参数含义如下:pstrLocalFile:包含要上传文件路径的字符串。依据返回值判定上传操作是否成功。函数GetFile()的原型如下:BOOL GetFile(LPCTSTR pstrRemoteFile,LPCTSTR pstrLocalFile,BOOL bFailIfExists=TRUE,DWORD dwAttributes=FILE_ATTRIBUTE_NORMAL,DWORD dwFlags=FTP_TRANSFER_TYPE_BINARY,DWORD_PTR dwContext=1);参数含义如下:pstrRemoteFile:包含要接收FTP服务器上文件路径的字符串。读者可以依据函数GetFile()的返回值来判定下载操作是否成功。5.3.2 FTP服务器操作通过浮动对话框获取用户输入的信息,调用类的成员连接、登录FTP服务器,最后将FTP服务器根目录下的所有文件显示在列表视图中。浮动对话框如图5.19所示。图5.19 浮动对话框我们需要在类CMainFrame中手动添加“连接服务器”和“确定”按钮的消息响应函数OnConnect()和OnChooseDisc(),步骤如下:(1)在类CMainFrame头文件添加文件包含指令,用来支持WinInet类,如下:#include/为了使用CFtpConnect CInternetSession在类中添加成员变量和成员函数,如下:(2)在类CMainFrame的实现文件添加文件包含指令,用来支持3个分割窗口视图,如下:#include MsgShow.h/3个窗体的头文件#include FileTree.h#include FtpClientView.h添加消息映射,即控件ID与处理事件函数建立联系,如下:添加了2个按钮单击事件的消息映射。类CMainFrame的构造函数如下:可以看到,构造函数只是初始化了一些成员变量。1.连接FTP服务器编写按钮“连接服务器”按钮的消息响应函数OnConnect(),如下:响应函数OnConnect()功能的实现步骤包括:获取浮动对话框上由用户填写的登录信息,保存在3个字符串变量中,他们是strHost、strName和strPass,调用类CInternetSession的成员函数GetFtpConnection()连接FTP服务器,代码中对异常的情况做了一些处理,代码包含在try和catch的语句块中。为类CFtpClientView添加成员函数BrowseDir(),用来遍历服务器根目录下的所有文件,代码编写如下:函数BrowseDir()使用了类CFtpFileFind,用来辅助FTP服务器上网络文件的检索。主要调用了此类的5个成员函数:FindFile()用来查找FTP服务器上指定的文件。通过while循环将满足条件的文件全部插入到列表视图中。用类CListCtrl的成员函数InsertItem()实现,原型如下:int InsertItem(int nItem,LPCTSTR lpszItem,int nImage);参数含义如下:nItem:要将列表项插入索引视图的位置。类CMsgShow我们提到过,是我们自己新建的基于CEditView的类。为此类添加成员函数ShowMsg(),用来将指定的字符串显示在信息显示窗格中,代码如下:函数ShowMsg()中的m_editView是类CMsgShow的成员变量,在类CMsgShow的构造函数中被初始化,代码如下:构造函数调用了类CEditView的成员函数GetEditCtrl(),用来获取指向编辑视图的指针,然后保存在成员变量m_editView中。函数ShowMsg()的功能实现过程:获取当前编辑视图窗格的文本内容,依据之前的内容再添加新的文本信息。函数ShowMsg()还使用到类CEditView继承自类CWnd的2个成员函数:GetWindowText():获取窗口的文本,并保存在传入的参数字符串中。用于连接服务器的函数OnConnect(),在连接到服务器以后会:改变自身按钮的文本为“断开连接”、将浮动对话框上的文本框设置为禁用。2.断开连接当程序与FTP服务器处于连接状态时,我们再次单击“断开连接”按钮时,将关闭与服务器的连接,如下:函数OnConnect()调用到了列表视图的成员函数deleteItem(),用来清空列表视图的所有列表项,函数deleteItem()的实现如下:很简单的函数封装,只是调用了类CListCtrl的成员函数DeleteAllItems(),甚至连参数都不需要。函数OnConnect()的后续操作包括:调用类CFtpConnection的成员函数Close()关闭与FTP的连接,在信息显示框中显示文本信息“断开与服务器的连接”,改变“断开连接”按钮的文本为“连接服务器”,最后将浮动对话框中被禁用的文本框设置为可用。5.3.3 遍历本地文件夹资源用户需要手动填写“文件夹路径”文本框,在单击“确定”按钮,树结构视图中将会显示出该文件夹下的所有文件资源。为浮动对话框的按钮“确定”添加消息响应函数OnChooseDisc(),功能代码编写如下:函数OnChooseDisc()中,调用到类CFileTree的成员函数deleteItem(),用来清除树结构视图中的所有项,实现如下:同样是很简单的函数封装,只是调用了类CTreeCtrl的成员函数DeleteAllItems(),甚至连参数都不需要。类CFileTree的成员函数BrowseDir(),用来实现遍历文件夹中文件资源,并按结构插入到树中,实现代码如下:函数BrowseDir()的功能实现过程:构造遍历文件的字符串,调用类CFileFind的6个成员函数:FindFile()用来查找本地指定路径下的文件资源。IsDots()用来确定找到的文件的文件名是否包含“.”或“.”,它们其实就是目录。IsDirectory()用来确定找到的文件是否是目录。类CTreeCtrl的成员函数InsertItem()用来向树结构视图中添加项,函数原型如下:HTREEITEM InsertItem(LPCTSTR lpszItem,int nImage,int nSelectedImage,HTREEITEM hParent=TVI_ROOT,HTREEITEM hInsertAfter=TVI_LAST);参数含义如下:lpszItem:插入项的文本指针。树结构视图CFileTree关联的图像列表是在函数OnInitialUpdate()中确定的,代码如下:我们当然得先在资源编辑器中插入2个图标资源,一个用来表示文件,一个用来表示文件夹,如图5.20所示。图5.20 自己制作的小图标类CWinApp的成员函数LoadIcon(),将加载指定ID的图标资源,返回图标的句柄。创建图标列表调用到类CImageList的成员函数Create(),函数原型如下:BOOL Create(int cx,int cy,UINT nFlags,int nInitial,int nGrow);参数含义如下:cx、cy:图像的长宽值,以像素为单位。调用类CImageList的成员函数Add(),将指定的图标句柄加入到图像列表中,调用类CTreeCtrl的成员函数SetImageList(),用来关联树结构视图与图像列表,函数原型如下:CImageList*SetImageList(CImageList*pImageList,int nImageListType);参数含义如下:pImageList:指向图像列表的指针。若为NULL,树视图的所有图标将会被移除。另外,成功操作的图结构视图的显示效果会是图5.21所示的样子。图5.21 树结构视图的效果要想改变显示效果,可以在类CFileTree中重载函数PreCreateWindow(),用来改变树结构视图的样式,代码如下:改变了样式以后显示的效果将会是图5.22所示的样子。图5.22 树结构视图的效果5.3.4 拖动文件实现上传文件上传到FTP服务器,只需要调用类CFtpConnetion的成员函数PutFile()就可以了,但是需要准备此函数的参数:要上传的本地文件的路径在开始拖动文件时获得,函数PutFile()的调用是在鼠标左键弹起时。注意:搭建自己的FTP服务器,并且创建了登录的用户时,默认这个用户是没有上传文件的权限的,需要我们设置一下权限,如图5.23所示Serv-U的权限设置。图5.23 Serv-U用户目录权限设置在类CFileTree的成员函数OnBegindrag()中添加如下代码:函数OnBegindrag()添加的功能是:获取拖动文件的文件名,若它有父节点的话还需要获取父节点的文件名。m_filename和m_fileLname是定义在类CFileTree中的成员变量,用来保存文件名和文件的部分路径,完整路径会在鼠标左键弹起时构建。为鼠标左键弹起事件的响应函数OnLButtonUp()添加代码如下:函数OnLButtonUp()添加的功能是:构建本地文件的路径,构建上传到FTP服务器上的路径,调用函数PutFile()上传文件,有错发送时会有错误提示信息,成功上传文件的话会在信息显示窗口显示操作信息。5.3.5 拖动文件实现下载将FTP服务器上的文件下载到本地,只需要调用类CFtpConnetion的成员函数GetFile()就可以了,但是需要准备此函数的参数:要下载到本地的文件路径,函数GetFile()的调用是在鼠标左键弹起时。在类CFtpClientView的成员函数OnBegindrag()中添加代码如下:函数OnBegindrag()添加的功能:获取拖动文件的文件名,构建FTP服务器上该文件的路径文本。在类CFtpClientView的成员函数OnLButtonUp()中添加代码如下:函数OnLButtonUp()添加的功能:构建FTP服务器上文件的路径,构建本地文件存放位置的路径,调用函数GetFile()下载FTP服务器上的文件。5.3.6 多次修改的头文件经过了多次成员函数和成员变量的添加,我们来看一下最终类的头文件我们添加了什么。首先是列表结构视图,头文件部分代码如下:树结构视图,部分头文件如下:主框架CMainFrame,部分头文件如下:5.4 小结本章实现了一个较第4章更为华丽的一个FTP客户端,也是网上最普遍的一类FTP客户端。但是本程序中尚有许多功能缺失,例如,本客户端只会遍历指定的本地文件夹下的所有文件资源,而非所有本地计算机上的资源;两个视图显示的图标比较单一等等。当然,有兴趣完善本章实例的读者可以自由修改。