> 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...





Reply via email to