首页 > 编程 > C++ > 正文

VC++ 实现文件上传下载服务器端

2019-11-08 20:18:54
字体:
来源:转载
供稿:网友


#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_Server.h: interface for the CFtp_Server class.////////////////////////////////////////////////////////////////////////

#if !defined(AFX_FTP_SERVER_H__DCFE7BE8_C212_475E_AAC8_811898047B46__INCLUDED_)#define AFX_FTP_SERVER_H__DCFE7BE8_C212_475E_AAC8_811898047B46__INCLUDED_

#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000

#include "basedef.h"#define WM_FINISHUPDATE WM_USER+401

class CFtp_Server  {public: CFtp_Server(); virtual ~CFtp_Server();

 BOOL StartListen(CWnd *pWnd, int nPort, char *sPath); void StopListen();

protected: //监听线程 static DWord WINAPI ListenThread(LPVOID lpParam);  //接收线程 static DWORD WINAPI RecvThread(LPVOID lpParam);private: //监听线程结束符 BOOL m_bEndListenThread;

 //监听端口 int m_iListenPort;

 //窗口指针 CWnd* m_pWnd;

 //服务器套接字 SOCKET m_socket;

 //保存本机地址 SOCKADDR_IN m_sin;

 //存储路径 char m_sPath[128];};

#endif // !defined(AFX_FTP_SERVER_H__DCFE7BE8_C212_475E_AAC8_811898047B46__INCLUDED_)

//服务器端 类 CPP

// Ftp_Server.cpp: implementation of the CFtp_Server class.////////////////////////////////////////////////////////////////////////

#include "stdafx.h"#include "Ftp_Server.h"

#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#define new DEBUG_NEW#endif

//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////

CFtp_Server::CFtp_Server(){}

CFtp_Server::~CFtp_Server(){}

BOOL CFtp_Server::StartListen(CWnd *pWnd, int nPort, char *sPath){ //初始化套接字 if (!AfxSocketInit()) {  return FALSE; }

 //获得端口号和窗口指针 m_iListenPort = nPort; m_pWnd = pWnd; strcpy(m_sPath, sPath);

 m_bEndListenThread = FALSE;//开始监听

 DWORD id; HANDLE h = CreateThread(NULL, 0, ListenThread, this, 0, &id);//创建句柄 //线程要执行的函数为ThreadListen,将this指针传递给线程,线程ID为id,创建成功,返回新线程的一个句柄 CloseHandle(h); //关闭句柄,并不终止线程

 return TRUE;}

void CFtp_Server::StopListen(){ m_bEndListenThread = TRUE; Sleep(100); closesocket(m_socket);}

DWORD WINAPI CFtp_Server::ListenThread(LPVOID lpParam){ CFtp_Server* pServer = (CFtp_Server*)lpParam;

 SOCKET sockListen = socket(AF_INET, SOCK_STREAM, 0);//创建socket //地址家族为internet,用于TCP和UDP,字节流,特定的协议

 SOCKADDR_IN sin; //转换地址 sin.sin_family = AF_INET; sin.sin_addr.s_addr = 0; //ip地址,以网路字节顺序。 sin.sin_port = htons(pServer->m_iListenPort);

 if (bind(sockListen, (SOCKADDR*)&sin, sizeof(sin)) == SOCKET_ERROR) {  closesocket(sockListen); //关闭socket  return FALSE; }

 if (listen(sockListen, 5) == SOCKET_ERROR) {//若将socket置于监听失败  closesocket(sockListen);  return FALSE; }

 fd_set fdListen;//结构体,将socket放进一个集合 timeval seltime;//结构体,指定时间值(秒+毫秒) seltime.tv_sec = 0; //秒 seltime.tv_usec = 10000;//毫秒==10秒

 while (!pServer->m_bEndListenThread) {//服务器在监听状态  FD_ZERO(&fdListen);//将集合清零  FD_SET(sockListen, &fdListen);//将socket添加到set中

  if (select(0, &fdListen, NULL, NULL, &seltime) <= 0 || !FD_ISSET(sockListen, &fdListen))   continue;  //如果在规定时间内,set中无socket可读出||socket不在set中,结束本次循环,继续下次循环

  int len = sizeof(sin);  SOCKET sock = accept(sockListen, (SOCKADDR*)&sin, &len);  //接受socket上的连接

  PARAMRECV* pParamRecv = new PARAMRECV;//结构体,接收线程参数  pParamRecv->sock = sock;  pParamRecv->ptr = pServer;

  DWORD id;  HANDLE h = CreateThread(NULL, 0, RecvThread, pParamRecv, 0, &id);  //创建ThreadRecv线程,将pParamRecv传递给线程  CloseHandle(h); }

 return 0;}

DWORD WINAPI CFtp_Server::RecvThread(LPVOID lpParam){ PARAMRECV* pParam = (PARAMRECV*)lpParam;//指向接收线程的指针 CFtp_Server* pServer = (CFtp_Server*)pParam->ptr;//指向Server的指针

 fd_set fdRecv;//结构体,接收线程集合 timeval seltime;//结构体,指定时间值==10s seltime.tv_sec = 0; seltime.tv_usec = 10000;

 while (1) {  FD_ZERO(&fdRecv);//集合清零  FD_SET(pParam->sock, &fdRecv);//将已连接的socket加入集合

  if (select(0, &fdRecv, NULL, NULL, &seltime) <= 0 || !FD_ISSET(pParam->sock, &fdRecv))   continue;  //如果在指定时间内,结构体内无可读接收线程||sock不在结构体内

  MSGFILE msgFile;  int iRecvCnt = recv(pParam->sock, (char*)&msgFile, sizeof(msgFile), 0);  //成功,返回接收字节数;正常结束,返回0;否则<0  if (iRecvCnt <= 0)   break;

  //请求文件列表  if (msgFile.iCommand == FILELIST)  {   while (!pServer->m_bEndListenThread)   {    MSGFILELIST msgFileList;    iRecvCnt = recv(pParam->sock, (char*)&msgFileList, sizeof(msgFileList), 0);    if (iRecvCnt <= 0)     break;

    pServer->m_pWnd->SendMessage(WM_FILELIST, (WPARAM)&msgFileList, 0);   }  }

  //请求文件下载  else if (msgFile.iCommand == FILEDOWNLOAD)  {   long lFileOffset = msgFile.lFileOffset;//文件偏移

   CFile file;   CString strPath, strName;   strPath.Format("%s", msgFile.sFilePath);   int iPos = strPath.ReverseFind('//');   strName = strPath.Right(strPath.GetLength() - iPos - 1);   strPath.Format("%s", pServer->m_sPath);   strPath += strName;

   BOOL bResult = file.Open(strPath, CFile::modeRead | CFile::shareDenyNone, NULL);   //打开指定路径的文件,只读||可共享,成功,返回非零;否则,0   if (!bResult)   {    break;   }

   char sSendBuf[RECVSIZE];//发送缓冲区,16K      while (lFileOffset < msgFile.lFileLength)   {    int iSeek = file.Seek(lFileOffset, CFile::begin);//寻找新的文件偏移,距离开始处    int iReadCnt = file.Read(sSendBuf, RECVSIZE);    if (iReadCnt == 0)     break;

    int iSendCnt = send(pParam->sock, sSendBuf, iReadCnt, 0);    //如果发送失败就终止线程    if (iSendCnt == -1)     break;    else     lFileOffset += iSendCnt;//修改偏移量   }

   file.Close();  }

  //请求文件上传  else if (msgFile.iCommand == FILEUPDATE)  {   char sRecvBuf[RECVSIZE] = "/0"; //接收缓冲区置空   long lFileOffset = msgFile.lFileOffset;   CFile file;

   //将客户端路径改为服务端保存路径   CString strPath, strName;   strPath.Format("%s", msgFile.sFilePath);   int iPos = strPath.ReverseFind('//');   strName = strPath.Right(strPath.GetLength() - iPos - 1);   strPath.Format("%s", pServer->m_sPath);   strPath += strName;

   BOOL bResult = file.Open(strPath, CFile::modeCreate | CFile::modeWrite | CFile::modeNoTruncate, NULL);   //打开接收端文件,写模式||若创建的文件已存在,不截短。   while (bResult && lFileOffset < msgFile.lFileLength)   {    int iRecvCnt = recv(pParam->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, msgFile.sFilePath);    pServer->m_pWnd->SendMessage(WM_FILEUPDATE, (WPARAM)&msgFileStatus, 0);   }   file.Close();   pServer->m_pWnd->SendMessage(WM_FINISHUPDATE, 0, 0);  }

  break; } delete pParam;

 return 0;}

//对话框 头文件

// Server_FTPDlg.h : header file//

#if !defined(AFX_SERVER_FTPDLG_H__492B251E_B713_4E0F_A5A4_C1BC9EB8EF08__INCLUDED_)#define AFX_SERVER_FTPDLG_H__492B251E_B713_4E0F_A5A4_C1BC9EB8EF08__INCLUDED_

#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000

#include "Ftp_Server.h"/////////////////////////////////////////////////////////////////////////////// CServer_FTPDlg dialog

class CServer_FTPDlg : public CDialog{// Constructionpublic: void InitListColumn(); CServer_FTPDlg(CWnd* pParent = NULL); // standard constructor

 CFtp_Server *m_pFtp_Server;

 BOOL m_bConnected; //已连接 int m_nUpdateNum; //已上传文件// Dialog Data //{{AFX_DATA(CServer_FTPDlg) enum { IDD = IDD_SERVER_FTP_DIALOG }; CListCtrl m_ListFile; int  m_nPort; //}}AFX_DATA

 // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CServer_FTPDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL

// Implementationprotected: HICON m_hIcon;

 // Generated message map functions //{{AFX_MSG(CServer_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 OnBtnListen(); afx_msg void OnBtnScan(); afx_msg void OnDestroy(); //}}AFX_MSG afx_msg LRESULT OnFileList(WPARAM wp, LPARAM lp); afx_msg LRESULT OnFileUpdate(WPARAM wp, LPARAM lp); afx_msg LRESULT OnFinishUpdate(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_SERVER_FTPDLG_H__492B251E_B713_4E0F_A5A4_C1BC9EB8EF08__INCLUDED_)

//对话框 CPP文件

// Server_FTPDlg.cpp : implementation file//

#include "stdafx.h"#include "Server_FTP.h"#include "Server_FTPDlg.h"

#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic 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

// Implementationprotected: //{{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_MAPEND_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////// CServer_FTPDlg dialog

CServer_FTPDlg::CServer_FTPDlg(CWnd* pParent /*=NULL*/) : CDialog(CServer_FTPDlg::IDD, pParent){ //{{AFX_DATA_INIT(CServer_FTPDlg) m_nPort = 7000; //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_bConnected = FALSE; m_nUpdateNum = 0;}

void CServer_FTPDlg::DoDataExchange(CDataExchange* pDX){ CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CServer_FTPDlg) DDX_Control(pDX, IDC_LIST_FILE, m_ListFile); DDX_Text(pDX, IDC_EDIT_PORT, m_nPort); //}}AFX_DATA_MAP}

BEGIN_MESSAGE_MAP(CServer_FTPDlg, CDialog) //{{AFX_MSG_MAP(CServer_FTPDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_ERASEBKGND() ON_BN_CLICKED(IDC_BTN_LISTEN, OnBtnListen) ON_BN_CLICKED(IDC_BTN_SCAN, OnBtnScan) ON_WM_DESTROY() //}}AFX_MSG_MAP ON_MESSAGE(WM_FILELIST, OnFileList) ON_MESSAGE(WM_FILEUPDATE, OnFileUpdate) ON_MESSAGE(WM_FINISHUPDATE, OnFinishUpdate)END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////// CServer_FTPDlg message handlers

BOOL CServer_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  InitListColumn();

 m_pFtp_Server = new CFtp_Server(); // TODO: Add extra initialization here  return TRUE;  // return TRUE  unless you set the focus to a control}

void CServer_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 CServer_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 CServer_FTPDlg::OnQueryDragIcon(){ return (HCURSOR) m_hIcon;}

BOOL CServer_FTPDlg::OnEraseBkgnd(CDC* pDC) { // TODO: Add your message handler code here and/or call default //更改背景颜色 CRect rect; GetClientRect(&rect); pDC->FillSolidRect(&rect, RGB(202, 225, 243)); return TRUE; // return CDialog::OnEraseBkgnd(pDC);}

void CServer_FTPDlg::OnBtnListen() { // TODO: Add your control notification handler code here if (m_bConnected) {  m_pFtp_Server->StopListen();  SetDlgItemText(IDC_BTN_LISTEN, _T("启动监听"));  GetDlgItem(IDC_EDIT_PORT)->EnableWindow(TRUE);  m_bConnected = FALSE;  return; } CString sPath; GetDlgItemText(IDC_EDIT_PATH, sPath); if (sPath.IsEmpty()) {  AfxMessageBox(_T("请先设置文件存储路径!"));  return; } int nPort = GetDlgItemInt(IDC_EDIT_PORT); if (m_pFtp_Server->StartListen(this, nPort, sPath.GetBuffer(0))) {  SetDlgItemText(IDC_BTN_LISTEN, _T("停止监听"));  GetDlgItem(IDC_EDIT_PORT)->EnableWindow(FALSE);  m_bConnected = TRUE;  return; }

 AfxMessageBox(_T("服务器启动失败!"));}

void CServer_FTPDlg::OnBtnScan() { // TODO: Add your control notification handler code here BROWSEINFO bi; //定义后面将被SHBrowseForFolder调用参数 char buffer[MAX_PATH];  ZeroMemory(buffer,MAX_PATH);  bi.hwndOwner = this->m_hWnd; bi.pidlRoot = NULL;  bi.pszDisplayName=buffer;  bi.lpszTitle = "指定文件夹";  bi.ulFlags = BIF_RETURNONLYFSDIRS;  bi.lpfn = NULL;  bi.lParam = 0;  bi.iImage = 0; LPITEMIDLIST pList = NULL;  if((pList=SHBrowseForFolder(&bi)) != NULL)  {  char path[MAX_PATH];  ZeroMemory(path,MAX_PATH);  SHGetPathFromIDList(pList,path);//根据你设置的属性  打开 返回路径到path  SetDlgItemText(IDC_EDIT_PATH, path); }}

void CServer_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 CServer_FTPDlg::OnDestroy() { CDialog::OnDestroy();  // TODO: Add your message handler code here if(m_pFtp_Server != NULL) {  m_pFtp_Server->StopListen();  delete m_pFtp_Server; }}

LRESULT CServer_FTPDlg::OnFileUpdate(WPARAM wp, LPARAM lp){ MSGFILESTATUS* pmsg = (MSGFILESTATUS*)wp; CString strPath; strPath.Format("%s", pmsg->sFilePath); int iTotal = m_ListFile.GetItemCount(); int iSel = 0; for(; iSel<iTotal; iSel++) {  CString strListPath;  strListPath = m_ListFile.GetItemText(iSel, 5);  if(strPath.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 CServer_FTPDlg::OnFileList(WPARAM wp, LPARAM lp){ MSGFILELIST* pmsgList = (MSGFILELIST*)wp; int iItem = m_ListFile.GetItemCount(); for (int i = m_nUpdateNum; i < iItem; i++) {  m_ListFile.DeleteItem(i); } iItem = m_nUpdateNum;

 CString strServerPath, strFileName, strFileSize; strServerPath.Format("%s", pmsgList->sFilePath); int iPos = strServerPath.ReverseFind('//'); //设置文件名到缓冲区 strFileName = strServerPath.Right(strServerPath.GetLength()-iPos-1); strFileSize.Format("%0.2fk", (float)pmsgList->lFileLength/1024);  LV_ITEM lvi; lvi.mask = LVIF_TEXT|LVIF_PARAM; lvi.iItem = iItem; lvi.iSubItem = 0; lvi.lParam = pmsgList->lFileLength; //显示 lvi.pszText = strFileName.GetBuffer(0); m_ListFile.InsertItem(&lvi); m_ListFile.SetItemText(iItem, 1, strFileSize.GetBuffer(0)); m_ListFile.SetItemText(iItem, 5, strServerPath.GetBuffer(0));

 //设置初始时间点 DWORD dwStartTick = GetTickCount(); char sStartTick[20]; sprintf(sStartTick, "%u", dwStartTick); m_ListFile.SetItemText(iItem, 6, sStartTick);

 return 0;}

LRESULT CServer_FTPDlg::OnFinishUpdate(WPARAM wp, LPARAM lp){ ++ m_nUpdateNum; return 0;}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选