📄 ftpdemo.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, ¶ms);
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 + -