//basedef.h
//此头文件定义了结构体和消息
#pragma once
#include <afxsock.h>
#define WM_FILELIST WM_USER + 101 //接收文件列表
#define WM_FILEUPDATE WM_USER + 102 //反映文件下载状态
#define WM_FILEDOWNLOAD WM_USER + 103 //发送文件列表
#define FILELIST 1000 //请求文件列表
#define FILEUPDATE 2000 //请求文件上传
#define FILEDOWNLOAD 3000 //请求文件下载
#define RECVSIZE 1024*16 //一次性发送/接收的数据块大小
//文件传递结构
typedef struct
{
int iCommand;
long lFileOffset;
long lFileLength;
char sFilePath[128];
}MSGFILE;
//请求线程参数
typedef struct
{
char sIP[15]; //IP地址
int iPort; //端口
MSGFILE msgFile; //通信语言结构
LPVOID ptr; //指针
}MSGPARAM;
//文件列表结构
typedef struct
{
long lFileLength;
char sFilePath[128];
}MSGFILELIST;
//反映文件状态的结构
typedef struct
{
long lFileOffset;//偏移
char sFilePath[128];//路径
}MSGFILESTATUS;
//接收线程参数
typedef struct
{
SOCKET sock;
LPVOID ptr;
}PARAMRECV;
//客户端 文件传输类
//
// Ftp_Client.h: interface for the CFtp_Client class.
//
//
#if !defined(AFX_FTP_CLIENT_H__CB684F7E_C9B5_4025_AA2E_F307234CA75C__INCLUDED_)
#define AFX_FTP_CLIENT_H__CB684F7E_C9B5_4025_AA2E_F307234CA75C__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "basedef.h"
#define WM_CONNECTERROR WM_USER + 301
class CFtp_Client
{
public:
CFtp_Client();
virtual ~CFtp_Client();
//创建线程发送请求
void SendRequest(MSGPARAM msgParam);
//设置服务器参数
BOOL InitParam(CWnd* pWnd, char* sIP, int nPort);
//停止所有线程
void StopThread();
protected:
//请求线程
static DWORD WINAPI RequestThread(LPVOID lpParam);
private:
//服务器IP
char m_sIP[15];
//服务器端口
int m_nPort;
//指向窗口的指针
CWnd* m_pWnd;
//停止线程
static BOOL m_bEndThread;
};
#endif // !defined(AFX_FTP_CLIENT_H__CB684F7E_C9B5_4025_AA2E_F307234CA75C__INCLUDED_)
//cpp 文件
// Ftp_Client.cpp: implementation of the CFtp_Client class.
//
//
#include "stdafx.h"
#include "Ftp_Client.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
BOOL CFtp_Client::m_bEndThread = FALSE;
//
// Construction/Destruction
//
CFtp_Client::CFtp_Client()
{
strcpy(m_sIP, "127.0.0.1");
m_nPort = 7000;
m_pWnd = NULL;
}
CFtp_Client::~CFtp_Client()
{
}
BOOL CFtp_Client::InitParam(CWnd* pWnd, char* sIP, int nPort)
{
if (!AfxSocketInit())
{
return FALSE;
}
//保留参数
strcpy(m_sIP, sIP);
m_nPort = nPort;
m_pWnd = pWnd;
return TRUE;
}
//向服务器请求文件列表
void CFtp_Client::SendRequest(MSGPARAM msgParam)
{
//为结构体赋值,作为参数传递到线程
MSGPARAM* pMsgParam = new MSGPARAM;
pMsgParam->ptr = m_pWnd;
strcpy(pMsgParam->sIP, m_sIP);
pMsgParam->iPort = m_nPort;
pMsgParam->msgFile.iCommand = msgParam.msgFile.iCommand;
pMsgParam->msgFile.lFileLength = msgParam.msgFile.lFileLength;
pMsgParam->msgFile.lFileOffset = msgParam.msgFile.lFileOffset;
strcpy(pMsgParam->msgFile.sFilePath, msgParam.msgFile.sFilePath);
DWORD id;
HANDLE h = CreateThread(NULL, 0, RequestThread, pMsgParam, 0, &id);
//创建发送请求并接收反馈的线程
CloseHandle(h);
}
DWORD WINAPI CFtp_Client::RequestThread(LPVOID lpParam)
{
MSGPARAM* pMsgParam = (MSGPARAM*)lpParam;
CWnd* pWnd = (CWnd*)pMsgParam->ptr;
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr(pMsgParam->sIP);
sin.sin_port = htons(pMsgParam->iPort);
//连接成功
if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR)
{
//发送请求
int iSendCnt = send(sock, (char*)&pMsgParam->msgFile, sizeof(pMsgParam->msgFile), 0);
if(pMsgParam->msgFile.iCommand == FILELIST) //如果是请求文件列表
{
pWnd->SendMessage(WM_FILELIST, sock, 0);
}
else if (pMsgParam->msgFile.iCommand == FILEUPDATE)
{
char sRecvBuf[RECVSIZE] = "\0"; //接收缓冲区置空
long lFileOffset = pMsgParam->msgFile.lFileOffset;
//打开文件,打不开则不上传
CFile file;
BOOL bResult = file.Open(pMsgParam->msgFile.sFilePath, CFile::modeRead|CFile::shareDenyNone, NULL);
if(bResult)
{
char sSendBuf[RECVSIZE];//发送缓冲区,16K
while(!CFtp_Client::m_bEndThread && lFileOffset < pMsgParam->msgFile.lFileLength)
{
int iSeek = file.Seek(lFileOffset, CFile::begin);//寻找新的文件偏移,距离开始处
int iReadCnt = file.Read(sSendBuf, RECVSIZE);//读计数器,读到发送缓冲区,一次16K
if (iReadCnt ==0)//读出字节数为0
break;
int iSendCnt = send(sock, sSendBuf, iReadCnt, 0);
if (iSendCnt == -1)
break;
else
lFileOffset += iSendCnt;//修改偏移量
MSGFILESTATUS msgFileStatus;//文件状态结构体
msgFileStatus.lFileOffset = lFileOffset;
strcpy(msgFileStatus.sFilePath, pMsgParam->msgFile.sFilePath);
pWnd->SendMessage(WM_FILEUPDATE, (WPARAM)&msgFileStatus, 0);
}
file.Close();
}
}
else if(pMsgParam->msgFile.iCommand == FILEDOWNLOAD) //如果是请求下载文件
{
char sRecvBuf[RECVSIZE] = "\0"; //接收缓冲区置空
long lFileOffset = pMsgParam->msgFile.lFileOffset;
CFile file;
BOOL bResult = file.Open(pMsgParam->msgFile.sFilePath, CFile::modeWrite|CFile::modeNoTruncate, NULL);
//打开接收端文件,写模式||若创建的文件已存在,不截短。
while(!CFtp_Client::m_bEndThread && bResult && lFileOffset < pMsgParam->msgFile.lFileLength)
{
int iRecvCnt = recv(sock, sRecvBuf, RECVSIZE, 0);
if(iRecvCnt <= 0)
break;
file.Seek(lFileOffset, CFile::begin);
file.Write(sRecvBuf, iRecvCnt);//写到接收缓冲区
lFileOffset += iRecvCnt;//修改偏移
MSGFILESTATUS msgFileStatus;//文件状态结构体
msgFileStatus.lFileOffset = lFileOffset;
strcpy(msgFileStatus.sFilePath, pMsgParam->msgFile.sFilePath);
pWnd->SendMessage(WM_FILEDOWNLOAD, (WPARAM)&msgFileStatus, 0);
}
file.Close();
if(lFileOffset < pMsgParam->msgFile.lFileLength && !CFtp_Client::m_bEndThread) //如果没有下载完,请求续传
{//接收线程未结束&&偏移<文件长度
MSGPARAM* pMsgParamResume = new MSGPARAM;//指向请求线程参数结构体的指针
strcpy(pMsgParamResume->sIP, pMsgParam->sIP);
pMsgParamResume->iPort = pMsgParam->iPort;
pMsgParamResume->ptr = pMsgParam->ptr;
pMsgParamResume->msgFile.iCommand = pMsgParam->msgFile.iCommand ;
pMsgParamResume->msgFile.lFileLength = pMsgParam->msgFile.lFileLength;
pMsgParamResume->msgFile.lFileOffset = lFileOffset;
strcpy(pMsgParamResume->msgFile.sFilePath, pMsgParam->msgFile.sFilePath);
DWORD id;
HANDLE h = CreateThread(NULL, 0, RequestThread, pMsgParamResume, 0, &id);
//递归调用
CloseHandle(h);
}
}
}
else
{
pWnd->SendMessage(WM_CONNECTERROR, 0, 0);
}
closesocket(sock);
delete pMsgParam;
return 0;
}
void CFtp_Client::StopThread()
{
m_bEndThread = TRUE;
}
//对话框头文件
// Client_FTPDlg.h : header file
//
#if !defined(AFX_CLIENT_FTPDLG_H__E7F99F34_0BD2_4B11_8FF7_D958887D2368__INCLUDED_)
#define AFX_CLIENT_FTPDLG_H__E7F99F34_0BD2_4B11_8FF7_D958887D2368__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "Label.h"
#include "Ftp_Client.h"
/
// CClient_FTPDlg dialog
class CClient_FTPDlg : public CDialog
{
// Construction
public:
void InitListColumn();
CClient_FTPDlg(CWnd* pParent = NULL); // standard constructor
CFtp_Client *m_pFtpClient; //上传下载类对象
BOOL m_bConnected; //连接状态
long m_lFileSize; //文件大小
CString m_strFileName;//文件名
CString m_strFilePath;//文件路径
// Dialog Data
//{{AFX_DATA(CClient_FTPDlg)
enum { IDD = IDD_CLIENT_FTP_DIALOG };
CProgressCtrl m_Progress;
CListCtrl m_ListFile;
CIPAddressCtrl m_IPAddr;
CLabel m_LabProgress;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CClient_FTPDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CClient_FTPDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnBtnScan();
afx_msg void OnBtnUpdate();
afx_msg void OnDestroy();
afx_msg void OnDblclkListFile(NMHDR* pNMHDR, LRESULT* pResult);
//}}AFX_MSG
afx_msg LRESULT OnFileDownload(WPARAM wp, LPARAM lp);
afx_msg LRESULT OnFileUpdate(WPARAM wp, LPARAM lp);
afx_msg LRESULT OnFileList(WPARAM wp, LPARAM lp);
afx_msg LRESULT OnConnectError(WPARAM wp, LPARAM lp);
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_CLIENT_FTPDLG_H__E7F99F34_0BD2_4B11_8FF7_D958887D2368__INCLUDED_)
//对话框 cpp 文件
// Client_FTPDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Client_FTP.h"
#include "Client_FTPDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CClient_FTPDlg dialog
CClient_FTPDlg::CClient_FTPDlg(CWnd* pParent /*=NULL*/)
: CDialog(CClient_FTPDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CClient_FTPDlg)
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_bConnected = FALSE;
m_strFileName = _T("");
m_lFileSize = 0;
}
void CClient_FTPDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CClient_FTPDlg)
DDX_Control(pDX, IDC_PROGRESS1, m_Progress);
DDX_Control(pDX, IDC_LIST_FILE, m_ListFile);
DDX_Control(pDX, IDC_IPADDRESS1, m_IPAddr);
DDX_Control(pDX, IDC_STATIC_PROGRESS, m_LabProgress);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CClient_FTPDlg, CDialog)
//{{AFX_MSG_MAP(CClient_FTPDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_ERASEBKGND()
ON_BN_CLICKED(IDC_BTN_SCAN, OnBtnScan)
ON_BN_CLICKED(IDC_BTN_UPDATE, OnBtnUpdate)
ON_WM_DESTROY()
ON_NOTIFY(NM_DBLCLK, IDC_LIST_FILE, OnDblclkListFile)
//}}AFX_MSG_MAP
ON_MESSAGE(WM_FILELIST, OnFileList)
ON_MESSAGE(WM_FILEUPDATE, OnFileUpdate)
ON_MESSAGE(WM_FILEDOWNLOAD, OnFileDownload)
ON_MESSAGE(WM_CONNECTERROR, OnConnectError)
END_MESSAGE_MAP()
/
// CClient_FTPDlg message handlers
BOOL CClient_FTPDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
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);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
m_LabProgress.SetFontSize(20);
m_LabProgress.SetBkColor(BACKCOLOR);
m_Progress.SetRange(0, 100);
m_Progress.SetPos(0);
m_LabProgress.SetText(_T("0%"));
m_IPAddr.SetAddress(127, 0, 0, 1);
SetDlgItemInt(IDC_EDIT_PORT, 7000);
InitListColumn();
m_pFtpClient = new CFtp_Client();
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CClient_FTPDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CClient_FTPDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
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;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CClient_FTPDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
BOOL CClient_FTPDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
//更改背景颜色
CRect rect;
GetClientRect(&rect);
pDC->FillSolidRect(&rect, BACKCOLOR);
return TRUE;
// return CDialog::OnEraseBkgnd(pDC);
}
void CClient_FTPDlg::OnBtnScan()
{
// TODO: Add your control notification handler code here
//文件选择
CFileDialog fileDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "All Files(*.*)|*.*||", this);
if(fileDlg.DoModal() == IDOK)
{
//获取文件路径
CString strPathName = fileDlg.GetPathName();
CFile file;
BOOL bOpen = file.Open(strPathName, CFile::modeRead|CFile::shareDenyNone, NULL);
if(!bOpen)
{
MessageBox("打开失败,请确认路径再重试!");
return;
}
m_lFileSize = file.GetLength();
m_strFilePath = strPathName;
m_strFileName = fileDlg.GetFileName();
file.Close();
SetDlgItemText(IDC_EDIT_PATH, strPathName);
//获取服务器IP和端口
BYTE btye1, btye2, btye3, btye4;
m_IPAddr.GetAddress(btye1, btye2, btye3, btye4);
char sIP[15];
sprintf(sIP, "%d.%d.%d.%d", btye1, btye2, btye3, btye4);//显示IP地址
int nPort = GetDlgItemInt(IDC_EDIT_PORT);
CString strIP(sIP);
if (strIP.IsEmpty())
{
AfxMessageBox(_T("请输入服务器IP地址!"));
return;
}
if (nPort<0)
{
AfxMessageBox(_T("请输入服务器端口!"));
return;
}
m_pFtpClient->InitParam(this, sIP, nPort);
//发送文件信息到服务器
MSGPARAM msgParam;
msgParam.msgFile.iCommand = FILELIST;
msgParam.msgFile.lFileLength = m_lFileSize;
msgParam.msgFile.lFileOffset = 0;
strcpy(msgParam.msgFile.sFilePath, strPathName);
m_pFtpClient->SendRequest(msgParam);
}
}
void CClient_FTPDlg::OnBtnUpdate()
{
// TODO: Add your control notification handler code here
CString strPathName;
GetDlgItemText(IDC_EDIT_PATH, strPathName);
//是否有要上传的文件
if (strPathName.IsEmpty())
{
AfxMessageBox(_T("请先选择要上传的文件!"));
return;
}
//上传文件
MSGPARAM msgParam;
msgParam.msgFile.iCommand = FILEUPDATE;
msgParam.msgFile.lFileLength = m_lFileSize;
msgParam.msgFile.lFileOffset = 0;
strcpy(msgParam.msgFile.sFilePath, strPathName);
m_pFtpClient->SendRequest(msgParam);
}
void CClient_FTPDlg::InitListColumn()
{
int iWidth = 50;
m_ListFile.InsertColumn(0, "文件名", LVCFMT_LEFT, 3*iWidth, -1);
m_ListFile.InsertColumn(1, "文件大小", LVCFMT_LEFT, 2*iWidth, -1);
m_ListFile.InsertColumn(2, "下载速度", LVCFMT_LEFT, 2*iWidth, -1);
m_ListFile.InsertColumn(3, "下载状态", LVCFMT_LEFT, 2*iWidth, -1);
m_ListFile.InsertColumn(4, "下载时间", LVCFMT_LEFT, 2*iWidth, -1);
m_ListFile.InsertColumn(5, "文件保存路径", LVCFMT_LEFT, 5*iWidth, -1);
m_ListFile.InsertColumn(6, "时间标记", LVCFMT_LEFT, 2*iWidth, -1);
//插入列:左对齐,无子列
m_ListFile.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
}
void CClient_FTPDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
if(m_pFtpClient != NULL)
{
m_pFtpClient->StopThread();
delete m_pFtpClient;
}
}
LRESULT CClient_FTPDlg::OnFileList(WPARAM wp, LPARAM lp)
{
SOCKET sock = (SOCKET)wp;
MSGFILELIST msgFileList;
msgFileList.lFileLength = m_lFileSize;
strcpy(msgFileList.sFilePath, m_strFilePath.GetBuffer(0));
//发送文件信息
int iSendCnt = send(sock, (char*)&msgFileList, sizeof(msgFileList), 0);
return 0;
}
LRESULT CClient_FTPDlg::OnFileUpdate(WPARAM wp, LPARAM lp)
{
MSGFILESTATUS* pmsg = (MSGFILESTATUS*)wp;
int nPos = int((float)pmsg->lFileOffset/m_lFileSize*100);
m_Progress.SetPos(nPos);
CString strStatus;
strStatus.Format("%d%%", nPos);
m_LabProgress.SetText(strStatus);
if (nPos<100)
return 0;
CString strFileSize;//显示文件大小
strFileSize.Format("%0.2fk", (float)m_lFileSize/1024);
int iItem = m_ListFile.GetItemCount();//获取文件列表元素个数
LV_ITEM lvi;//结构体ListView Item,指定或接收属性
lvi.mask = LVIF_TEXT|LVIF_PARAM;
lvi.iItem = iItem;
lvi.iSubItem = 0;
lvi.lParam = m_lFileSize;
lvi.pszText = m_strFileName.GetBuffer(0);//返回CString中指向字符串的指针
m_ListFile.InsertItem(&lvi);//插入列表
m_ListFile.SetItemText(iItem, 1, strFileSize.GetBuffer(0));
m_ListFile.SetItemText(iItem, 5, m_strFilePath.GetBuffer(0));
return 0;
}
LRESULT CClient_FTPDlg::OnFileDownload(WPARAM wp, LPARAM lp)
{
MSGFILESTATUS* pmsg = (MSGFILESTATUS*)wp;
CString strPath, strName;
strPath.Format("%s", pmsg->sFilePath);
int iPos = strPath.ReverseFind('\\');
strName = strPath.Right(strPath.GetLength() - iPos - 1);
int iTotal = m_ListFile.GetItemCount();
int iSel = 0;
for(; iSel<iTotal; iSel++)
{
CString strListPath;
strListPath = m_ListFile.GetItemText(iSel, 0);
if(strName.Compare(strListPath) == 0)//路径相同
break;
}
if(iSel == iTotal)
return 1;
long lFileLength = m_ListFile.GetItemData(iSel);
CString strStatus;
strStatus.Format("%0.2f%%", (float)pmsg->lFileOffset/lFileLength*100);
//显示状态 %,精确到小数点后两位
m_ListFile.SetItemText(iTotal-1, 3, strStatus.GetBuffer(0));
//显示时间
DWORD dwNowTick, dwStartTick;//毫秒
dwNowTick = GetTickCount();
sscanf(m_ListFile.GetItemText(iSel, 6), "%u", &dwStartTick);
long iEllapsed = (dwNowTick-dwStartTick);//间隔:秒
strStatus.Format("%dms", iEllapsed);
m_ListFile.SetItemText(iSel, 4, strStatus.GetBuffer(0));
//显示速度
if(iEllapsed > 0)
{
strStatus.Format("%dk/s", (pmsg->lFileOffset/1024/iEllapsed)*1000);
m_ListFile.SetItemText(iSel, 2, strStatus.GetBuffer(0));
}
return 0;
}
LRESULT CClient_FTPDlg::OnConnectError(WPARAM wp, LPARAM lp)
{
AfxMessageBox(_T("服务器连接失败!"));
return 0;
}
void CClient_FTPDlg::OnDblclkListFile(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
NMLISTVIEW* pListView = (NMLISTVIEW*)pNMHDR;//结构体,ListView的通知信息
int iSel = pListView->iItem;
if(iSel == -1)
return;
CString strFileName = m_ListFile.GetItemText(iSel, 0);
CFileDialog dlg(FALSE, NULL, strFileName.GetBuffer(0), OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "All Files(*.*)|*.*||", this);
//打开一个保存对话框,隐藏readonly||覆盖确认
if(dlg.DoModal() != IDOK)
return;
CString strClientPath = dlg.GetPathName();
//得到客户端保存路径
CFile file;
BOOL bOpen = file.Open(strClientPath, CFile::modeCreate|CFile::modeWrite, NULL);
if(!bOpen)
{
MessageBox("文件创建或打开失败,请确认路径再重试!");
return;
}
file.Close();
MSGPARAM msgParam;
msgParam.msgFile.iCommand = FILEDOWNLOAD;
msgParam.msgFile.lFileLength = m_ListFile.GetItemData(iSel);
msgParam.msgFile.lFileOffset = 0;
strcpy(msgParam.msgFile.sFilePath, strClientPath);
//子项目,第6列
DWORD dwStartTick = GetTickCount();
char sStartTick[20];
sprintf(sStartTick, "%u", dwStartTick);
m_ListFile.SetItemText(iSel, 6, sStartTick);
m_pFtpClient->SendRequest(msgParam);//调用请求线程
*pResult = 0;
}