www.pudn.com > JPGGIF.zip > Picture.cpp


 
 
#include "stdafx.h" 
#include "Picture.h" 
 
 
#define HIMETRIC_INCH   2540    // HIMETRIC units per inch 
 
 
//////////////////////////////////////////////////////////////// 
// CPicture implementation 
// 
 
CPicture::CPicture() 
{ 
} 
 
CPicture::~CPicture() 
{ 
} 
 
////////////////// 
// Load from resource. Looks for "IMAGE" type. 
// 
BOOL CPicture::Load(HINSTANCE hInst, UINT nIDRes) 
{ 
	// find resource in resource file 
	HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(nIDRes), "IMAGE"); // type 
	if ( !hRsrc ) 
		return FALSE; 
 
	// load resource into memory 
	DWORD len = ::SizeofResource(hInst, hRsrc); 
	HGLOBAL hResData = ::LoadResource(hInst, hRsrc); 
	if ( !hResData ) 
		return FALSE; 
 
	HGLOBAL hGlobal = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, len); 
	if ( !hGlobal ) 
	{ 
		::FreeResource(hResData); 
		return FALSE; 
	} 
 
	char* pDest = reinterpret_cast ( ::GlobalLock(hGlobal) ); 
	char* pSrc = reinterpret_cast ( ::LockResource(hResData) ); 
	if (!pSrc || !pDest) 
	{ 
		::GlobalFree(hGlobal); 
		::FreeResource(hResData); 
		return FALSE; 
	} 
 
	::CopyMemory(pDest,pSrc,len); 
	::FreeResource(hResData); 
	::GlobalUnlock(hGlobal); 
 
 
	// don't delete memory on object's release 
	IStream* pStream = NULL; 
	if ( ::CreateStreamOnHGlobal(hGlobal,FALSE,&pStream) != S_OK ) 
	{ 
		::GlobalFree(hGlobal); 
		return FALSE; 
	} 
 
	// create memory file and load it 
	BOOL bRet = Load(pStream); 
 
	::GlobalFree(hGlobal); 
 
	return bRet; 
} 
 
////////////////// 
// Load from path name. 
// 
BOOL CPicture::Load(LPCTSTR pszPathName) 
{ 
	HANDLE hFile = ::CreateFile(pszPathName,  
								FILE_READ_DATA, 
								FILE_SHARE_READ, 
								NULL,  
								OPEN_EXISTING, 
								FILE_ATTRIBUTE_NORMAL, 
								NULL); 
	if ( !hFile ) 
		return FALSE; 
 
	DWORD len = ::GetFileSize( hFile, NULL); // only 32-bit of the actual file size is retained 
	if (len == 0) 
		return FALSE; 
 
	HGLOBAL hGlobal = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, len); 
	if ( !hGlobal ) 
	{ 
		::CloseHandle(hFile); 
		return FALSE; 
	} 
 
	char* lpBuffer = reinterpret_cast ( ::GlobalLock(hGlobal) ); 
	DWORD dwBytesRead = 0; 
 
	while ( ::ReadFile(hFile, lpBuffer, 4096, &dwBytesRead, NULL) ) 
	{ 
		lpBuffer += dwBytesRead; 
		if (dwBytesRead == 0) 
			break; 
		dwBytesRead = 0; 
	} 
 
	::CloseHandle(hFile); 
 
	 
	::GlobalUnlock(hGlobal); 
 
 
	// don't delete memory on object's release 
	IStream* pStream = NULL; 
	if ( ::CreateStreamOnHGlobal(hGlobal,FALSE,&pStream) != S_OK ) 
	{ 
		::GlobalFree(hGlobal); 
		return FALSE; 
	} 
 
	// create memory file and load it 
	BOOL bRet = Load(pStream); 
 
	::GlobalFree(hGlobal); 
 
	return bRet; 
} 
 
////////////////// 
// 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); 
 
	return hr == S_OK; 
} 
 
////////////////// 
// Render to device context. Covert to HIMETRIC for IPicture. 
// 
// prcMFBounds : NULL if dc is not a metafile dc 
// 
BOOL CPicture::Render(HDC dc, RECT* rc, LPCRECT prcMFBounds) const 
{ 
 
	if ( !rc || (rc->right == rc->left && rc->bottom == rc->top) )  
	{ 
		SIZE sz = GetImageSize(dc); 
		rc->right = sz.cx; 
		rc->bottom = sz.cy; 
	} 
 
	long hmWidth,hmHeight; // HIMETRIC units 
	GetHIMETRICSize(hmWidth, hmHeight); 
 
	m_spIPicture->Render(dc,  
						rc->left, rc->top,  
						rc->right - rc->left, rc->bottom - rc->top, 
						0, hmHeight, hmWidth, -hmHeight, prcMFBounds); 
 
	return TRUE; 
} 
 
////////////////// 
// Get image size in pixels. Converts from HIMETRIC to device coords. 
// 
SIZE CPicture::GetImageSize(HDC dc) const 
{ 
	SIZE sz = {0,0}; 
 
	if (!m_spIPicture) 
		return sz; 
	 
	LONG hmWidth, hmHeight; // HIMETRIC units 
	m_spIPicture->get_Width(&hmWidth); 
	m_spIPicture->get_Height(&hmHeight); 
 
	sz.cx = hmWidth; 
	sz.cy = hmHeight; 
 
	if ( dc == NULL )  
	{ 
		HDC dcscreen = ::GetWindowDC(NULL); 
 
		SetHIMETRICtoDP(dcscreen,&sz); // convert to pixels 
	}  
	else  
	{ 
		SetHIMETRICtoDP(dc,&sz); 
	} 
	return sz; 
} 
 
 
void CPicture::SetHIMETRICtoDP(HDC hdc, SIZE* sz) const 
{ 
	int nMapMode; 
	if ( (nMapMode = ::GetMapMode(hdc)) < MM_ISOTROPIC && nMapMode != MM_TEXT) 
	{ 
		// when using a constrained map mode, map against physical inch 
		 
		::SetMapMode(hdc,MM_HIMETRIC); 
		POINT pt; 
		pt.x = sz->cx; 
		pt.y = sz->cy; 
		::LPtoDP(hdc,&pt,1); 
		sz->cx = pt.x; 
		sz->cy = pt.y; 
		::SetMapMode(hdc, nMapMode); 
	} 
	else 
	{ 
		// map against logical inch for non-constrained mapping modes 
		int cxPerInch, cyPerInch; 
		cxPerInch = ::GetDeviceCaps(hdc,LOGPIXELSX); 
		cyPerInch = ::GetDeviceCaps(hdc,LOGPIXELSY); 
		sz->cx = MulDiv(sz->cx, cxPerInch, HIMETRIC_INCH); 
		sz->cy = MulDiv(sz->cy, cyPerInch, HIMETRIC_INCH); 
	} 
 
 
	POINT pt; 
	pt.x = sz->cx; 
	pt.y = sz->cy; 
	::DPtoLP(hdc,&pt,1); 
	sz->cx = pt.x; 
	sz->cy = pt.y; 
 
}