//
// 类的声明~
//
class CMyPicture
{
public:
CMyPicture();
virtual ~CMyPicture();
public:
void FreePictureData();
BOOL Load(CString sFilePathName);
BOOL Load(UINT ResourceName, LPCSTR ResourceType);
BOOL LoadPictureData(BYTE* pBuffer, int nSize);
BOOL SaveAsBitmap(CString sFilePathName);
BOOL Show(CDC* pDC, CPoint LeftTop, CPoint WidthHeight, int MagnifyX, int MagnifyY);
BOOL Show(CDC* pDC, CRect DrawRect);
BOOL ShowBitmapResource(CDC* pDC, const int BMPResource, CPoint LeftTop);
BOOL UpdateSizeOnDC(CDC* pDC);
public:
IPicture* m_IPicture; // Same As LPPICTURE (typedef IPicture __RPC_FAR *LPPICTURE)
LONG m_Height; // Height (In Pixels Ignor What Current Device Context Uses)
LONG m_Weight; // Size Of The Image Object In Bytes (File OR Resource)
LONG m_Width; // Width (In Pixels Ignor What Current Device Context Uses)
};
//
// 类的定义~
//
#include "MyPicture.h"
CMyPicture::CMyPicture()
{
m_IPicture = NULL;
m_Height = 0;
m_Weight = 0;
m_Width = 0;
}
CMyPicture::~CMyPicture()
{
if(m_IPicture != NULL)
FreePictureData(); // 避免内存泄漏~
}
void CMyPicture::FreePictureData()
{
if(m_IPicture != NULL)
{
m_IPicture->Release();
m_IPicture = NULL;
m_Height = 0;
m_Weight = 0;
m_Width = 0;
}
}
BOOL CMyPicture::Load(UINT ResourceName, LPCSTR ResourceType)
{
BOOL bResult = FALSE;
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
HGLOBAL hGlobal = NULL;
HRSRC hSource = NULL;
LPVOID lpVoid = NULL;
int nSize = 0;
if(m_IPicture != NULL)
FreePictureData();
hSource = FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(ResourceName), ResourceType);
if(hSource == NULL)
{
MessageBoxEx(hWnd, "FindResource() Failed/t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
return FALSE;
}
hGlobal = LoadResource(AfxGetResourceHandle(), hSource);
if(hGlobal == NULL)
{
MessageBoxEx(hWnd, "LoadResource() Failed/t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
return FALSE;
}
lpVoid = LockResource(hGlobal);
if(lpVoid == NULL)
{
MessageBoxEx(hWnd, "LockResource() Failed/t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
return FALSE;
}
nSize = (UINT)SizeofResource(AfxGetResourceHandle(), hSource);
if(LoadPictureData((BYTE*)hGlobal, nSize))
bResult = TRUE;
UnlockResource(hGlobal); // 16Bit Windows Needs This
FreeResource(hGlobal); // 16Bit Windows Needs This (32Bit - Automatic Release)
m_Weight = nSize; // Update Picture Size Info...
if(m_IPicture != NULL) // Do Not Try To Read From Memory That Is Not Exist...
{
m_IPicture->get_Height(&m_Height);
m_IPicture->get_Width(&m_Width);
// Calculate Its Size On a "Standard" (96 DPI) Device Context
m_Height = MulDiv(m_Height, 96, HIMETRIC_INCH);
m_Width = MulDiv(m_Width, 96, HIMETRIC_INCH);
}
else // Picture Data Is Not a Known Picture Type
{
m_Height = 0;
m_Width = 0;
bResult = FALSE;
}
return bResult;
}
BOOL CMyPicture::Load(CString sFilePathName)
{
BOOL bResult = FALSE;
CFile PictureFile;
CFileException e;
int nSize = 0;
if(m_IPicture != NULL)
FreePictureData(); // Important - Avoid Leaks...
if(PictureFile.Open(sFilePathName, CFile::modeRead | CFile::typeBinary, &e))
{
nSize = PictureFile.GetLength();
BYTE* pBuffer = new BYTE[nSize];
// 从文件读到pBuffer
if (PictureFile.Read(pBuffer, nSize) > 0 )
{
// 接作调用函数读pBuffer
if(LoadPictureData(pBuffer, nSize))
bResult = TRUE;
}
PictureFile.Close();
delete [] pBuffer;
}
else // Open Failed...
{
TCHAR szCause[255];
e.GetErrorMessage(szCause, 255, NULL);
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, szCause, ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
bResult = FALSE;
}
m_Weight = nSize; // Update Picture Size Info...
if(m_IPicture != NULL) // Do Not Try To Read From Memory That Is Not Exist...
{
m_IPicture->get_Height(&m_Height);
m_IPicture->get_Width(&m_Width);
// Calculate Its Size On a "Standard" (96 DPI) Device Context
m_Height = MulDiv(m_Height, 96, HIMETRIC_INCH);
m_Width = MulDiv(m_Width, 96, HIMETRIC_INCH);
}
else // 未知 // Picture Data Is Not a Known Picture Type
{
m_Height = 0;
m_Width = 0;
bResult = FALSE;
}
return bResult;
}
BOOL CMyPicture::LoadPictureData(BYTE *pBuffer, int nSize)
{
BOOL bResult = FALSE;
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, nSize);
if(hGlobal == NULL)
{
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "Can not allocate enough memory/t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
return FALSE;
}
void* pData = GlobalLock(hGlobal);
memcpy(pData, pBuffer, nSize);
GlobalUnlock(hGlobal);
IStream* pStream = NULL;
if(CreateStreamOnHGlobal(hGlobal, TRUE, &pStream) == S_OK)
{
HRESULT hr;
if((hr = OleLoadPicture(pStream, nSize, FALSE, IID_IPicture, (LPVOID *)&(this->m_IPicture) )) == E_NOINTERFACE)
{
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "IPicture interface is not supported/t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
return FALSE;
}
else // S_OK
{
pStream->Release();
pStream = NULL;
bResult = TRUE;
}
}
FreeResource(hGlobal); // 16Bit Windows Needs This (32Bit - Automatic Release)
return bResult;
}
BOOL CMyPicture::Show(CDC *pDC, CRect DrawRect)
{
// CDC为空或者没有图片就返回~
if(pDC == NULL || m_IPicture == NULL)
return FALSE;
long Width = 0;
long Height = 0;
m_IPicture->get_Width(&Width);
m_IPicture->get_Height(&Height);
HRESULT hrP = NULL;
hrP = m_IPicture->Render(pDC->m_hDC,
DrawRect.left, // Left
DrawRect.top, // Top
DrawRect.right - DrawRect.left, // Width
DrawRect.bottom - DrawRect.top, // Height
0,
Height,
Width,
-Height,
&DrawRect);
if (SUCCEEDED(hrP))
return TRUE;
// 无法显示图片
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "Can not allocate enough memory/t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
return FALSE;
}
BOOL CMyPicture::Show(CDC *pDC, CPoint LeftTop, CPoint WidthHeight, int MagnifyX=0, int MagnifyY=0)
{
// CDC为空或者没有图片就返回~
if (pDC == NULL || m_IPicture == NULL)
return FALSE;
long Width = 0;
long Height = 0;
m_IPicture->get_Width(&Width);
m_IPicture->get_Height(&Height);
// if(MagnifyX == NULL) MagnifyX = 0;
// if(MagnifyY == NULL) MagnifyY = 0;
MagnifyX = int(MulDiv(Width, pDC->GetDeviceCaps(LOGPIXELSX), HIMETRIC_INCH) * MagnifyX);
MagnifyY = int(MulDiv(Height,pDC->GetDeviceCaps(LOGPIXELSY), HIMETRIC_INCH) * MagnifyY);
CRect DrawRect(LeftTop.x, LeftTop.y, MagnifyX, MagnifyY);
HRESULT hrP = NULL;
hrP = m_IPicture->Render(pDC->m_hDC,
LeftTop.x, // Left
LeftTop.y, // Top
WidthHeight.x + MagnifyX, // Width
WidthHeight.y + MagnifyY, // Height
0,
Height,
Width,
-Height,
&DrawRect);
// 若成功
if(SUCCEEDED(hrP))
return TRUE;
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "Can not allocate enough memory/t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
return FALSE;
}
BOOL CMyPicture::SaveAsBitmap(CString sFilePathName)
{
BOOL bResult = FALSE;
ILockBytes *Buffer = 0;
IStorage *pStorage = 0;
IStream *FileStream = 0;
BYTE *BufferBytes;
STATSTG BytesStatistics;
DWORD OutData;
long OutStream;
CFile BitmapFile; CFileException e;
double SkipFloat = 0;
DWORD ByteSkip = 0;
_ULARGE_INTEGER RealData;
CreateILockBytesOnHGlobal(NULL, TRUE, &Buffer); // Create ILockBytes Buffer
HRESULT hr = ::StgCreateDocfileOnILockBytes(Buffer,
STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, &pStorage);
hr = pStorage->CreateStream(L"PICTURE",
STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, 0, &FileStream);
m_IPicture->SaveAsFile(FileStream, TRUE, &OutStream); // Copy Data Stream
FileStream->Release();
pStorage->Release();
Buffer->Flush();
// Get Statistics For Final Size Of Byte Array
Buffer->Stat(&BytesStatistics, STATFLAG_NONAME);
// Cut UnNeeded Data Coming From SaveAsFile() (Leave Only "Pure" Picture Data)
SkipFloat = (double(OutStream) / 512); // Must Be In a 512 Blocks...
if(SkipFloat > DWORD(SkipFloat)) ByteSkip = (DWORD)SkipFloat + 1;
else ByteSkip = (DWORD)SkipFloat;
ByteSkip = ByteSkip * 512; // Must Be In a 512 Blocks...
// Find Difference Between The Two Values
ByteSkip = (DWORD)(BytesStatistics.cbSize.QuadPart - ByteSkip);
// Allocate Only The "Pure" Picture Data
RealData.LowPart = 0;
RealData.HighPart = 0;
RealData.QuadPart = ByteSkip;
BufferBytes = (BYTE*)malloc(OutStream);
if(BufferBytes == NULL)
{
Buffer->Release();
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "Can not allocate enough memory/t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
}
Buffer->ReadAt(RealData, BufferBytes, OutStream, &OutData);
if(BitmapFile.Open(sFilePathName, CFile::typeBinary | CFile::modeCreate | CFile::modeWrite, &e))
{
BitmapFile.Write(BufferBytes, OutData);
BitmapFile.Close();
bResult = TRUE;
}
else // Write File Failed...
{
TCHAR szCause[255];
e.GetErrorMessage(szCause, 255, NULL);
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, szCause, ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
bResult = FALSE;
}
Buffer->Release();
free(BufferBytes);
return bResult;
}
BOOL CMyPicture::ShowBitmapResource(CDC *pDC, const int BMPResource, CPoint LeftTop)
{
if (pDC == NULL)
return(FALSE);
CBitmap BMP;
if(BMP.LoadBitmap(BMPResource))
{
// Get Bitmap Details
BITMAP BMPInfo;
BMP.GetBitmap(&BMPInfo);
// Create An In-Memory DC Compatible With The Display DC We R Gonna Paint On
CDC DCMemory;
DCMemory.CreateCompatibleDC(pDC);
// Select The Bitmap Into The In-Memory DC
CBitmap* pOldBitmap = DCMemory.SelectObject(&BMP);
// Copy Bits From The In-Memory DC Into The On-Screen DC
pDC->BitBlt(LeftTop.x, LeftTop.y, BMPInfo.bmWidth, BMPInfo.bmHeight, &DCMemory, 0, 0, SRCCOPY);
DCMemory.SelectObject(pOldBitmap); // (As Shown In MSDN Example...)
}
else
{
TRACE("ERROR: Can Not Find The Bitmap Resource/n");
return FALSE;
}
return TRUE;
}
BOOL CMyPicture::UpdateSizeOnDC(CDC *pDC)
{
if(pDC == NULL || m_IPicture == NULL)
{
m_Height = 0;
m_Width = 0;
return FALSE;
}
m_IPicture->get_Height(&m_Height);
m_IPicture->get_Width(&m_Width);
// Get Current DPI - Dot Per Inch
int CurrentDPI_X = pDC->GetDeviceCaps(LOGPIXELSX);
int CurrentDPI_Y = pDC->GetDeviceCaps(LOGPIXELSY);
// Use a "Standard" Print (When Printing)
if(pDC->IsPrinting())
{
CurrentDPI_X = 96;
CurrentDPI_Y = 96;
}
m_Height = MulDiv(m_Height, CurrentDPI_Y, HIMETRIC_INCH);
m_Width = MulDiv(m_Width, CurrentDPI_X, HIMETRIC_INCH);
return TRUE;
}
//
// 如何使用~
//
CMyPicture m_Pic;
m_Pic.UpdateSizeOnDC(&dc);
m_Pic.Show(&dc,CRect(0,0,180,180));
... 还有很多~