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

📄 urldownloaddlg.cpp

📁 不错的http下载程序。
💻 CPP
字号:
//////////////////////////////////////////////////////////////////////
//
// Written by Michael Dunn (mdunn at inreach dot com).  Copyright and all
// that stuff.  Use however you like but give me credit where it's due.  I'll
// know if you don't. bwa ha ha ha ha!
// 
// Release history:
//   December 24, 1999: Version 1.0.  First release.
//
//////////////////////////////////////////////////////////////////////

// URLDownloadDlg.cpp : implementation file
//

#include "stdafx.h"
#include "URLDownload.h"
#include "URLDownloadDlg.h"
#include "BindStatusCallback.h"

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

static UINT gThreadProc ( void* pv );

/////////////////////////////////////////////////////////////////////////////
// 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

// Implementation
protected:
	//{{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_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CURLDownloadDlg dialog

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

void CURLDownloadDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CURLDownloadDlg)
	DDX_Control(pDX, IDC_TIMEOUT_SECS, m_editTimeout);
	DDX_Control(pDX, IDC_TIMEOUT, m_btnTimeout);
	DDX_Control(pDX, IDC_SPIN, m_spinner);
	DDX_Control(pDX, IDC_FILE, m_editFile);
	DDX_Control(pDX, IDC_ABOUT, m_btnAbout);
	DDX_Control(pDX, IDC_URL, m_editURL);
	DDX_Control(pDX, IDCANCEL, m_btnExit);
	DDX_Control(pDX, IDC_STOP, m_btnStop);
	DDX_Control(pDX, IDC_START, m_btnStart);
	DDX_Control(pDX, IDC_PROGRESS, m_progress);
	DDX_Control(pDX, IDC_IE_STATUS, m_stIEMsg);
	DDX_Control(pDX, IDC_CUSTOM_STATUS, m_stCustomMsg);
	DDX_Text(pDX, IDC_TIMEOUT_SECS, m_uTimeout);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CURLDownloadDlg, CDialog)
	//{{AFX_MSG_MAP(CURLDownloadDlg)
	ON_WM_SYSCOMMAND()
	ON_BN_CLICKED(IDC_START, OnStart)
	ON_BN_CLICKED(IDC_STOP, OnStop)
	ON_BN_CLICKED(IDC_ABOUT, OnAbout)
	ON_BN_CLICKED(IDC_TIMEOUT, OnClickedTimeout)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CURLDownloadDlg message handlers

BOOL CURLDownloadDlg::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

    // Init & pre-fill some of the dlg controls.

    m_spinner.SetRange ( 1, 120 );
    m_progress.SetRange ( 0, 100 );
    
    // Fill the URL editbox with "http://"
    m_editURL.SetWindowText ( _T("http://") );

    // Fill the file editbox with the user's MyDocs directory.
LPITEMIDLIST pidl;
LPMALLOC     pMalloc;
TCHAR        szDocsDir [MAX_PATH];

    if ( SUCCEEDED( SHGetSpecialFolderLocation ( NULL, CSIDL_PERSONAL,
                                                 &pidl )))
        {
        if ( SHGetPathFromIDList ( pidl, szDocsDir ))
            {
            lstrcat ( szDocsDir, _T("\\") );
            m_editFile.SetWindowText ( szDocsDir );
            }

        if ( SUCCEEDED( SHGetMalloc ( &pMalloc )))
            {
            pMalloc->Free ( pidl );
            pMalloc->Release();
            }
        }

    // Set the focus to the URL edit box.
    GotoDlgCtrl ( &m_editURL );
    m_editURL.SetSel ( -1, -1 );

    return FALSE;  // return TRUE  unless you set the focus to a control
}

void CURLDownloadDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}


/////////////////////////////////////////////////////////////////////////////
// CURLDownloadDlg command handlers

void CURLDownloadDlg::OnOK() 
{
    // Do nothing - this is just here to prevent the dlg from closing if
    // the user hits the Enter key.
}

void CURLDownloadDlg::OnStart() 
{
CWinThread* pWorkerThread;

    UpdateData();

    if ( m_editURL.GetWindowTextLength() == 0 )
        {
        AfxMessageBox ( _T("Please enter a URL.") );
        return;
        }

    if ( m_editURL.GetWindowTextLength() == 0 )
        {
        AfxMessageBox ( _T("Please enter a filename.") );
        return;
        }

    // Create our worker thread.  It won't start until we disable all of the
    // dialog controls.

    pWorkerThread = AfxBeginThread ( gThreadProc, this,
                                     THREAD_PRIORITY_NORMAL, 0, 
                                     CREATE_SUSPENDED );

    // Note: Yeah I know that it's BAD to pass a CWnd object between threads.
    // I forgot about that rule when I wrote the above call, and it turns out
    // that I got lucky and it works.  All the stuff the worker thread does
    // involves just sending messages to window handles.  Since accessing the
    // data member CWnd::m_hWnd is safe to do across threads, nothing ever
    // asserted to alert me of this mistake.
    // Since I have finished this sample app and just now noticed this mistake,
    // I;m gonna be lazy and not fix it. :D

    if ( NULL != pWorkerThread )
        {
        g_fAbortDownload = 0;

        m_editURL.    EnableWindow ( FALSE );
        m_editFile.   EnableWindow ( FALSE );
        m_editTimeout.EnableWindow ( FALSE );
        m_btnStart.   EnableWindow ( FALSE );
        m_btnStop.    EnableWindow ();
        m_btnExit.    EnableWindow ( FALSE );
        m_btnAbout.   EnableWindow ( FALSE );
        m_btnTimeout. EnableWindow ( FALSE );
        m_spinner.    EnableWindow ( FALSE );

        GotoDlgCtrl ( &m_btnStop );

        // Kick off the download!
        pWorkerThread->ResumeThread();
        }
    else
        {
        AfxMessageBox ( _T("Couldn't create worker thread!"), MB_ICONERROR );
        }
}

void CURLDownloadDlg::OnStop() 
{
    InterlockedExchange ( &g_fAbortDownload, 1 );
}

void CURLDownloadDlg::OnAbout() 
{
CAboutDlg dlgAbout;

    dlgAbout.DoModal();
}


/////////////////////////////////////////////////////////////////////////////
// CURLDownloadDlg message handlers

// Handler for BN_CLICKED from the "Use time limit" checkbox.
void CURLDownloadDlg::OnClickedTimeout() 
{
    UpdateTimeoutCtrls();
}

// UpdateTimeoutCtrls(): Enables/disabled the timeout-related controls
// (edit box and spin button) according to the state of the "Use time limit"
// checkbox.
void CURLDownloadDlg::UpdateTimeoutCtrls()
{
BOOL bEnable = m_btnTimeout.GetCheck();

    m_editTimeout.EnableWindow ( bEnable );
    m_spinner.EnableWindow ( bEnable );
}


/////////////////////////////////////////////////////////////////////////////
// CURLDownloadDlg other functions

// gThreadProd(): Function for our worker thread.  It just calls 
// CURLDownloadDlg::WorkerThreadProc().
UINT gThreadProc ( void* pv )
{
CURLDownloadDlg* pDlg = (CURLDownloadDlg*) pv;

    pDlg->WorkerThreadProc();

    return 0;
}

// WorkerThreadProc(): Function that does all the work of downloading
// and error reporting.
void CURLDownloadDlg::WorkerThreadProc()
{
CCallback callback;
HRESULT   hr;
CString   sURL, sFile;

    callback.m_pDlg = this;

    m_editURL.GetWindowText ( sURL );
    m_editFile.GetWindowText ( sFile );

    // If the user wants a timeout, calculate the time when the download
    // should abort.
    if ( m_btnTimeout.GetCheck() )
        {
        callback.m_bUseTimeout = TRUE;

        callback.m_timeToStop = CTime::GetCurrentTime() +
                                  CTimeSpan( 0, 0, 0, m_uTimeout );
        }

    hr = URLDownloadToFile ( NULL,      // ptr to ActiveX container
                             sURL,      // URL to get
                             sFile,     // file to store data in
                             0,         // reserved
                             &callback  // ptr to IBindStatusCallback
                           );

    if ( SUCCEEDED(hr) )
        {
        AfxMessageBox ( _T("Download completed successfully!"), 
                        MB_ICONINFORMATION );
        }
    else
        {
        LPTSTR lpszErrorMessage;
        CString sMsg;

        if ( FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER | 
                              FORMAT_MESSAGE_FROM_SYSTEM | 
                              FORMAT_MESSAGE_IGNORE_INSERTS,
                            NULL, hr, 
                            MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT ),
                            (LPTSTR) &lpszErrorMessage, 0, NULL ))
            {
            sMsg.Format ( _T("Download failed.  Error = 0x%08lX\n\n%s"),
                          (DWORD) hr, lpszErrorMessage );

            LocalFree ( lpszErrorMessage );
            }
        else
            {
            sMsg.Format ( _T("Download failed.  Error = 0x%08lX\n\nNo message available."),
                          (DWORD) hr );
            }

        AfxMessageBox ( sMsg );
        }

    // At this point, the thread's about to end, so re-enable the dialog
    // controls.

    m_editURL.   EnableWindow();
    m_editFile.  EnableWindow();
    m_btnStart.  EnableWindow();
    m_btnStop.   EnableWindow ( FALSE );
    m_btnExit.   EnableWindow();
    m_btnAbout.  EnableWindow();
    m_btnTimeout.EnableWindow();
    UpdateTimeoutCtrls();

    GotoDlgCtrl ( &m_editURL );
}

// ProgressUpdate(): Called by the worker thread to update the status indicators
// in the main window.
void CURLDownloadDlg::ProgressUpdate ( LPCTSTR szIEMsg,
                                       LPCTSTR szCustomMsg,
                                       const int nPercentDone )
{
    ASSERT ( AfxIsValidString ( szIEMsg ));
    ASSERT ( AfxIsValidString ( szCustomMsg ));
    ASSERT ( nPercentDone >= 0  &&  nPercentDone <= 100 );

    m_stIEMsg.SetWindowText ( szIEMsg );
    m_stCustomMsg.SetWindowText ( szCustomMsg );
    m_progress.SetPos ( nPercentDone );
}

⌨️ 快捷键说明

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