IEMIMECTL.CPP

// IEMimeCtl.cpp : Implementation of CIEMimeCtl 
#include "stdafx.h"

#include "IEMime.h"
#include "IEMimeCtl.h"

#include "dispids.h"

/////////////////////////////////////////////////////////////////////////////
// CIEMimeCtl


HRESULT CIEMimeCtl::OnDraw(ATL_DRAWINFO& di)
{
RECT& rc = *(RECT*)di.prcBounds;

HDC hdc = di.hdcDraw;
HBRUSH hOldBrush, hBrush;
HPEN hOldPen, hPen;
hPen = (HPEN)GetStockObject(BLACK_PEN);
hOldPen = (HPEN)SelectObject(hdc, hPen);
hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);

SetBkMode(di.hdcDraw,TRANSPARENT);
SetTextColor(di.hdcDraw,RGB(0,0,255));
if (!m_bstrCFFormat) // Empty - don't draw text
return S_OK;

ATLTRACE(_T(" m_bstrCFFormat=%s\n"),(LPTSTR)m_bstrCFFormat);
rc.left += 5; // small left margin
DrawText(di.hdcDraw, m_bstrCFFormat, m_bstrCFFormat.length(), &rc,
DT_LEFT | DT_WORD_ELLIPSIS | DT_SINGLELINE);

SelectObject(hdc, hOldPen);
SelectObject(hdc, hOldBrush);

return S_OK;
}

STDMETHODIMP CIEMimeCtl::get_URL(BSTR * pVal)
{
//*pVal = m_bstrURL.copy();
// NOTE: _bstr_t::copy() has a BUG in VC5.0 that is fixed in VS5 SP1. See KB Q151491.
*pVal = ::SysAllocString(static_cast<const wchar_t*>(m_bstrURL));

return S_OK;
}

STDMETHODIMP CIEMimeCtl::put_URL(BSTR newVal)
{
m_bstrURL = newVal;

FireOnChanged(DISPID_URL);

if (!m_bstrURL) // NULL string
return S_OK;

if (READYSTATE_LOADING != m_nReadyState) // Wait until control is done loading before
Reload(); // firing off download

return S_OK;
}

STDMETHODIMP CIEMimeCtl::get_Media(BSTR * pVal)
{
//*pVal = m_bstrMedia.copy();
// NOTE: _bstr_t::copy() has a BUG in VC5.0 that is fixed in VS5 SP1. See KB Q151491.
*pVal = ::SysAllocString(static_cast<const wchar_t*>(m_bstrMedia));

return S_OK;
}

STDMETHODIMP CIEMimeCtl::put_Media(BSTR newVal)
{
m_bstrMedia = newVal;

FireOnChanged(DISPID_MEDIA);

return S_OK;
}

STDMETHODIMP CIEMimeCtl::get_Cfformat(BSTR * pVal)
{
*pVal = m_bstrCFFormat.copy();

return S_OK;
}

STDMETHODIMP CIEMimeCtl::AboutBox()
{
// The following is necessary to prepare the frame for showing a modal dialog box
HRESULT hr;
OLEINPLACEFRAMEINFO frameInfo;
RECT rcPos, rcClip;
CComPtr<IOleInPlaceFrame> spInPlaceFrame;
CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow;
frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
HWND hwndFrame = NULL;

if (m_spInPlaceSite)
{
m_spInPlaceSite->GetWindowContext(&spInPlaceFrame,
&spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
if (spInPlaceFrame)
{
spInPlaceFrame->GetWindow(&hwndFrame);
hr = spInPlaceFrame->EnableModeless(FALSE);
if (FAILED(hr))
return S_OK; // Failed, but we don't want to send errors back to script
}
}
// -------------------------------------------------------------------------------

::MessageBox(hwndFrame, _T("This is My Control"), _T("About iemim"), MB_OK | MB_TASKMODAL);

// Tell frame our modal dialog box has gone away
if (spInPlaceFrame)
{
spInPlaceFrame->EnableModeless(TRUE);
}
// --------------------------------------------

return S_OK;
}

STDMETHODIMP CIEMimeCtl::Reload()
{
if (!m_bstrURL) // NO OP
return S_OK;
else
{
m_nReadyState = READYSTATE_INTERACTIVE;
FireOnChanged(DISPID_READYSTATE);
CBindStatusCallback2<CIEMimeCtl>::Download(this, OnData, m_bstrURL, m_spClientSite, FALSE);
}

return S_OK;
}

HRESULT CIEMimeCtl::PreBindMoniker(CComPtr<IBindCtx> pBindCtx, CComPtr<IMoniker> pMoniker)
{
HRESULT hr = S_OK;

if (!(m_bstrMedia)) // No MIME registration of our own, default
return S_OK; // will give us an accept-type of "*/*"

LPSTR rgszTypes[1];
CLIPFORMAT cfFormats[1];
cfFormats[0] = CF_NULL;

// Register m_bstrMedia as a media-type. This will either give us
// the CLIPFORMAT of an existing media-type or create a new one for us.
rgszTypes[0] = (LPSTR)(m_bstrMedia);
if (SUCCEEDED(hr))
hr = RegisterMediaTypes(1, (LPSTR*)&rgszTypes, cfFormats);

FORMATETC rgfmtetc[1] =
{ {CF_NULL, NULL, DVASPECT_CONTENT, -1, TYMED_NULL} };
IEnumFORMATETC *pMyEtc = NULL;

// Create and register a FORMATETC enumerator for our (potentially custom)
// media type. Basically this has the equivalent effect of telling URLMON
// to use this media type for the HTTP Accept-types header.
// (this won't come into play for file://)
rgfmtetc[0].cfFormat = cfFormats[0];
hr = CreateFormatEnumerator (1, rgfmtetc, &pMyEtc);
if (SUCCEEDED(hr) && pMyEtc)
{
hr = RegisterFormatEnumerator(pBindCtx, pMyEtc, 0);
_ASSERTE(SUCCEEDED(hr));
}

return hr;
}

void CIEMimeCtl::OnBindingFailure(HRESULT hr, LPCWSTR szError)
{
if (NULL != szError && NULL != *szError)
m_bstrCFFormat = szError;
else
{
// Convert HR to human-readable string
if (INET_E_NO_VALID_MEDIA == hr)
m_bstrCFFormat = _T("<Resource at URL does not match Media type>");
else
m_bstrCFFormat = _T("<Failed to download>");
}

m_nReadyState = READYSTATE_COMPLETE;
FireOnChanged(DISPID_READYSTATE);
FireViewChange();

}

//OnData will be used as a callback functin by the CBindStatusCallback object.
//OnData will be called periodically with data from the asynchronous transfer
void CIEMimeCtl::OnData(CBindStatusCallback2<CIEMimeCtl>* pbsc, BYTE* pBytes, DWORD dwSize,
DWORD grfBSCF, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
{
static TCHAR formatname[MAX_PATH];

GetClipboardFormatName(pformatetc->cfFormat, formatname, MAX_PATH);
m_bstrCFFormat = formatname;

FireOnChanged(DISPID_CFFORMAT);

if (grfBSCF & BSCF_LASTDATANOTIFICATION)
{
Fire_Complete(); // Fire the "Complete" event
m_nReadyState = READYSTATE_COMPLETE;
FireOnChanged(DISPID_READYSTATE);
FireViewChange();
}

}

// From ATLCTL.H, line 842
STDMETHODIMP CIEMimeCtl::FreezeEvents(BOOL bFreeze)
{
ATLTRACE(_T("IOleControlImpl::FreezeEvents\n"));
if (bFreeze)
m_nFreezeEvents++;
else
{
m_nFreezeEvents--;
// Modified this so that we wait until container is
// set before downloading
if (!m_nFreezeEvents)
{
// Let's go!
Reload();
}
}

return S_OK;
}