home *** CD-ROM | disk | FTP | other *** search
- // ===========================================================================
- // File: P R O G R E S S . C P P
- //
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
- // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- // PARTICULAR PURPOSE.
- //
- // Description:
- //
- // This sample demonstrates using a URL moniker to download information.
- // The key routines include the implementation of IBindStatusCallback
- // and the CDownload::DoDownload routine, which creates and binds to the
- // URL moniker.
- //
- // Instructions:
- //
- // To use this sample:
- // * build it using the NMAKE command. NMAKE will create PROGRESS.EXE.
- // * run PROGRESS.EXE. specify the resource to download by passing an
- // URL on the command-line. use no command-line argument to default to
- // downloading "http://www.msn.com".
- // * The program displays a dialog box containing information about the
- // download:
- // - a status message, describing the current status of the download
- // - a progress message, describing the amount of information that
- // has been downloaded.
- // - a text box, which displays chunks of the download information as
- // it arrives.
- // * Press the "GO" button to begin the download.
- //
- // Sample update:-
- // * New feature include Progress Bar to indicated progress of the download
- // * Edit box replaces the old text box. Also the whole file can be viewed.
- // If the file exceeds 32KB then only the first 32 KB from the last data
- // pull will be displayed. If the pull exceeds 32 KB, then only the first
- // 32 KB of the last Read will be displayed.
- //
- ///
- // File updated by Jobi George 19-June-1996
- // File updated by Ramesha Gopalakrishna 28-June-1996
- // File updated by Oliver Wallace 9-July-1996
- // Copyright 1995-1996 Microsoft Corporation. All Rights Reserved.
- // ===========================================================================
- #include "urlmon.h"
- #include "wininet.h"
- #include "resource.h"
- #include "commctrl.h"
-
- #define EDIT_BOX_LIMIT 0x7FFF // The Edit box limit
-
- // %%Classes: ----------------------------------------------------------------
- class CDownload {
- public:
- CDownload(LPCWSTR szURL);
- ~CDownload();
- HRESULT DoDownload(HWND,HWND,HWND,HWND);
- LPCWSTR m_url;
-
- private:
- IMoniker* m_pmk;
- IBindCtx* m_pbc;
- IBindStatusCallback* m_pbsc;
- };
-
- class CBindStatusCallback : public IBindStatusCallback {
- public:
- // IUnknown methods
- STDMETHODIMP QueryInterface(REFIID riid,void ** ppv);
- STDMETHODIMP_(ULONG) AddRef() { return m_cRef++; }
- STDMETHODIMP_(ULONG) Release() { if (--m_cRef == 0) { delete this; return 0; } return m_cRef; }
-
- // IBindStatusCallback methods
- STDMETHODIMP OnStartBinding(DWORD dwReserved, IBinding* pbinding);
- STDMETHODIMP GetPriority(LONG* pnPriority);
- STDMETHODIMP OnLowResource(DWORD dwReserved);
- STDMETHODIMP OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode,
- LPCWSTR pwzStatusText);
- STDMETHODIMP OnStopBinding(HRESULT hrResult, LPCWSTR szError);
- STDMETHODIMP GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindinfo);
- STDMETHODIMP OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC *pfmtetc,
- STGMEDIUM* pstgmed);
- STDMETHODIMP OnObjectAvailable(REFIID riid, IUnknown* punk);
-
- // constructors/destructors
- CBindStatusCallback(HWND hwndStatus, HWND hwndProgress, HWND hwndText, HWND hwndProgressBar);
- ~CBindStatusCallback();
-
- inline void SetStatus(LPCWSTR szStatus) { SetWndText(m_hwndStatus, szStatus); }
- void SetProgress(LPCWSTR szProgress) { SetWndText(m_hwndProgress, szProgress); }
- void SetProgressBar(ULONG cProgress, ULONG maxProgress)
- {
- // Set the range and increment of the progress bar.
- SendMessage(m_hwndProgressBar, PBM_SETRANGE, 0, 100);
- SendMessage(m_hwndProgressBar, PBM_SETPOS, (WPARAM) (maxProgress ? cProgress * 100 / maxProgress : 0), 0);
- }
- void SetWndText(HWND hwnd, LPCWSTR szText);
-
- // data members
- DWORD m_cRef;
- IBinding* m_pbinding;
- IStream* m_pstm;
- HWND m_hwndStatus;
- HWND m_hwndProgress;
- HWND m_hwndText;
- HWND m_hwndProgressBar;
- DWORD m_cbOld;
- };
-
-
- // ===========================================================================
- // CBindStatusCallback Implementation
- // ===========================================================================
-
- // ---------------------------------------------------------------------------
- // %%Function: CBindStatusCallback::CBindStatusCallback
- // ---------------------------------------------------------------------------
- CBindStatusCallback::CBindStatusCallback(HWND hwndStatus, HWND hwndProgress, HWND hwndText, HWND hwndProgressBar)
- {
- m_hwndStatus = hwndStatus;
- m_hwndProgress = hwndProgress;
- m_hwndText = hwndText;
- m_hwndProgressBar = hwndProgressBar;
- m_pbinding = NULL;
- m_pstm = NULL;
- m_cRef = 1;
- m_cbOld = 0;
- } // CBindStatusCallback
-
- // ---------------------------------------------------------------------------
- // %%Function: CBindStatusCallback::~CBindStatusCallback
- // ---------------------------------------------------------------------------
- CBindStatusCallback::~CBindStatusCallback()
- {
- } // ~CBindStatusCallback
-
- // ---------------------------------------------------------------------------
- // %%Function: CBindStatusCallback::SetWndText
- // ---------------------------------------------------------------------------
- inline void
- CBindStatusCallback::SetWndText(HWND hwnd,LPCWSTR szText)
- {
- if (IsWindow(hwnd))
- {
- char rgchBuf[INTERNET_MAX_PATH_LENGTH];
- WideCharToMultiByte(CP_ACP, 0, szText, -1, rgchBuf, INTERNET_MAX_PATH_LENGTH, 0, 0);
- SetWindowText(hwnd, rgchBuf);
- }
- } // CBindStatusCallback::SetWndText
-
- // ---------------------------------------------------------------------------
- // %%Function: CBindStatusCallback::QueryInterface
- // ---------------------------------------------------------------------------
- STDMETHODIMP
- CBindStatusCallback::QueryInterface(REFIID riid, void** ppv)
- {
- *ppv = NULL;
-
- if (riid==IID_IUnknown || riid==IID_IBindStatusCallback)
- {
- *ppv = this;
- AddRef();
- return S_OK;
- }
- return E_NOINTERFACE;
- } // CBindStatusCallback::QueryInterface
-
- // ---------------------------------------------------------------------------
- // %%Function: CBindStatusCallback::OnStartBinding
- // ---------------------------------------------------------------------------
- STDMETHODIMP
- CBindStatusCallback::OnStartBinding(DWORD dwReserved, IBinding* pbinding)
- {
- if (m_pbinding != NULL)
- m_pbinding->Release();
- m_pbinding = pbinding;
- if (m_pbinding != NULL)
- {
- m_pbinding->AddRef();
- SetStatus(L"Status: Starting to bind...");
- }
- return S_OK;
- } // CBindStatusCallback::OnStartBinding
-
- // ---------------------------------------------------------------------------
- // %%Function: CBindStatusCallback::GetPriority
- // ---------------------------------------------------------------------------
- STDMETHODIMP
- CBindStatusCallback::GetPriority(LONG* pnPriority)
- {
- return E_NOTIMPL;
- } // CBindStatusCallback::GetPriority
-
- // ---------------------------------------------------------------------------
- // %%Function: CBindStatusCallback::OnLowResource
- // ---------------------------------------------------------------------------
- STDMETHODIMP
- CBindStatusCallback::OnLowResource(DWORD dwReserved)
- {
- return E_NOTIMPL;
- } // CBindStatusCallback::OnLowResource
-
- // ---------------------------------------------------------------------------
- // %%Function: CBindStatusCallback::OnProgress
- // ---------------------------------------------------------------------------
- STDMETHODIMP
- CBindStatusCallback::OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
- {
- char sz[255];
-
- if(szStatusText!=NULL)
- WideCharToMultiByte(CP_ACP, 0, szStatusText,-1, sz, 255, 0,0);
-
- char msg[100];
- WCHAR out[200];
-
- wsprintf(msg,"Progress: %s %d of %d ", sz, ulProgress, (ulProgress>ulProgressMax)?ulProgress:ulProgressMax);
- MultiByteToWideChar(CP_ACP, 0, msg, -1, out, sizeof(out));
-
- SetProgress(out);
- SetProgressBar(ulProgress, ulProgressMax);
- return(NOERROR);
- } // CBindStatusCallback::OnProgress
-
- // ---------------------------------------------------------------------------
- // %%Function: CBindStatusCallback::OnStopBinding
- // ---------------------------------------------------------------------------
- STDMETHODIMP
- CBindStatusCallback::OnStopBinding(HRESULT hrStatus, LPCWSTR pszError)
- {
- if (hrStatus)
- SetStatus(L"Status: File download Failed.");
-
- if (m_pbinding)
- {
- m_pbinding->Release();
- m_pbinding = NULL;
- }
-
- return S_OK;
- } // CBindStatusCallback::OnStopBinding
-
- // ---------------------------------------------------------------------------
- // %%Function: CBindStatusCallback::GetBindInfo
- // ---------------------------------------------------------------------------
- STDMETHODIMP
- CBindStatusCallback::GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindInfo)
- {
- *pgrfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
- *pgrfBINDF |= BINDF_GETNEWESTVERSION | BINDF_NOWRITECACHE;
- pbindInfo->cbSize = sizeof(BINDINFO);
- pbindInfo->szExtraInfo = NULL;
- memset(&pbindInfo->stgmedData, 0, sizeof(STGMEDIUM));
- pbindInfo->grfBindInfoF = 0;
- pbindInfo->dwBindVerb = BINDVERB_GET;
- pbindInfo->szCustomVerb = NULL;
- return S_OK;
- } // CBindStatusCallback::GetBindInfo
-
- // ---------------------------------------------------------------------------
- // %%Function: CBindStatusCallback::OnDataAvailable
- // ---------------------------------------------------------------------------
- STDMETHODIMP
- CBindStatusCallback::OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC* pfmtetc, STGMEDIUM* pstgmed)
- {
- HRESULT hr=S_OK;
- DWORD dStrlength=0;
-
- // Get the Stream passed
- if (BSCF_FIRSTDATANOTIFICATION & grfBSCF)
- {
- if (!m_pstm && pstgmed->tymed == TYMED_ISTREAM)
- {
- m_pstm = pstgmed->pstm;
- if (m_pstm)
- m_pstm->AddRef();
- }
- }
-
- // If there is some data to be read then go ahead and read them
- if (m_pstm && dwSize > m_cbOld)
- {
- DWORD dwRead = dwSize - m_cbOld; // Minimum amount available that hasn't been read
- DWORD dwActuallyRead = 0; // Placeholder for amount read during this pull
-
- if (dwRead > 0)
- do
- {
- char * pNewstr = new char[dwRead + 1];
- if (pNewstr==NULL)
- return S_FALSE;
- hr=m_pstm->Read(pNewstr,dwRead,&dwActuallyRead);
- pNewstr[dwActuallyRead] = 0;
- // If we really read something then lets add it to the Edit box
- if (dwActuallyRead>0)
- {
- dStrlength=GetWindowTextLength(m_hwndText);
-
- char *pOldstr=NULL;
- if (dwActuallyRead>=EDIT_BOX_LIMIT) // Read exceeded Edit box size
- {
- pOldstr= new char[EDIT_BOX_LIMIT];
- if (pOldstr==NULL)
- {
- delete[] pNewstr;
- return S_FALSE;
- }
- lstrcpyn(pOldstr,pNewstr,EDIT_BOX_LIMIT-1);
- }
- else if (dStrlength + dwActuallyRead >= EDIT_BOX_LIMIT)
- {
- // This pull exceeded the edit box size. Only copy the last read.
- pOldstr = new char[dwActuallyRead+1];
- if (pOldstr==NULL)
- {
- delete[] pNewstr;
- return S_FALSE;
- }
- lstrcpyn(pOldstr,pNewstr,dwActuallyRead);
- }
- else
- {
- pOldstr= new char[dStrlength+dwActuallyRead+1];
- if (pOldstr==NULL)
- {
- delete[] pNewstr;
- return S_FALSE;
- }
- GetWindowText(m_hwndText,pOldstr,(dStrlength+dwActuallyRead+1));
- lstrcat(pOldstr,pNewstr);
- }
- SetWindowText(m_hwndText,pOldstr);
- m_cbOld += dwActuallyRead;
- delete[] pOldstr;
- }
- delete[] pNewstr;
-
- } while (!(hr == E_PENDING || hr == S_FALSE) && SUCCEEDED(hr));
- }// if (m_pstm && dwSize > m_cbOld)
-
- if (BSCF_LASTDATANOTIFICATION & grfBSCF)
- {
- if (m_pstm)
- m_pstm->Release();
- hr=S_OK; // If it was the last data then we should return S_OK as we just finished reading everything
- SetStatus(L"Status: File downloaded.");
- }
-
- return hr;
- } // CBindStatusCallback::OnDataAvailable
-
- // ---------------------------------------------------------------------------
- // %%Function: CBindStatusCallback::OnObjectAvailable
- // ---------------------------------------------------------------------------
- STDMETHODIMP
- CBindStatusCallback::OnObjectAvailable(REFIID riid, IUnknown* punk)
- {
- return E_NOTIMPL;
- } // CBindStatusCallback::OnObjectAvailable
-
-
- // ===========================================================================
- // CDownload Implementation
- // ===========================================================================
-
- // ---------------------------------------------------------------------------
- // %%Function: CDownload::CDownload
- // ---------------------------------------------------------------------------
- CDownload::CDownload(LPCWSTR szURL)
- {
- m_url = szURL;
- m_pmk = 0;
- m_pbc = 0;
- m_pbsc = 0;
- } // CDownload
-
- // ---------------------------------------------------------------------------
- // %%Function: CDownload::~CDownload
- // ---------------------------------------------------------------------------
- CDownload::~CDownload()
- {
- if (m_pmk)
- m_pmk->Release();
- if (m_pbc)
- m_pbc->Release();
- if (m_pbsc)
- m_pbsc->Release();
- } // ~CDownload
-
- // ---------------------------------------------------------------------------
- // %%Function: CDownload::DoDownload
- // ---------------------------------------------------------------------------
- HRESULT
- CDownload::DoDownload(HWND hwndStatus, HWND hwndProgress, HWND hwndText, HWND hwndProgressBar)
- {
- IStream* pstm = NULL;
- HRESULT hr;
-
- hr = CreateURLMoniker(NULL, m_url, &m_pmk);
- if (FAILED(hr))
- goto LErrExit;
-
- m_pbsc = new CBindStatusCallback(hwndStatus, hwndProgress, hwndText, hwndProgressBar);
- if (m_pbsc == NULL)
- {
- hr = E_OUTOFMEMORY;
- goto LErrExit;
- }
-
- hr = CreateBindCtx(0, &m_pbc);
- if (FAILED(hr))
- goto LErrExit;
-
- hr = RegisterBindStatusCallback(m_pbc,
- m_pbsc,
- 0,
- 0L);
- if (FAILED(hr))
- goto LErrExit;
-
- hr = m_pmk->BindToStorage(m_pbc, 0, IID_IStream, (void**)&pstm);
- if (FAILED(hr))
- goto LErrExit;
-
- return hr;
-
- LErrExit:
- if (m_pbc != NULL)
- {
- m_pbc->Release();
- m_pbc = NULL;
- }
- if (m_pbsc != NULL)
- {
- m_pbsc->Release();
- m_pbsc = NULL;
- }
- if (m_pmk != NULL)
- {
- m_pmk->Release();
- m_pmk = NULL;
- }
- if (pstm)
- {
- pstm->Release();
- pstm = NULL;
- }
- return hr;
- } // CDownload::DoDownload
-
-
- // ===========================================================================
- // User Interface and Initialization Routines
- // ===========================================================================
-
- // ---------------------------------------------------------------------------
- // %%Function: DialogProc
- // ---------------------------------------------------------------------------
- BOOL CALLBACK
- DialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
- {
- static CDownload* pcdl = NULL;
-
- switch(message)
- {
- case WM_INITDIALOG:
- EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE);
- EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), TRUE);
- pcdl = (CDownload*)(LPVOID)(lParam);
- break;
-
- case WM_COMMAND:
- {
- switch (LOWORD(wParam))
- {
- case IDOK:
- {
- char rgchBuf[INTERNET_MAX_PATH_LENGTH];
- HWND hwndStatus = GetDlgItem(hwndDlg, IDC_DISPLAY);
- HWND hwndProgress = GetDlgItem(hwndDlg, IDC_PROGRESS);
- HWND hwndText = GetDlgItem(hwndDlg, IDC_EDIT);
- HWND hwndProgressBar = GetDlgItem(hwndDlg, IDC_PROGRESSBAR);
-
- EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
- EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
-
- WideCharToMultiByte(CP_ACP, 0, pcdl->m_url, -1, rgchBuf, MAX_PATH, 0, 0);
- SetWindowText(hwndDlg, rgchBuf);
-
- SetWindowText(hwndStatus, TEXT("Status: Initiating Bind..."));
- pcdl->DoDownload(hwndStatus, hwndProgress, hwndText, hwndProgressBar);
- EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), TRUE);
- break;
- }
-
- case IDCANCEL:
- EndDialog(hwndDlg,0);
- return 1;
- }
- break;
- }
- }
-
- return 0;
- } // DialogProc
-
- // ---------------------------------------------------------------------------
- // %%Function: WinMain
- // ---------------------------------------------------------------------------
- int WINAPI
- WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR szCmdLine, int nCmdShow)
- {
- static WCHAR szDefaultURL[] = L"http://www.msn.com";
- WCHAR rgwchCmdLine[MAX_PATH];
- HRESULT hr;
-
- InitCommonControls();
-
- hr = CoInitialize(NULL);
- if (FAILED(hr))
- return hr;
-
- MultiByteToWideChar(CP_ACP, 0, szCmdLine, -1, rgwchCmdLine, MAX_PATH);
-
- CDownload download(rgwchCmdLine[0] ? rgwchCmdLine : szDefaultURL);
-
- int x = DialogBoxParam(hinst, MAKEINTRESOURCE(IDD_DIALOG1), HWND_DESKTOP,
- (FARPROC)&DialogProc, (LPARAM)(LPVOID)&download);
-
- CoUninitialize();
-
- return 0;
- } // WinMain
-
- // EOF =======================================================================
-
-