2008/02/12
URLDownloadToFile 수행시 진행상황 파악하기
URLDownloadToFile 함수를 이용하여 URL 로부터 다운을 받을때 이 함수만을 단독으로 이용하면 받는동안 진행상황을 파악할 수 없으며 다운로드가 종료될때까지 다른 작업을 수행 할 수 없다.
진행상황을 파악하기 위해서는 CallBack 함수를 이용해야 하고, 진행중 다른 작업을 하려면 Thread로 동작을 하거나 Application에 다른 작업을 하도록 해주어야 한다.
GMPmp3 의 업그레이드 버전인 v2 를 만들기 위해 이 방법을 사용하였다.
진행 상황을 파악하기 위한 CallBack 함수는 IBindStatusCallback 인터페이스를 상속 받아 구현한다.
함수 중 OnProgress 함수가 진행 중 계속 호출되어 이 함수내에 다운로드 진행상황을 처리해주면 된다.
Original Post : http://neodreamer-dev.tistory.com/58
진행상황을 파악하기 위해서는 CallBack 함수를 이용해야 하고, 진행중 다른 작업을 하려면 Thread로 동작을 하거나 Application에 다른 작업을 하도록 해주어야 한다.
GMPmp3 의 업그레이드 버전인 v2 를 만들기 위해 이 방법을 사용하였다.
진행 상황을 파악하기 위한 CallBack 함수는 IBindStatusCallback 인터페이스를 상속 받아 구현한다.
함수 중 OnProgress 함수가 진행 중 계속 호출되어 이 함수내에 다운로드 진행상황을 처리해주면 된다.
CallBack 함수 소스 보기
//---------------------------------------------------------------------------
// 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();
Original Post : http://neodreamer-dev.tistory.com/58
Labels:
IBindStatusCallback
,
TistoryOldPost
,
Turbo C++
,
URLDownloadToFile
,
다운로드
Subscribe to:
Post Comments
(
Atom
)
No comments :
Post a Comment