?? 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 + -