웹, HTML

다운로드 진행상황 콜백 구현부분 참조

디버그정 2008. 9. 15. 19:46
//---------------------------------------------------------------------------
// Header
#include <vcl.h>
#include <windows.h>
#include <UrlMon.h>
#include <UrlMon.hpp>
#pragma comment(lib,"urlmon.lib")
#pragma comment(lib,"WinInet.lib")

class TCallback : public IBindStatusCallback
{
    DWORD m_cRef;
   
private:
    STDMETHODIMP QueryInterface(REFIID riid,void **ppv);
    STDMETHODIMP_(ULONG) AddRef();
    STDMETHODIMP_(ULONG) Release();

    STDMETHODIMP GetBindInfo(DWORD *grfBINDF,BINDINFO *bindinfo);
    STDMETHODIMP GetPriority(LONG *nPriority);
    STDMETHODIMP OnDataAvailable(DWORD grfBSCF,DWORD dwSize,
        FORMATETC *formatetc,STGMEDIUM *stgmed);
    STDMETHODIMP OnLowResource(DWORD reserved);
    STDMETHODIMP OnObjectAvailable(REFIID iid,IUnknown *punk);
    STDMETHODIMP OnStartBinding(DWORD dwReserved,IBinding *pib);
    STDMETHODIMP OnStopBinding(HRESULT hresult,LPCWSTR szError);
    STDMETHODIMP OnProgress(ULONG ulProgress, ULONG ulProgressMax,
        ULONG ulStatusCode, LPCWSTR szStatusText);
 
public:
    TfrmDownload* frmDown; // 진행상황을 표시해줄 Form 포인터
    TCallback() {m_cRef = 1;};
};


//---------------------------------------------------------------------------
// Source

STDMETHODIMP TCallback::QueryInterface(REFIID riid,void **ppv)
{
    *ppv = NULL;
    if (riid==IID_IUnknown || riid==IID_IBindStatusCallback) {
        *ppv = this;
        AddRef();
        return S_OK;
    }
    return E_NOINTERFACE;
}

STDMETHODIMP_(ULONG) TCallback::AddRef()
{
    return m_cRef++;
}

STDMETHODIMP_(ULONG) TCallback::Release()
{
    if(--m_cRef==0) {
        delete this;
        return 0;
    }
    return m_cRef;
}

STDMETHODIMP TCallback::GetBindInfo(DWORD *grfBINDF,BINDINFO *bindinfo)
{
    return E_NOTIMPL;
}

STDMETHODIMP TCallback::GetPriority(LONG *nPriority)
{
    return E_NOTIMPL;
}

STDMETHODIMP TCallback::OnDataAvailable(DWORD grfBSCF,DWORD dwSize,
    FORMATETC *formatetc,STGMEDIUM *stgmed)
{     
    return E_NOTIMPL;
}

STDMETHODIMP TCallback::OnLowResource(DWORD reserved)
{
    return E_NOTIMPL;
}
STDMETHODIMP TCallback::OnObjectAvailable(REFIID iid,IUnknown *punk)
{
    return E_NOTIMPL;
}

STDMETHODIMP TCallback::OnStartBinding(DWORD dwReserved,IBinding *pib)
{
    return E_NOTIMPL;
}

STDMETHODIMP TCallback::OnStopBinding(HRESULT hresult,LPCWSTR szError)
{
    return E_NOTIMPL;
}

STDMETHODIMP TCallback::OnProgress(ULONG ulProgress, ULONG ulProgressMax,
    ULONG ulStatusCode, LPCWSTR szStatusText)
{         
    AnsiString Status;
    switch (ulStatusCode)
    {
      case BINDSTATUS_FINDINGRESOURCE :
    Status = "Finding resource " + AnsiString(szStatusText); break;
      case BINDSTATUS_CONNECTING :
           Status = "Connecting to " + AnsiString(szStatusText); break;
      case BINDSTATUS_REDIRECTING :
           Status = "Redirecting..."; break;
      case BINDSTATUS_BEGINDOWNLOADDATA :
           Status = "Start to download " + AnsiString(szStatusText); break;
      case BINDSTATUS_DOWNLOADINGDATA :
           Status = "Downloading..."; break;
      case BINDSTATUS_ENDDOWNLOADDATA :
           Status = "Complete downloading " + AnsiString(szStatusText); break;
      case BINDSTATUS_BEGINDOWNLOADCOMPONENTS :
           Status = "Start to download components"; break;
      case BINDSTATUS_INSTALLINGCOMPONENTS :
           Status = "Installing components..." ; break;
      case BINDSTATUS_ENDDOWNLOADCOMPONENTS :
           Status = "Complete downloading components"; break;
      case BINDSTATUS_USINGCACHEDCOPY :
          Status = "Copying form buffer..."; break;
      case BINDSTATUS_SENDINGREQUEST :
           Status = "Sending request..."; break;
      case BINDSTATUS_CLASSIDAVAILABLE :
           Status = "Class ID is available"; break;
      case BINDSTATUS_MIMETYPEAVAILABLE :
           Status = "MIME type is available"; break;
      case BINDSTATUS_CACHEFILENAMEAVAILABLE :
           Status = "Cache file name is available"; break;
      case BINDSTATUS_BEGINSYNCOPERATION :
           Status = "Start sync operation"; break;
      case BINDSTATUS_ENDSYNCOPERATION :
           Status = "Complete sync operation"; break;
      case BINDSTATUS_BEGINUPLOADDATA :
           Status = "Start to upload data"; break;
      case BINDSTATUS_UPLOADINGDATA :
           Status = "Uploading data"; break;
      case BINDSTATUS_ENDUPLOADDATA :
           Status = "Complete Uploading data"; break;
      case BINDSTATUS_PROTOCOLCLASSID :
           Status = "Protocol class ID is available"; break;
      case BINDSTATUS_ENCODING :
           Status = "Encoding..."; break;
      case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE :
           Status = "Verified MIME is available"; break;
      case BINDSTATUS_CLASSINSTALLLOCATION :
           Status = "Class install location"; break;
      case BINDSTATUS_DECODING :
           Status = "Decoding..."; break;
      case BINDSTATUS_LOADINGMIMEHANDLER :
           Status = "Loading MIME handler"; break;
      case BINDSTATUS_CONTENTDISPOSITIONATTACH :
           Status = "Content disposition attach"; break;
      case BINDSTATUS_FILTERREPORTMIMETYPE :
           Status = "Filter report MIME type"; break;
      case BINDSTATUS_CLSIDCANINSTANTIATE :
           Status = "Clsid can instantiate"; break;
      case BINDSTATUS_IUNKNOWNAVAILABLE :
           Status = "Unknown available"; break;
      case BINDSTATUS_DIRECTBIND :
           Status = "Direct bind"; break;
      case BINDSTATUS_RAWMIMETYPE :
           Status = "MIME type of the resource, before any code sniffing is done"; break;
      case BINDSTATUS_PROXYDETECTING :
           Status = "Detecting proxy..."; break;
      case BINDSTATUS_ACCEPTRANGES :
           Status = "Valid types of range requests for a resource"; break;
      default : Status = "";
    }

    // Application에 다른 메세지를 처리하도록 지시
    Application->ProcessMessages();

    if (ulProgressMax > 0)
    {
        // 진행상황을 Progress Bar를 이용하여 표시
        double dblRate = ((double)ulProgress / (double)ulProgressMax) * 100.0;
        frmDown->prgDownload->Min = 0;
        frmDown->prgDownload->Max = 100;
        frmDown->prgDownload->Position = static_cast<int>(dblRate);
    }

    if (frmDown->IsUserCancel())
     return E_ABORT;
       
    // Application에 다른 메세지를 처리하도록 지시
    Application->ProcessMessages();

    return S_OK;
}

//---------------------------------------------------------------------------
// Caller
    m_bDownloading = true;

    Status.frmDown = this;

    LPUNKNOWN   pCaller = NULL;
    DeleteUrlCacheEntry(m_strURL.c_str());
    HRESULT hRet = URLDownloadToFile(pCaller, m_strURL.c_str(),
        m_strDst.c_str(), 0, &Status);

    if (hRet == S_OK)
    {
        ShowMessage("다운로드 완료!");
    }
    else if (hRet == E_ABORT)
    {
        if (m_bUserCancel == true)
            ShowMessage("다운로드가 취소되었습니다.");
        else
            ShowMessage("다운로드 실패!");
    }

    m_bDownloading = false;
    Close();