一、实验目的二、实验环境三、实验内容
一、实验目的
- 掌握MFC Win32项目的创建方法创建一个Internet会话以及建立与FTP服务器的连接;用MFC应用程序向导创建文档/视图结构的框架程序;掌握CHtmlView类、CToolBarCtrl类、CReBar类等的用法。
- *** 作系统:WINDOWS 7及以上开发工具:Microsoft VisualBasic6.0实验设备:PC
1.设计一个简易FTP客户机,可以选择登陆的FTP服务器,使用登录名和密码。一旦与服务器建立连接,即显示服务器当前目录列表,列表包括文件名、修改如期和大小,实现的 *** 作包括进入子目录、返回上一级目录、重命名文件、删除文件、上传文件和下载文件。
2.搭建FT服务器,并与客户机进行联合测试
3.利用CHtmlView类实现一个浏览器程序,用户可以使用这个自制浏览器访问任何网站、下载文件、提交表单、打开本地文件等,网址可以通过CReBar空间创建的工具条输入并导航到目标资源,可以在主窗口单机各种超链接。
FTP客户机:
FtpClient.h:
#pragma once #ifndef __AFXWIN_H__ #error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件" #endif #include "resource.h" // CFtpClientApp: class CFtpClientApp : public CWinApp { public: CFtpClientApp(); // 重写 public: virtual BOOL InitInstance(); // 实现 DECLARE_MESSAGE_MAP() }; extern CFtpClientApp theApp;
FtpClient.cpp:
// FtpClient.cpp : 定义应用程序的类行为。 #include "stdafx.h" #include "FtpClient.h" #include "FtpClientDlg.h" // CFtpClientApp BEGIN_MESSAGE_MAP(CFtpClientApp, CWinApp) ON_COMMAND(ID_HELP, &CWinApp::OnHelp) END_MESSAGE_MAP() // CFtpClientApp 构造 CFtpClientApp::CFtpClientApp() { // 支持重新启动管理器 m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART; // TODO: 在此处添加构造代码, // 将所有重要的初始化放置在 InitInstance 中 } // 唯一的一个 CFtpClientApp 对象 CFtpClientApp theApp; // CFtpClientApp 初始化 BOOL CFtpClientApp::InitInstance() { INITCOMMonCONTROLSEX InitCtrls; InitCtrls.dwSize = sizeof(InitCtrls); // 将它设置为包括所有要在应用程序中使用的 // 公共控件类。 InitCtrls.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&InitCtrls); CWinApp::InitInstance(); AfxEnableControlContainer(); CShellManager *pShellManager = new CShellManager; SetRegistryKey(_T("应用程序向导生成的本地应用程序")); CFtpClientDlg dlg; m_pMainWnd = &dlg; INT_PTR nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: 在此放置处理何时用 // “确定”来关闭对话框的代码 } else if (nResponse == IDCANCEL) { // TODO: 在此放置处理何时用 // “取消”来关闭对话框的代码 } // 删除上面创建的 shell 管理器。 if (pShellManager != NULL) { delete pShellManager; } // 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序, // 而不是启动应用程序的消息泵。 return FALSE; }
FtpClientDlg.h:
// FtpClientDlg.h : 头文件 #pragma once #include "Afxinet.h" // CFtpClientDlg 对话框 class CFtpClientDlg : public CDialogEx { public: CFtpClientDlg(CWnd* pParent = NULL); // 标准构造函数 // 对话框数据 enum { IDD = IDD_FTPCLIENT_DIALOG }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 protected: HICON m_hIcon; // 生成的消息映射函数 virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: afx_msg void OnBnClickedButtonLogin(); afx_msg void OnBnClickedButtonUpload(); CString m_strPassword; CString m_strServerName; CString m_strUserName; afx_msg void OnBnClickedButtonRename(); afx_msg void OnBnClickedButtonQuery(); afx_msg void OnBnClickedButtonDownload(); afx_msg void OnBnClickedButtonLogout(); CInternetSession* m_pFTPSession; CFtpConnection* m_pConnection; CFtpFileFind* m_pFileFind; //遍历目录 void DisplayContent(LPCTSTR lpctstr,CString currentDir=_T("/")); CListCtrl m_listDirectory; void Download(void);//下载文件 void Upload(void);//上传文件 void Rename(void);//文件改名 afx_msg void OnBnClickedButtonSubdir(); afx_msg void OnBnClickedButtonDelete(); afx_msg void OnBnClickedButtonParentdir(); void DeleteFile(void);//删除文件 void DisplaySubDir(void);//显示子目录 CString GetParentDirectory(CString str);//返回父目录 void DisplayParentDir(void);//显示父目录 //连接服务器 BOOL Connect(CString serverName, CString userName, CString password); };
FtpClientDlg.cpp:
// FtpClientDlg.cpp : 实现文件 #include "stdafx.h" #include "FtpClient.h" #include "FtpClientDlg.h" #include "afxdialogex.h" #include "NewNameDlg.h" // 用于应用程序“关于”菜单项的 CaboutDlg 对话框 class CaboutDlg : public CDialogEx { public: CaboutDlg(); // 对话框数据 enum { IDD = IDD_aboutBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: DECLARE_MESSAGE_MAP() }; CaboutDlg::CaboutDlg() : CDialogEx(CaboutDlg::IDD) {} void CaboutDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CaboutDlg, CDialogEx) END_MESSAGE_MAP() // CFtpClientDlg 对话框 CFtpClientDlg::CFtpClientDlg(CWnd* pParent ) : CDialogEx(CFtpClientDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINframe); m_strServerName = _T("127.0.0.1"); m_strUserName = _T("anonymous"); m_strPassword = _T(""); m_pFTPSession=NULL; m_pConnection = NULL; m_pFileFind = NULL; } void CFtpClientDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT_PASSWORD, m_strPassword); DDX_Text(pDX, IDC_EDIT_SERVERNAME, m_strServerName); DDX_Text(pDX, IDC_EDIT_USERNAME, m_strUserName); DDX_Control(pDX, IDC_LIST_DIRECTORY, m_listDirectory); } BEGIN_MESSAGE_MAP(CFtpClientDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON_LOGIN, &CFtpClientDlg::OnBnClickedButtonLogin) ON_BN_CLICKED(IDC_BUTTON_UPLOAD, &CFtpClientDlg::OnBnClickedButtonUpload) ON_BN_CLICKED(IDC_BUTTON_RENAME, &CFtpClientDlg::OnBnClickedButtonRename) ON_BN_CLICKED(IDC_BUTTON_QUERY, &CFtpClientDlg::OnBnClickedButtonQuery) ON_BN_CLICKED(IDC_BUTTON_DOWNLOAD, &CFtpClientDlg::OnBnClickedButtonDownload) ON_BN_CLICKED(IDC_BUTTON_LOGOUT, &CFtpClientDlg::OnBnClickedButtonLogout) ON_BN_CLICKED(IDC_BUTTON_SUBDIR, &CFtpClientDlg::OnBnClickedButtonSubdir) ON_BN_CLICKED(IDC_BUTTON_DELETE, &CFtpClientDlg::OnBnClickedButtonDelete) ON_BN_CLICKED(IDC_BUTTON_PARENTDIR, &CFtpClientDlg::OnBnClickedButtonParentdir) END_MESSAGE_MAP() // CFtpClientDlg 消息处理程序 BOOL CFtpClientDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_aboutBOX 必须在系统命令范围内。 ASSERT((IDM_aboutBOX & 0xFFF0) == IDM_aboutBOX); ASSERT(IDM_aboutBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { BOOL bNamevalid; CString straboutMenu; bNamevalid = straboutMenu.LoadString(IDS_aboutBOX); ASSERT(bNamevalid); if (!straboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_aboutBOX, straboutMenu); } } // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动 // 执行此 *** 作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 m_listDirectory.InsertColumn(0,_T("文件名"),LVCFMT_CENTER,200); m_listDirectory.InsertColumn(1,_T("修改日期"),LVCFMT_CENTER,100); m_listDirectory.InsertColumn(2,_T("大小"),LVCFMT_CENTER,200); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } void CFtpClientDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_aboutBOX) { CaboutDlg dlgabout; dlgabout.DoModal(); } else { CDialogEx::OnSysCommand(nID, lParam); } } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CFtpClientDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast(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 { CDialogEx::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标 //显示。 HCURSOR CFtpClientDlg::OnQueryDragIcon() { return static_cast (m_hIcon); } void CFtpClientDlg::OnBnClickedButtonLogin() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); if (Connect(m_strServerName,m_strUserName,m_strPassword)) { DisplayContent(_T("*")); GetDlgItem(IDC_EDIT_SERVERNAME)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_USERNAME)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_PASSWORD)->EnableWindow(FALSE); GetDlgItem(IDC_BUTTON_LOGIN)->EnableWindow(FALSE); }else //连接失败 { AfxMessageBox(_T("连接服务器失败!"),MB_OK|MB_ICONSTOP); } } void CFtpClientDlg::OnBnClickedButtonUpload() { // TODO: 在此添加控件通知处理程序代码 Upload(); } void CFtpClientDlg::OnBnClickedButtonRename() { // TODO: 在此添加控件通知处理程序代码 Rename(); } void CFtpClientDlg::OnBnClickedButtonQuery() { // TODO: 在此添加控件通知处理程序代码 DisplayContent(_T("*")); } void CFtpClientDlg::OnBnClickedButtonDownload() { // TODO: 在此添加控件通知处理程序代码 Download(); } //退出 void CFtpClientDlg::OnBnClickedButtonLogout() { // TODO: 在此添加控件通知处理程序代码 delete m_pFTPSession; delete m_pConnection; delete m_pFileFind; m_pFTPSession=NULL; m_pConnection = NULL; m_pFileFind = NULL; DestroyWindow(); } //显示服务器当前目下的所有文件与子目录 void CFtpClientDlg::DisplayContent(LPCTSTR lpctstr,CString currentDir) { UpdateData(TRUE); Connect(m_strServerName,m_strUserName,m_strPassword); m_pConnection->SetCurrentDirectory(currentDir); m_listDirectory.DeleteAllItems(); m_pFileFind=new CFtpFileFind(m_pConnection); BOOL bFound; bFound=m_pFileFind->FindFile(lpctstr); if (!bFound) { m_pFileFind->Close(); m_pFileFind=NULL; AfxMessageBox(_T("没有找到文件!"),MB_OK | MB_ICONSTOP); return; } CString strFileName; CString strFileTime; CString strFileLength; while(bFound) { bFound= m_pFileFind->FindNextFile(); strFileName=m_pFileFind->GetFileName(); FILETIME ft; m_pFileFind->GetLastWriteTime(&ft); CTime FileTime(ft); strFileTime = FileTime.Format("%y-%m-%d"); if (m_pFileFind->IsDirectory()) { //如果是目录用<子目录>代替 strFileLength = "<子目录>"; } else { //得到文件大小 ULonGLONG fileSize=m_pFileFind->GetLength(); if (fileSize<1024) { strFileLength.Format(_T("%d Bytes"),fileSize); } else if (fileSize<(1024*1024)) { strFileLength.Format(_T("%3.3f KB"),fileSize/1024.0); }else if (fileSize<(1024*1024*1024)) { strFileLength.Format(_T("%3.3f MB"),fileSize/(1024*1024.0)); }else { strFileLength.Format(_T("%1.3f GB"), fileSize/(1024.0*1024*1024)); }//end if fileSize }//end if int column=0; m_listDirectory.InsertItem(column,strFileName,0); m_listDirectory.SetItemText(column,1,strFileTime); m_listDirectory.SetItemText(column,2,strFileLength); column++; }//end while UpdateData(FALSE); } //下载 void CFtpClientDlg::Download(void) { int index=m_listDirectory.GetNextItem(-1,LVNI_SELECTED); if (index==-1) { AfxMessageBox(_T("请首先选择要下载的文件!"),MB_OK | MB_ICONQUESTION); } else { CString strType=m_listDirectory.GetItemText(index,2); //得到选择项的类型 if (strType!="<子目录>") //选择的是文件 { CString strDestName; CString strSourceName; strSourceName = m_listDirectory.GetItemText(index,0);//得到所要下载的文件名 CFileDialog dlg(FALSE,_T(""),strSourceName); if (dlg.DoModal()==IDOK) { //获得下载文件在本地机上存储的路径和名称 strDestName=dlg.GetPathName(); //调用CFtpConnect类中的GetFile函数下载文件 if (m_pConnection->GetFile(strSourceName,strDestName)) AfxMessageBox(_T("下载成功!"),MB_OK|MB_ICONINFORMATION); else AfxMessageBox(_T("下载失败!"),MB_OK|MB_ICONSTOP); } } else { //选择的是目录 AfxMessageBox(_T("不能下载目录!n请重选!"),MB_OK|MB_ICONSTOP); } } } //上传 void CFtpClientDlg::Upload(void) { CString strSourceName; CString strDestName; CFileDialog dlg(TRUE,_T(""),_T("*.*")); if (dlg.DoModal()==IDOK) { //获得待上传的本地文件路径和文件名 strSourceName = dlg.GetPathName(); strDestName = dlg.GetFileName(); //调用CFtpConnect类中的PutFile函数上传文件 if (m_pConnection->PutFile(strSourceName,strDestName)) AfxMessageBox(_T("上传成功"),MB_OK|MB_ICONINFORMATION); else AfxMessageBox(_T("上传失败"),MB_OK|MB_ICONSTOP); } DisplayContent(_T("*")); } //文件改名 void CFtpClientDlg::Rename(void) { CString strNewName; CString strOldName; int index=m_listDirectory.GetNextItem(-1,LVNI_SELECTED); //得到CListCtrl被选中的项 if (index==-1) { AfxMessageBox(_T("没有选择文件!"),MB_OK | MB_ICONQUESTION); } else { strOldName = m_listDirectory.GetItemText(index,0);//得到所选择的文件名 CNewNameDlg dlg; if (dlg.DoModal()==IDOK) { strNewName=dlg.m_NewFileName; if (m_pConnection->Rename(strOldName,strNewName)) AfxMessageBox(_T("重命名成功!"),MB_OK|MB_ICONINFORMATION); else AfxMessageBox(_T("无法重命名!"),MB_OK|MB_ICONSTOP); } } DisplayContent(_T("*"));//显示目录 } void CFtpClientDlg::OnBnClickedButtonSubdir() { // TODO: 在此添加控件通知处理程序代码 DisplaySubDir(); } void CFtpClientDlg::OnBnClickedButtonDelete() { // TODO: 在此添加控件通知处理程序代码 DeleteFile(); } void CFtpClientDlg::OnBnClickedButtonParentdir() { // TODO: 在此添加控件通知处理程序代码 DisplayParentDir(); } //删除文件 void CFtpClientDlg::DeleteFile(void) { int index=m_listDirectory.GetNextItem(-1,LVNI_SELECTED); if (index==-1) { AfxMessageBox(_T("没有选择文件!"),MB_OK | MB_ICONQUESTION); } else { CString strFileName; strFileName = m_listDirectory.GetItemText(index,0); if (_T("<子目录>")==m_listDirectory.GetItemText(index,2)) { AfxMessageBox(_T("不能删除目录!"),MB_OK | MB_ICONSTOP); } else { if (m_pConnection->Remove(strFileName)) AfxMessageBox(_T("删除成功!"),MB_OK|MB_ICONINFORMATION); else AfxMessageBox(_T("无法删除!"),MB_OK|MB_ICONSTOP); } } DisplayContent(_T("*")); } //显示下级子目录 void CFtpClientDlg::DisplaySubDir(void) { static CString strCurrentDirectory,strSub; m_pConnection->GetCurrentDirectory(strCurrentDirectory); strCurrentDirectory.Format(_T("%s/"),(strCurrentDirectory)); //得到所选择的文本 int index=m_listDirectory.GetNextItem(-1,LVNI_SELECTED); strSub = m_listDirectory.GetItemText(index,0); if (index==-1) { AfxMessageBox(_T("没有选择目录!"),MB_OK | MB_ICONQUESTION); } else { //判断是不是目录 if (_T("<子目录>")!=m_listDirectory.GetItemText(index,2)) { AfxMessageBox(_T("不是子目录!"),MB_OK | MB_ICONSTOP); } else { //设置当前目录 strCurrentDirectory.Format(_T("%s%s"),strCurrentDirectory,strSub); m_pConnection->SetCurrentDirectory(strCurrentDirectory); //对当前目录进行查询 DisplayContent(_T("*"),strCurrentDirectory); } } } //返回上一级目录的字符串表示 CString CFtpClientDlg::GetParentDirectory(CString str) { int LastIndex=0; for (int i=0; i GetCurrentDirectory(strCurrentDirectory); if (strCurrentDirectory ==_T("/")) { AfxMessageBox(_T("已经是根目录了!"),MB_OK | MB_ICONSTOP); } else { strCurrentDirectory=GetParentDirectory(strCurrentDirectory); //设置当前目录 m_pConnection->SetCurrentDirectory(strCurrentDirectory); //对当前目录进行查询 DisplayContent(_T("*"),strCurrentDirectory); } } BOOL CFtpClientDlg::Connect(CString serverName, CString userName, CString password) { m_pFTPSession=new CInternetSession(AfxGetAppName(),1,PRE_CONFIG_INTERNET_ACCESS); try { //试图建立FTP连接 m_pConnection=m_pFTPSession->GetFtpConnection(serverName,userName,password); } catch (CInternetException* e) { //错误处理 e->Delete(); m_pFTPSession=NULL; m_pConnection=NULL; return FALSE; } return TRUE; }
NewNameDlg.h:
#pragma once // CNewNameDlg 对话框 class CNewNameDlg : public CDialog { DECLARE_DYNAMIC(CNewNameDlg) public: CNewNameDlg(CWnd* pParent = NULL); // 标准构造函数 virtual ~CNewNameDlg(); // 对话框数据 enum { IDD = IDD_NEWNAMEDLG }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 DECLARE_MESSAGE_MAP() public: afx_msg void OnBnClickedOk(); CString m_NewFileName; };
NewNameDlg.cpp:
// NewNameDlg.cpp : 实现文件 #include "stdafx.h" #include "FtpClient.h" #include "NewNameDlg.h" #include "afxdialogex.h" // CNewNameDlg 对话框 IMPLEMENT_DYNAMIC(CNewNameDlg, CDialog) CNewNameDlg::CNewNameDlg(CWnd* pParent ) : CDialog(CNewNameDlg::IDD, pParent) { m_NewFileName = _T(""); } CNewNameDlg::~CNewNameDlg() {} void CNewNameDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT_NEWFILENAME, m_NewFileName); } BEGIN_MESSAGE_MAP(CNewNameDlg, CDialog) ON_BN_CLICKED(IDOK, &CNewNameDlg::OnBnClickedOk) END_MESSAGE_MAP() // CNewNameDlg 消息处理程序 void CNewNameDlg::OnBnClickedOk() { // TODO: 在此添加控件通知处理程序代码 CDialog::OnOK(); UpdateData(TRUE); }
运行结果:
简易FTP服务器与客户机:
浏览器程序:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)