⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftpdemo.cpp

📁 利用辅助线程从匿名FTP服务器上下载文件
💻 CPP
字号:
// FTPDemo.cpp : Defines the entry point for the application.
//

#include "stdafx.h"

//全局变量
HINSTANCE   hInst ;
TCHAR       szAppName[] = TEXT ("FTPDEMO");

//函数声明
LRESULT CALLBACK    WndProc (HWND, UINT, WPARAM, LPARAM) ;
BOOL    CALLBACK    DlgProc (HWND, UINT, WPARAM, LPARAM) ;
VOID                FtpThread (PVOID) ;
VOID                ButtonSwitch (HWND, HWND, TCHAR *) ;
FILELIST *          GetFileList (VOID) ;
int                 Compare (const void * pinfo1, const void * pinfo2) ;


int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

     hInst = hInstance ;

     wndclass.style         = 0 ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = NULL ;
     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;

     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"), 
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("从匿名服务器下载文件的Demo"),
                          WS_OVERLAPPEDWINDOW | WS_VSCROLL,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;

     ShowWindow (hwnd, nCmdShow) ;
     UpdateWindow (hwnd) ;

     //此句用于窗口显示后立即检查本地是否有新的文件

     SendMessage (hwnd, WM_USER_CHECKFILES, 0, 0) ;

     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static FILELIST * plist ;
     static int        cxClient, cyClient, cxChar, cyChar ;
     HDC               hdc ;
     int               i ;
     PAINTSTRUCT       ps ;
     SCROLLINFO        si ;
     SYSTEMTIME        st ;
     TCHAR             szFilename [MAX_PATH] ;

     switch (message)
     {
     case WM_CREATE:
          cxChar = LOWORD (GetDialogBaseUnits ()) ;
          cyChar = HIWORD (GetDialogBaseUnits ()) ;
          return 0 ;

     case WM_SIZE:
          cxClient = LOWORD (lParam) ;
          cyClient = HIWORD (lParam) ;

          si.cbSize = sizeof (SCROLLINFO) ;
          si.fMask  = SIF_RANGE | SIF_PAGE ;
          si.nMin   = 0 ;
          si.nMax   = plist ? plist->iNum - 1 : 0 ;
          si.nPage  = cyClient / cyChar ;

          SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
          return 0 ;

     case WM_VSCROLL:
          si.cbSize = sizeof (SCROLLINFO) ;
          si.fMask  = SIF_POS | SIF_RANGE | SIF_PAGE ;
          GetScrollInfo (hwnd, SB_VERT, &si) ;

          switch (LOWORD (wParam))
          {
          case SB_LINEDOWN:       si.nPos += 1 ;              break ;
          case SB_LINEUP:         si.nPos -= 1 ;              break ;
          case SB_PAGEDOWN:       si.nPos += si.nPage ;       break ;
          case SB_PAGEUP:         si.nPos -= si.nPage ;       break ;
          case SB_THUMBPOSITION:  si.nPos = HIWORD (wParam) ; break ;
          default:                return 0 ;
          }
          si.fMask = SIF_POS ;
          SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
          InvalidateRect (hwnd, NULL, TRUE) ;
          return 0 ;



     case WM_USER_CHECKFILES:
         //得到系统日期并用以组织文件名字

          GetSystemTime (&st);
          wsprintf (szFilename, TEXT ("FTPDEMO%04i%02i.TXT"), st.wYear, st.wMonth);//每月更新FTPDEMOyyyymm.TXT

          //检查当前目录是否存在该文件,如果存在则读取所有文件
          //函数GetFileAttributes调用失败后将返回0xFFFFFFFF
          if (GetFileAttributes (szFilename) != (DWORD) -1)
          {
               SendMessage (hwnd, WM_USER_GETFILES, 0, 0) ;
               return 0 ;
          }
          //否则从Internet得到该文件
          //测试当前目录所在驱动器是否是CD-ROM类型,因为一般来说CD-ROM不可写
          if (GetDriveType (NULL) == DRIVE_CDROM)
          {
               MessageBox (hwnd, TEXT ("Cannot run this program from CD-ROM!"),szAppName, MB_OK | MB_ICONEXCLAMATION) ;
               return 0 ;
          }
          //询问用户是否下载文件
          if (IDYES == MessageBox (hwnd, TEXT ("从Internet下载新文件?"),szAppName, MB_YESNO | MB_ICONQUESTION))
			  DialogBox (hInst, szAppName, hwnd, DlgProc);

          //更新主窗口
          SendMessage (hwnd, WM_USER_GETFILES, 0, 0);
          return 0 ;

     case WM_USER_GETFILES:
          SetCursor (LoadCursor (NULL, IDC_WAIT));
          ShowCursor (TRUE) ;

          //将所有的FTPDEMOyyyymm.TXT档案读到动态配置的FILELIST型态结构中

          plist = GetFileList () ;

          ShowCursor (FALSE) ;
          SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

          //模拟WM_SIZE message,然後在其显示区域显示这些档案的内容

          SendMessage (hwnd, WM_SIZE, 0, MAKELONG (cxClient, cyClient)) ;
          InvalidateRect (hwnd, NULL, TRUE) ;
          return 0 ;

     case WM_PAINT:
          hdc = BeginPaint (hwnd, &ps) ;
          SetTextAlign (hdc, TA_UPDATECP) ;

          si.cbSize = sizeof (SCROLLINFO) ;
          si.fMask  = SIF_POS ;
          GetScrollInfo (hwnd, SB_VERT, &si) ;

          if (plist)
          {
               for (i = 0 ; i < plist->iNum ; i++)
               {
                    MoveToEx (hdc, cxChar, (i - si.nPos) * cyChar, NULL) ;
                    TextOut  (hdc, 0, 0, plist->info[i].szFilename,lstrlen (plist->info[i].szFilename)) ;
                    TextOut  (hdc, 0, 0, TEXT (": "), 2) ;
                    TextOutA (hdc, 0, 0, plist->info[i].szContents,strlen (plist->info[i].szContents)) ;
               }
          }
          EndPaint (hwnd, &ps) ;
          return 0 ;

     case WM_DESTROY:
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

BOOL CALLBACK DlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static PARAMS params ;

     switch (message)
     {
     case WM_INITDIALOG:
          params.bContinue = TRUE ;
          params.hwnd = hwnd;
          _beginthread (FtpThread, 0, &params);
          return TRUE ;

     case WM_COMMAND:
          switch (LOWORD (wParam))
          {
          case IDCANCEL:           //取消下载
               params.bContinue = FALSE ;
               return TRUE ;

          case IDOK:               //退出模态对话框
               EndDialog (hwnd, 0) ;
               return TRUE ;
          }
     }
     return FALSE ;
}

/*----------------------------------------------------------------------
   FtpThread: 从FTP server上读取文件并将他们拷贝到本地磁盘中
  ----------------------------------------------------------------------*/

void FtpThread (PVOID parg)
{
     BOOL            bSuccess ;
     HINTERNET       hIntSession, hFtpSession, hFind ;
     HWND            hwndStatus, hwndButton ;
     PARAMS *        pparams;
     TCHAR           szBuffer [64] ;
     WIN32_FIND_DATA finddata ;

     pparams = (PARAMS *)parg ;
	 //用hwndStatus代号呼叫SetWindowText来让使用者知道进展情况,这里指的是对话方块中间的静态文字区
     hwndButton = GetDlgItem (pparams->hwnd, IDCANCEL);
     hwndStatus = GetDlgItem (pparams->hwnd, IDC_MYSTATUS);

     hIntSession = InternetOpen (szAppName, INTERNET_OPEN_TYPE_PRECONFIG,NULL, NULL, INTERNET_FLAG_ASYNC) ;

     if (hIntSession == NULL)
     {
          wsprintf (szBuffer, TEXT ("InternetOpen error %i"), GetLastError ()) ;
          ButtonSwitch (hwndStatus, hwndButton, szBuffer) ;
          _endthread () ;
     }

     SetWindowText (hwndStatus, TEXT ("Internet session opened...")) ;

     //检查用户是否按下了CANCEL

     if (!pparams->bContinue)
     {
          InternetCloseHandle (hIntSession) ;
          ButtonSwitch (hwndStatus, hwndButton, NULL) ;
          _endthread () ;
     }

     hFtpSession = InternetConnect (hIntSession, FTPSERVER,INTERNET_DEFAULT_FTP_PORT,
                                    NULL, NULL, INTERNET_SERVICE_FTP, 0, 0) ;
     if (hFtpSession == NULL)
     {
          InternetCloseHandle (hIntSession) ;
          wsprintf (szBuffer,TEXT ("InternetConnect error %i"),GetLastError ()) ;
          ButtonSwitch (hwndStatus, hwndButton, szBuffer) ;
          _endthread () ;
     }

     SetWindowText (hwndStatus, TEXT ("FTP Session opened...")) ;
     
     //检查用户是否按下了CANCEL

     if (!pparams->bContinue)
     {
          InternetCloseHandle (hFtpSession) ;
          InternetCloseHandle (hIntSession) ;
          ButtonSwitch (hwndStatus, hwndButton, NULL) ;
          _endthread () ;
     }

     //设置目录
     
     bSuccess = FtpSetCurrentDirectory (hFtpSession, DIRECTORY);

     if (!bSuccess)
     {
          InternetCloseHandle (hFtpSession) ;
          InternetCloseHandle (hIntSession) ;
          wsprintf (szBuffer, TEXT ("Cannot set directory to %s"),DIRECTORY);
          ButtonSwitch (hwndStatus, hwndButton, szBuffer) ;
          _endthread () ;
     }

     SetWindowText (hwndStatus, TEXT ("Directory found...")) ;

     //检查用户是否按下了CANCEL

     if (!pparams->bContinue)
     {
          InternetCloseHandle (hFtpSession) ;
          InternetCloseHandle (hIntSession) ;
          ButtonSwitch (hwndStatus, hwndButton, NULL) ;
          _endthread () ;
     }

     //得到符合TEMPLATE文件名要求得第一个文件
     hFind = FtpFindFirstFile (hFtpSession, TEMPLATE, &finddata, 0, 0) ;

     if (hFind == NULL)
     {
          InternetCloseHandle (hFtpSession) ;
          InternetCloseHandle (hIntSession) ;
          ButtonSwitch (hwndStatus, hwndButton, TEXT ("Cannot find files")) ;
          _endthread () ;
     }

     do 
     {
          //检查用户是否按下了CANCEL
          if (!pparams->bContinue)
          {
               InternetCloseHandle (hFind) ;
               InternetCloseHandle (hFtpSession) ;
               InternetCloseHandle (hIntSession) ;
               ButtonSwitch (hwndStatus, hwndButton, NULL) ;
               _endthread () ;
          }
          //从internet复制文件到本地磁盘, 当本地磁盘上已经存在这个文件得时候返回NULL
          wsprintf (szBuffer, TEXT ("Reading file %s..."), finddata.cFileName);
          SetWindowText (hwndStatus, szBuffer) ;

          FtpGetFile (hFtpSession, finddata.cFileName, finddata.cFileName, TRUE, 
                      FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY, 0) ;
     }
     while (InternetFindNextFile (hFind, &finddata)) ;

     InternetCloseHandle (hFind) ;
     InternetCloseHandle (hFtpSession) ;
     InternetCloseHandle (hIntSession) ;

     ButtonSwitch (hwndStatus, hwndButton, TEXT ("Internet Download Complete"));
}

/*-----------------------------------------------------------------------
   ButtonSwitch:  在状态信息框中显示信息并将Cancel按钮改变为IDOK按钮
  -----------------------------------------------------------------------*/

VOID ButtonSwitch (HWND hwndStatus, HWND hwndButton, TCHAR * szText) 
{
     if (szText)
          SetWindowText (hwndStatus, szText) ;
     else
          SetWindowText (hwndStatus, TEXT ("Internet Session Cancelled")) ;

     SetWindowText (hwndButton, TEXT ("OK")) ;
     SetWindowLong (hwndButton, GWL_ID, IDOK) ;
}

/*-----------------------------------------------------------------------
   GetFileList: 从本地磁盘中读文件并保存他们得名字和内容
  -----------------------------------------------------------------------*/

FILELIST * GetFileList (void)
{
     DWORD           dwRead ;
     FILELIST      * plist ;
     HANDLE          hFile, hFind ;
     int             iSize, iNum  ;
     WIN32_FIND_DATA finddata ;

     hFind = FindFirstFile (TEMPLATE, &finddata) ;

     if (hFind == INVALID_HANDLE_VALUE)
          return NULL ;
     
     plist = NULL ;
     iNum  = 0 ;

     do
     {
          //打开文件
          hFile = CreateFile (finddata.cFileName, GENERIC_READ, FILE_SHARE_READ,NULL, OPEN_EXISTING, 0, NULL) ;

          if (hFile == INVALID_HANDLE_VALUE)
               continue ;
          //得到文件大小
          iSize = GetFileSize (hFile, NULL) ;

          if (iSize == (DWORD) -1)
          {
               CloseHandle (hFile) ;
               continue ;
          }
          //为FILELIST类型得变量plist分配内存块

          plist = (FILELIST *)realloc (plist, sizeof (FILELIST) + iNum * sizeof (FILEINFO));

          //分配空间以保存文件名 
          plist->info[iNum].szFilename = (char *)malloc (lstrlen (finddata.cFileName) +sizeof (TCHAR)) ;
          lstrcpy (plist->info[iNum].szFilename, finddata.cFileName) ;

          //分配空间以保存文件内容
          plist->info[iNum].szContents = (char *)malloc (iSize + 1) ;
          ReadFile (hFile, plist->info[iNum].szContents, iSize, &dwRead, NULL);
          plist->info[iNum].szContents[iSize] = 0 ;

          CloseHandle (hFile) ;
          iNum ++ ;
     }
     while (FindNextFile (hFind, &finddata)) ;

     FindClose (hFind) ;

     //按文件名排序
     qsort (plist->info, iNum, sizeof (FILEINFO), Compare) ;

     plist->iNum = iNum ;

     return plist ;
}

/*----------------------------
   Compare function for qsort
  ----------------------------*/

int Compare (const void * pinfo1, const void * pinfo2)
{
     return lstrcmp (((const FILEINFO *)pinfo2)->szFilename, ((const FILEINFO *)pinfo1)->szFilename) ;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -