Here's my CPictureHolder & CFontHolder classes... <attached> <disclaimer> This is production code which has evolved over time. Some chunks commented out, etc. Although it has not been exhaustively tested, none of the code has had a GPF or leak traced back to it in quite some time. YMMV. </disclaimer>
Ciao, Dee -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] Behalf Of Ehsan Akhgari Sent: Wednesday, February 18, 2004 6:27 AM To: [EMAIL PROTECTED] Subject: RE: [msvc] OleLoadPicture( ) problem > 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... _______________________________________________ msvc mailing list [EMAIL PROTECTED] See http://beginthread.com/mailman/listinfo/msvc_beginthread.com for subscription changes, and list archive.
CPicHolder.h
Description: Binary data
