📄 updatedlg.cpp
字号:
// UpdateDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Resource.h"
#include "UpdateDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
const UINT WM_FTPTRANSFER_THREAD_FINISHED = WM_APP + 1;
const UINT WM_FTPTRANSFER_ASK_OVERWRITE_FILE = WM_APP + 2;
/////////////////////////////////////////////////////////////////////////////
// CUpdateDlg dialog
IMPLEMENT_DYNAMIC(CUpdateDlg, CDialog);
CUpdateDlg::CUpdateDlg(CWnd* pParent /*=NULL*/)
: CDialog(CUpdateDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CUpdateDlg)
//}}AFX_DATA_INIT
m_hInternetSession = NULL;
m_hFTPConnection = NULL;
m_hFTPFile = NULL;
m_bAbort = FALSE;
m_bSafeToClose = FALSE;
m_pThread = NULL;
m_bUsingAttached = NULL;
m_bDownload = TRUE;
m_nPort = INTERNET_DEFAULT_FTP_PORT;
m_bBinary = TRUE;
m_bOverwrite = FALSE;
}
void CUpdateDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CUpdateDlg)
DDX_Control(pDX, IDC_PROGRESS1, m_ctrlProgress);
DDX_Control(pDX, IDC_ANIMATE1, m_ctrlAnimate);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CUpdateDlg, CDialog)
//{{AFX_MSG_MAP(CUpdateDlg)
ON_WM_CLOSE()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_FTPTRANSFER_THREAD_FINISHED, OnThreadFinished)
ON_MESSAGE(WM_FTPTRANSFER_ASK_OVERWRITE_FILE, OnAskOverwrite)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CUpdateDlg message handlers
void CUpdateDlg::AttachToExisitingHandles(HINTERNET hInternetSession, HINTERNET hFTPConnection)
{
ASSERT(m_hInternetSession == NULL);
ASSERT(m_hFTPConnection == NULL);
m_hInternetSession = hInternetSession;
m_hFTPConnection = hFTPConnection;
m_bUsingAttached = TRUE;
}
LRESULT CUpdateDlg::OnAskOverwrite(WPARAM /*wParam*/, LPARAM /*lParam*/)
{
CString sMsg;
AfxFormatString1(sMsg, IDS_TRANSFER_OK_TO_OVERWRITE, m_sRemoteFile);
return (AfxMessageBox(sMsg, MB_YESNO) == IDYES);
}
LRESULT CUpdateDlg::OnThreadFinished(WPARAM wParam, LPARAM /*lParam*/)
{
//It's now safe to close since the thread has signaled us
m_bSafeToClose = TRUE;
//Stop the animation
m_ctrlAnimate.Stop();
//If an error occured display the message box
if (m_bAbort)
EndDialog(IDCANCEL);
else if (wParam)
{
if (m_sError.GetLength())
AfxMessageBox(m_sError);
EndDialog(IDCANCEL);
}
else
EndDialog(IDOK);
return 0L;
}
BOOL CUpdateDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
// Setup the animation control
m_ctrlAnimate.Open(IDR_AVI_UPDATE);
// Check to see if the file we are downloading exists and if
// it does, then ask the user if they were it overwritten
if (m_bDownload)
{
CFileStatus fs;
ASSERT(m_sLocalFile.GetLength());
if (!m_bOverwrite && CFile::GetStatus(m_sLocalFile, fs))
{
CString sMsg;
AfxFormatString1(sMsg, IDS_OK_TO_OVERWRITE, m_sLocalFile);
if (AfxMessageBox(sMsg, MB_YESNO) != IDYES)
{
TRACE(_T("Failed to confirm file overwrite, download aborted\n"));
EndDialog(IDCANCEL);
return TRUE;
}
}
}
//Try and open the file we will downloading into / uploading from
if (m_bDownload)
{
if (!m_LocalFile.Open(m_sLocalFile, CFile::modeCreate | CFile::modeWrite | CFile::shareDenyWrite))
{
TRACE(_T("Failed to open the file to download into, Error:%d\n"), GetLastError());
CString sError;
sError.Format(_T("%d"), ::GetLastError());
CString sMsg;
AfxFormatString1(sMsg, IDS_FAIL_FILE_OPEN, sError);
AfxMessageBox(sMsg);
EndDialog(IDCANCEL);
return TRUE;
}
}
else
{
if (!m_LocalFile.Open(m_sLocalFile, CFile::modeRead | CFile::shareDenyWrite))
{
TRACE(_T("Failed to open the file to upload, Error:%d\n"), GetLastError());
CString sError;
sError.Format(_T("%d"), ::GetLastError());
CString sMsg;
AfxFormatString1(sMsg, IDS_FTPTRANSFER_FAIL_LOCALFILE_OPEN2, sError);
AfxMessageBox(sMsg);
EndDialog(IDCANCEL);
return TRUE;
}
}
//Spin off the background thread which will do the actual file transfer
m_pThread = AfxBeginThread(_TransferThread, this, THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED);
if (m_pThread == NULL)
{
TRACE(_T("Failed to create transfer thread, dialog is aborting\n"));
EndDialog(IDCANCEL);
return TRUE;
}
m_pThread->m_bAutoDelete = FALSE;
m_pThread->ResumeThread();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
UINT CUpdateDlg::_TransferThread(LPVOID pParam)
{
//Convert from the SDK world to the C++ world
CUpdateDlg* pDlg = (CUpdateDlg*) pParam;
ASSERT(pDlg);
ASSERT(pDlg->IsKindOf(RUNTIME_CLASS(CUpdateDlg)));
pDlg->TransferThread();
return 0;
}
void CUpdateDlg::SetProgressRange(DWORD dwFileSize)
{
m_ctrlProgress.SetRange(0, (short)((dwFileSize+512)/1024));
}
void CUpdateDlg::SetProgress(DWORD dwBytesRead)
{
m_ctrlProgress.SetPos(dwBytesRead/1024);
}
void CUpdateDlg::PlayAnimation()
{
m_ctrlAnimate.Play(0, (UINT)-1, (UINT)-1);
}
void CUpdateDlg::HandleThreadErrorWithLastError(UINT nIDError, DWORD dwLastError)
{
//Form the error string to report
CString sError;
DWORD dwErr = dwLastError;
if (dwErr == 0)
dwErr = ::GetLastError();
if (dwErr == ERROR_INTERNET_EXTENDED_ERROR)
{
DWORD dwInetError;
DWORD dwSize=0;
::InternetGetLastResponseInfo(&dwInetError, NULL, &dwSize);
TCHAR* pszResponse = new TCHAR[dwSize+1];
::InternetGetLastResponseInfo(&dwInetError, pszResponse, &dwSize);
pszResponse[dwSize] = _T('\0');
sError = pszResponse;
sError = _T("\n") + sError; //Add a line feed between the normal message
//and the verbose error message
delete [] pszResponse;
}
else
sError.Format(_T("%d"), dwErr);
AfxFormatString1(m_sError, nIDError, sError);
//Delete the file being downloaded to if it is present
if (m_bDownload)
{
m_LocalFile.Close();
::DeleteFile(m_sLocalFile);
}
PostMessage(WM_FTPTRANSFER_THREAD_FINISHED, 1);
}
void CUpdateDlg::HandleThreadError(UINT nIDError)
{
m_sError.LoadString(nIDError);
PostMessage(WM_FTPTRANSFER_THREAD_FINISHED, 1);
}
void CUpdateDlg::TransferThread()
{
//Create the Internet session handle (if needed)
if (!m_bUsingAttached)
{
ASSERT(m_hInternetSession == NULL);
m_hInternetSession = ::InternetOpen(NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (m_hInternetSession == NULL)
{
TRACE(_T("Failed in call to InternetOpen, Error:%d\n"), ::GetLastError());
HandleThreadErrorWithLastError(IDS_FTPTRANSFER_GENERIC_ERROR);
return;
}
//Should we exit the thread
if (m_bAbort)
{
PostMessage(WM_FTPTRANSFER_THREAD_FINISHED);
return;
}
}
ASSERT(m_hInternetSession);
//Should we exit the thread
if (m_bAbort)
{
PostMessage(WM_FTPTRANSFER_THREAD_FINISHED);
return;
}
//Make the connection to the FTP server (if needed)
if (!m_bUsingAttached)
{
ASSERT(m_hFTPConnection == NULL);
ASSERT(m_sServer.GetLength());
if (m_sUserName.GetLength())
m_hFTPConnection = ::InternetConnect(m_hInternetSession, m_sServer, m_nPort,
m_sUserName, m_sPassword, INTERNET_SERVICE_FTP, 0, (DWORD) this);
else
m_hFTPConnection = ::InternetConnect(m_hInternetSession, m_sServer,
m_nPort, NULL, NULL, INTERNET_SERVICE_FTP, 0, (DWORD) this);
if (m_hFTPConnection == NULL)
{
TRACE(_T("Failed in call to InternetConnect, Error:%d\n"), ::GetLastError());
HandleThreadErrorWithLastError(IDS_FAIL_CONNECT_SERVER);
return;
}
//Should we exit the thread
if (m_bAbort)
{
PostMessage(WM_FTPTRANSFER_THREAD_FINISHED);
return;
}
}
ASSERT(m_hFTPConnection);
//Start the animation to signify that the download is taking place
PlayAnimation();
// Get the length of the file to transfer
DWORD dwFileSize = 0;
BOOL bGotFileSize = FALSE;
if (m_bDownload)
{
WIN32_FIND_DATA wfd;
HINTERNET hFind = ::FtpFindFirstFile(m_hFTPConnection,
m_sRemoteFile, &wfd, INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, (DWORD) this);
if (hFind)
{
//Set the progress control range
bGotFileSize = TRUE;
dwFileSize = (DWORD) wfd.nFileSizeLow;
SetProgressRange(dwFileSize);
//Destroy the enumeration handle now that we are finished with it
InternetCloseHandle(hFind);
}
}
else
{
bGotFileSize = TRUE;
dwFileSize = m_LocalFile.GetLength();
SetProgressRange(dwFileSize);
}
//Should we exit the thread
if (m_bAbort)
{
PostMessage(WM_FTPTRANSFER_THREAD_FINISHED);
return;
}
//check to see if the file already exists on the server
if (!m_bDownload)
{
WIN32_FIND_DATA wfd;
HINTERNET hFind = ::FtpFindFirstFile(m_hFTPConnection, m_sRemoteFile, &wfd, INTERNET_FLAG_RELOAD |
INTERNET_FLAG_DONT_CACHE, (DWORD) this);
BOOL bFound = FALSE;
if (hFind)
{
bFound = TRUE;
//Destroy the enumeration handle now that we are finished with it
InternetCloseHandle(hFind);
}
if (bFound && !m_bOverwrite && SendMessage(WM_FTPTRANSFER_ASK_OVERWRITE_FILE) == 0)
{
PostMessage(WM_FTPTRANSFER_THREAD_FINISHED, 1);
return;
}
}
//Should we exit the thread
if (m_bAbort)
{
PostMessage(WM_FTPTRANSFER_THREAD_FINISHED);
return;
}
//Open the remote file
ASSERT(m_hFTPFile == NULL);
if (m_bDownload)
{
if (m_bBinary)
m_hFTPFile = FtpOpenFile(m_hFTPConnection, m_sRemoteFile, GENERIC_READ, FTP_TRANSFER_TYPE_BINARY |
INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, (DWORD) this);
else
m_hFTPFile = FtpOpenFile(m_hFTPConnection, m_sRemoteFile, GENERIC_READ, FTP_TRANSFER_TYPE_ASCII |
INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, (DWORD) this);
}
else
{
if (m_bBinary)
m_hFTPFile = FtpOpenFile(m_hFTPConnection, m_sRemoteFile, GENERIC_WRITE, FTP_TRANSFER_TYPE_BINARY |
INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, (DWORD) this);
else
m_hFTPFile = FtpOpenFile(m_hFTPConnection, m_sRemoteFile, GENERIC_WRITE, FTP_TRANSFER_TYPE_ASCII |
INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, (DWORD) this);
}
if (m_hFTPFile == NULL)
{
TRACE(_T("Failed in call to FtpOpenFile, Error:%d\n"), ::GetLastError());
HandleThreadErrorWithLastError(IDS_FTPTRANSFER_FAIL_OPEN_FILE);
return;
}
//Should we exit the thread
if (m_bAbort)
{
PostMessage(WM_FTPTRANSFER_THREAD_FINISHED);
return;
}
//Now do the actual reading / writing of the file
DWORD dwStartTicks = ::GetTickCount();
DWORD dwCurrentTicks = dwStartTicks;
DWORD dwBytesRead = 0;
DWORD dwBytesWritten = 0;
char szReadBuf[1024];
DWORD dwBytesToRead = 1024;
DWORD dwTotalBytesRead = 0;
DWORD dwTotalBytesWritten = 0;
DWORD dwLastTotalBytes = 0;
DWORD dwLastPercentage = 0;
do
{
if (m_bDownload)
{
//Read from the remote file
if (!::InternetReadFile(m_hFTPFile, szReadBuf, dwBytesToRead, &dwBytesRead))
{
TRACE(_T("Failed in call to InternetReadFile, Error:%d\n"), ::GetLastError());
HandleThreadErrorWithLastError(IDS_ERROR_READFILE);
return;
}
else if (dwBytesRead && !m_bAbort)
{
//Write the data to file
TRY
{
m_LocalFile.Write(szReadBuf, dwBytesRead);
}
CATCH(CFileException, e);
{
TRACE(_T("An exception occured while writing to the download file\n"));
HandleThreadErrorWithLastError(IDS_ERROR_READFILE, e->m_lOsError);
e->Delete();
return;
}
END_CATCH
//Increment the total number of bytes read
dwTotalBytesRead += dwBytesRead;
UpdateControlsDuringTransfer(dwTotalBytesRead, dwLastPercentage, bGotFileSize, dwFileSize);
}
}
else
{
//Read the data from the local file
TRY
{
dwBytesRead = m_LocalFile.Read(szReadBuf, 1024);
}
CATCH(CFileException, e);
{
TRACE(_T("An exception occured while reading the local file\n"));
HandleThreadErrorWithLastError(IDS_ERROR_READFILE, e->m_lOsError);
e->Delete();
return;
}
END_CATCH
//Write to the remote file
if (dwBytesRead)
{
if (!::InternetWriteFile(m_hFTPFile, szReadBuf, dwBytesRead, &dwBytesWritten))
{
TRACE(_T("Failed in call to InternetWriteFile, Error:%d\n"), ::GetLastError());
HandleThreadErrorWithLastError(IDS_FTPTRANSFER_ERROR_WRITEFILE);
return;
}
else if (dwBytesWritten && !m_bAbort)
{
//Increment the total number of bytes read
dwTotalBytesWritten += dwBytesWritten;
UpdateControlsDuringTransfer(dwTotalBytesWritten, dwLastPercentage, bGotFileSize, dwFileSize);
}
}
}
}
while (dwBytesRead && !m_bAbort);
//Delete the file being downloaded, if it is present and the download was aborted
m_LocalFile.Close();
if (m_bAbort && m_bDownload)
::DeleteFile(m_sLocalFile);
//We're finished
PostMessage(WM_FTPTRANSFER_THREAD_FINISHED);
}
void CUpdateDlg::UpdateControlsDuringTransfer(DWORD dwTotalBytesRead,
DWORD& dwLastPercentage, BOOL bGotFileSize, DWORD dwFileSize)
{
if (bGotFileSize)
{
//Update the percentage downloaded in the caption
DWORD dwPercentage = (DWORD) (dwTotalBytesRead * 100.0 / dwFileSize);
if (dwPercentage != dwLastPercentage)
{
//Update the progress control bar
SetProgress(dwTotalBytesRead);
}
}
}
void CUpdateDlg::OnClose()
{
if (m_bSafeToClose)
CDialog::OnClose();
else
{
//Just set the abort flag to TRUE and
//disable the cancel button
m_bAbort = TRUE;
}
}
void CUpdateDlg::OnDestroy()
{
//Wait for the worker thread to exit
if (m_pThread)
{
WaitForSingleObject(m_pThread->m_hThread, INFINITE);
delete m_pThread;
m_pThread = NULL;
}
//Free up the internet handles we may be using
::InternetCloseHandle(m_hFTPFile);
m_hFTPFile = NULL;
if (!m_bUsingAttached)
{
::InternetCloseHandle(m_hFTPConnection);
::InternetCloseHandle(m_hInternetSession);
}
m_hFTPConnection = NULL;
m_hInternetSession = NULL;
//Let the parent class do its thing
CDialog::OnDestroy();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -