在前面文章中阐述了用CImage类绘图,和绘制放大镜,如果设置HALFTONE此模式,图像才不会失真,但是放大镜上面显示的图像会出现白色斑点,在window sever操作系统中运行,白色斑点不会出现,目前测试在window 7操作系统中发现任然有此问题,而且使用HALFTONE模式显示jpg图像,虽然不失真,但是显示效率明显很慢,放大镜移动起来,视觉效果很差。
针对前面的显示问题,使用网上流传的CPicture类来实现jpg图像的显示以及放大镜功能,可以很好的解决此问题。
CPicture类如下:
#ifndef PICTURE_H
#ifndef picture_h
#define PICTURE_H
#define picture_h
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CPicture
{
public:
CPicture();
virtual ~CPicture();
public:
BOOL LoadPicture(UINT nResource, LPCTSTR lpszResType)
{return LoadPicture(MAKEINTRESOURCE(nResource), lpszResType);}
BOOL LoadPictureFromFile(LPCTSTR lpszFileName);
BOOL LoadPicture(LPCTSTR lpszResource,LPCTSTR lpszResType);
BOOL IsValid(){ return m_pPic!=NULL;}
CSize GetSize(){return m_size;}
void Draw(CDC* pDC, LPCRECT lprcDest, LPCRECT lprcSrc);
void Draw(CDC* pDC, int xDest,int yDest, int cxDest, int cyDest ,
int xSrc ,int ySrc ,int cxSrc ,int cySrc);
void Release();
protected:
IPicture* m_pPic;
OLE_XSIZE_HIMETRIC _w_him;
OLE_YSIZE_HIMETRIC _h_him;
CSize m_size;
protected:
void CalcSize();
};
#endif // define picture_h
#endif // define PICTURE_H
#include "stdafx.h"
#include "Picture.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPicture::CPicture()
:m_pPic(NULL), _h_him(0), _w_him(0), m_size(0,0)
{
}
CPicture::~CPicture()
{
Release();
}
void CPicture::Release()
{
if(m_pPic != NULL)
{
m_pPic->Release();
m_pPic = NULL;
_h_him = _w_him = 0;
m_size.cx = m_size.cy = 0;
}
}
BOOL CPicture::LoadPicture(LPCTSTR lpszResource, LPCTSTR lpszResType)
{
Release();
HINSTANCE hInst = AfxFindResourceHandle(lpszResource, lpszResType);
HRSRC hRsrc = ::FindResource(hInst, lpszResource, lpszResType);
if(hRsrc == NULL) return FALSE;
HGLOBAL hGlobal = LoadResource(hInst, hRsrc);
if(hGlobal == NULL) return FALSE;
DWORD dwSize = SizeofResource(hInst, hRsrc);
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, dwSize);
if(hMem == NULL) return FALSE;
LPVOID pSrc = ::LockResource(hGlobal);
if(pSrc == NULL) {
::GlobalFree(hMem);
return FALSE;
}
LPVOID pDes = ::GlobalLock(hMem);
if(pDes == NULL){
//::GlobalUnlock(hGlobal);
::GlobalFree(hMem);
return FALSE;
}
memcpy(pDes, pSrc, dwSize);
//GlobalUnlock(hGlobal);
GlobalUnlock(hMem);
::FreeResource(hGlobal);
IStream* pStm = NULL;
CreateStreamOnHGlobal(hMem, TRUE, &pStm);
if(!SUCCEEDED(OleLoadPicture(pStm,dwSize,TRUE,IID_IPicture,(LPVOID*)&m_pPic)))
{
pStm -> Release();
::GlobalFree(hMem);
pStm = NULL;
return FALSE;
}
pStm->Release();
::GlobalFree(hMem);
CalcSize();
return TRUE;
}
BOOL CPicture::LoadPictureFromFile(LPCTSTR lpszFileName)
{
Release();
CFile file;
if(!file.Open(lpszFileName, CFile::modeRead))
return FALSE;
DWORD dwSize = file.GetLength();
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, dwSize);
if(hMem == NULL) return FALSE;
LPVOID pDes = ::GlobalLock(hMem);
if(pDes == NULL){
::GlobalFree(hMem);
return FALSE;
}
//file.ReadHuge(pDes, dwSize);
file.Read(pDes,dwSize);
file.Close();
GlobalUnlock(hMem);
IStream* pStm = NULL;
CreateStreamOnHGlobal(hMem, TRUE, &pStm);
if(!SUCCEEDED(OleLoadPicture(pStm,dwSize,TRUE,IID_IPicture,(LPVOID*)&m_pPic)))
{
pStm -> Release();
::GlobalFree(hMem);
pStm = NULL;
return FALSE;
}
pStm->Release();
::GlobalFree(hMem);
CalcSize();
return TRUE;
}
如何用此类实现放大镜功能呢?如下利用双缓冲技术,实现放大镜
CDC * pDC=GetDlgItem(IDC_DISIMAGE_STATIC)->GetDC();
//创建内存DC
CDC dcMem;
dcMem.CreateCompatibleDC(pDC); //依附窗口DC创建兼容内存DC
CBitmap bmp; //内存中承载临时图象的位图
bmp.CreateCompatibleBitmap(pDC,1224,1024);//创建兼容位图
dcMem.SelectObject(&bmp);
m_Image.Draw(&dcMem,CRect(0,0,816,682),CRect(0,0,2448,2048));//绘制原始图像
m_Image.Draw(&dcMem,ndRect.left,ndRect.top,ndRect.Width(),ndRect.Height(),nsRect.left*3,nsRect.top*3,nsRect.Width()*3,nsRect.Height()*3);//绘制放大镜
pDC->BitBlt(0,0,816,682,&dcMem,0,0,SRCCOPY);//将内存DC上的图象拷贝到前台
dcMem.DeleteDC(); //删除DC
bmp.DeleteObject(); //删除位图
ReleaseDC(pDC);