> Let's start with a BMP, since as far as I know the OLE system only
> handles Windows picture formats.
OK. It was the same for every graphic format, including BMP.
> How are you trying to use OleLoadPicture()? I would have tried to test
> it but I don't know a good way to get the IStream and I don't have a
> clue what IID to ask for and why I would even want one...
I am using a modified version of Paul DiLascia's class, which is as follows:
class CPicture {
public:
CPicture();
~CPicture();
// Load frm various sosurces
BOOL Load(UINT nIDRes);
BOOL Load(LPCTSTR pszPathName);
BOOL Load(CAtlFile& file);
BOOL Load(IStream* pstm);
// render to device context
BOOL Render(HDC hDC, CRect rc=CRect(0,0,0,0),
LPCRECT prcMFBounds=NULL) const;
CSize GetImageSize(HDC hDC=NULL) const;
operator IPicture*() {
return m_spIPicture;
}
void GetHIMETRICSize(OLE_XSIZE_HIMETRIC& cx, OLE_YSIZE_HIMETRIC& cy)
const {
cx = cy = 0;
const_cast<CPicture*>(this)->m_hr =
m_spIPicture->get_Width(&cx);
assert(SUCCEEDED(m_hr));
const_cast<CPicture*>(this)->m_hr =
m_spIPicture->get_Height(&cy);
assert(SUCCEEDED(m_hr));
}
void Free() {
if (m_spIPicture) {
m_spIPicture.Release();
}
}
private:
CComPtr< IStream > GetIStreamFromFile(CAtlFile & file) const;
CComPtr< IStream > GetIStreamFromFile(LPCTSTR pszPathName) const;
CComPtr< IStream > GetIStreamFromMemory(BYTE * pMem, DWORD len)
const;
void HIMETRICtoDP(HDC hDC, LPSIZE lpSize) const;
protected:
CComQIPtr<IPicture>m_spIPicture; // ATL smart
pointer to IPicture
HRESULT m_hr;
// last error code
};
////////////////////////////////////////////////////////////////
// CPicture implementation
//
CPicture::CPicture()
{
}
CPicture::~CPicture()
{
}
//////////////////
// Load from resource. Looks for "IMAGE" type.
//
BOOL CPicture::Load(UINT nIDRes)
{
// find resource in resource file
HINSTANCE hInst = _AtlBaseModule.GetResourceInstance();
HRSRC hRsrc = ::FindResource(hInst,
MAKEINTRESOURCE(nIDRes),
"IMAGE"); // type
if (!hRsrc)
return FALSE;
// load resource into memory
DWORD len = SizeofResource(hInst, hRsrc);
BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
if (!lpRsrc)
return FALSE;
// create memory file and load it
CComPtr< IStream > spStream = GetIStreamFromMemory( lpRsrc, len );
return Load( spStream );
}
//////////////////
// Load from path name.
//
BOOL CPicture::Load(LPCTSTR pszPathName)
{
CComPtr< IStream > pStream = GetIStreamFromFile( pszPathName );
return Load(pStream);
}
//////////////////
// Load from CFile
//
BOOL CPicture::Load(CAtlFile& file)
{
CComPtr< IStream > pStream = GetIStreamFromFile( file );
return Load(pStream);
}
//////////////////
// Load from stream (IStream). This is the one that really does it: call
// OleLoadPicture to do the work.
//
BOOL CPicture::Load(IStream* pstm)
{
Free();
HRESULT hr = OleLoadPicture(pstm, 0, FALSE,
IID_IPicture, (void**)&m_spIPicture);
hr;
DWORD dwCode = HRESULT_CODE(hr);
DWORD dwFacility = HRESULT_FACILITY(hr);
return TRUE;
}
//////////////////
// Render to device context. Covert to HIMETRIC for IPicture.
//
BOOL CPicture::Render(HDC hDC, CRect rc, LPCRECT prcMFBounds) const
{
assert(hDC);
if (rc.IsRectNull()) {
CSize sz = GetImageSize(hDC);
rc.right = sz.cx;
rc.bottom = sz.cy;
}
long hmWidth,hmHeight; // HIMETRIC units
GetHIMETRICSize(hmWidth, hmHeight);
m_spIPicture->Render(hDC, rc.left, rc.top, rc.Width(), rc.Height(),
0, hmHeight, hmWidth, -hmHeight, prcMFBounds);
return TRUE;
}
//////////////////
// Get image size in pixels. Converts from HIMETRIC to device coords.
//
CSize CPicture::GetImageSize(HDC hDC) const
{
if (!m_spIPicture)
return CSize(0,0);
LONG hmWidth, hmHeight; // HIMETRIC units
m_spIPicture->get_Width(&hmWidth);
m_spIPicture->get_Height(&hmHeight);
CSize sz(hmWidth,hmHeight);
if (hDC==NULL)
hDC = ::GetWindowDC( NULL );
if (hDC)
{
HIMETRICtoDP(hDC, &sz);
}
return sz;
}
CComPtr< IStream > CPicture::GetIStreamFromFile(CAtlFile & file) const
{
ULONGLONG ull;
if (SUCCEEDED(file.GetSize( ull )))
{
boost::scoped_array< BYTE > const contents( new BYTE[
DWORD(ull) ] );
if (contents.get())
{
return GetIStreamFromMemory( contents.get(),
DWORD(ull) );
}
}
return NULL;
}
CComPtr< IStream > CPicture::GetIStreamFromFile(LPCTSTR pszPathName) const
{
CAtlFile file;
if (SUCCEEDED(file.Create( pszPathName, GENERIC_READ,
FILE_SHARE_READ,
OPEN_EXISTING )))
{
return GetIStreamFromFile( file );
}
else
{
return NULL;
}
}
CComPtr< IStream > CPicture::GetIStreamFromMemory(BYTE * pb, DWORD len)
const
{
HGLOBAL const hg = ::GlobalAlloc( GHND, len );
if (hg)
{
BYTE * pbNew = static_cast< BYTE * > (::GlobalLock( hg ));
if (pbNew)
{
std::copy( pb, pb + len, pbNew );
::SetLastError( NO_ERROR );
if (::GlobalUnlock( hg ) == 0 && NO_ERROR ==
::GetLastError())
{
CComPtr< IStream > spStream;
::CreateStreamOnHGlobal( hg, TRUE, &spStream
);
return spStream;
}
}
}
return NULL;
}
void CPicture::HIMETRICtoDP(HDC hDC, LPSIZE lpSize) const
{
int nMapMode = GetMapMode( hDC );
if (nMapMode < MM_ISOTROPIC &&
nMapMode != MM_TEXT)
{
// when using a constrained map mode, map against physical
inch
SetMapMode(hDC, MM_HIMETRIC);
POINT pt = { 0 };
LPtoDP(hDC, &pt, 1);
SetMapMode(hDC, nMapMode);
lpSize->cx = pt.x;
lpSize->cy = pt.y;
}
else
{
// map against logical inch for non-constrained mapping
modes
int cxPerInch, cyPerInch;
assert(hDC != NULL);
cxPerInch = GetDeviceCaps(hDC, LOGPIXELSX);
cyPerInch = GetDeviceCaps(hDC, LOGPIXELSY);
assert(cxPerInch != 0 && cyPerInch != 0);
lpSize->cx = MulDiv(lpSize->cx, cxPerInch, 2540);
lpSize->cy = MulDiv(lpSize->cy, cyPerInch, 2540);
}
}
> How come you don't use CPictureHolder in your control?
At first, because I didn't know about it. But anyway I'm writing an ATL
control, and can't use an MFC class (of course I can try to add MFC support
to my ATL project, but that would be the last thing to try). But maybe
studying MFC sources for CPictureHolder can help...
-------------
Ehsan Akhgari
Farda Technology (www.farda-tech.com)
List Owner: [EMAIL PROTECTED]
[ Email: [EMAIL PROTECTED] ]
[ WWW: http://www.beginthread.com/Ehsan ]
I've done the math enough to know the dangers of a second guessing...