VC下可以使用 IPicture接口来实现图片显示及放大缩小等功能,具体实现代码:
BOOL LoadPic(char* picName,HDC hdc,DWORD l, DWORD t,DWORD w, DWORD h)
{
IPicture *pPic;
IStream *pStm;
CFileStatus fstatus;
CFile file;
LONG cb;
if(file.Open(picName,CFile::modeRead)&&
file.GetStatus(picName, fstatus)&&
((cb = fstatus.m_size) != -1))
{
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb);
LPVOID pvData = NULL;
if(hGlobal != NULL)
{
if((pvData = GlobalLock(hGlobal)) != NULL)
{
file.ReadHuge(pvData, cb);
GlobalUnlock(hGlobal);
CreateStreamOnHGlobal(hGlobal, TRUE, &pStm);
//HRESULT hr = OleLoadPicturePath(wszPath, (LPUNKNOWN)NULL, 0, 0, IID_IPicture,(VOID**)&pPic);
if(SUCCEEDED(OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic)))
{
OLE_XSIZE_HIMETRIC hmWidth;
OLE_YSIZE_HIMETRIC hmHeight;
pPic->get_Width(&hmWidth);
pPic->get_Height(&hmHeight);
pPic->Render(hdc,l,t,w, h,0,hmHeight,hmWidth,-hmHeight,NULL);
pPic->Release();
}
else
{
return FALSE;
}
}
}
}
else
{
return FALSE;
}
return TRUE;
}
Picture只需要调整Render函数的参数即可实现放大缩小功能,前一个rect是目标矩形,后一个rect是源矩形,调整前一个rect实现缩小,改后一个rect实现放大,需要注意的是后一个rect的单位是0.01mm且坐标系和前一个rect不同。
但是EVC不支持OleLoadPicture和OleLoadPicturePath函数,改用IImage接口实现。IImage是WinCE5.0之后才加入的COM组件,能更为方便显示图片。
用IImage来显示图片很简单,调用几个函数就可以了:
IImage * m_pImage;
IImagingFactory * m_pImagingFactory;
HRESULT hr;
//COM初始化
if (FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED)))
goto END;
//创建COM实例
if(FAILED(hr = CoCreateInstance(CLSID_ImagingFactory,NULL,CLSCTX_INPROC_SERVER,IID_IImagingFactory,(void**) &m_pImagingFactory)))
goto END;
//从文件中创建图片
if(FAILED(hr = m_pImagingFactory->CreateImageFromFile(TEXT("测试.bmp"), &m_pImage)))
goto END;
//绘制图片
if(FAILED(hr = m_pImage->Draw(hdc,&rcWnd,NULL)))
goto END;
END:
//释放资源
if(m_pImage != NULL)
{
m_pImage->Release();
m_pImage = NULL;
}
if(m_pImagingFactory != NULL)
{
m_pImagingFactory->Release();
m_pImagingFactory = NULL;
}
CoUninitialize();
只要将srcRect参数赋值NULL即可显示整副图片,如要显示部分需要设置srcrect的值,和picture::Render一样 这里的srcrect也是以0.01mm为单位的,可以调用IImage::GetImageInfo接口获得原图信息转换为mm。其放大缩小的实现与Render类似。
在这里我遇到了一个问题,在EVC的模拟器上运行时,IImage使用完全正常,但是在WINCE5.0平台上使用时却不能显示图片,把srcrect设为NULL才能在平台上正常显示,但是这样不能实现图片放大功能。模拟器与平台使用同一内核,设置完全一样,我怀疑与IImage::Draw的第2个rect参数有关系,可能是2个rect的坐标系或单位不统一导致的。
这时我换了一种方法,创建一个内存DC,把图片用IImage::Draw按原图大小贴到内存DC上,再使用StretchBlt接口把内存DC里的图片贴到屏幕上,设置StretchBlt函数的参数即可实现原图的放大缩小,唯一的缺憾就是显示大图片时速度较慢。
如果是显示图片的话,用EVC自带的API就可以了SHLoadImageFile(Filename);
C++中可以使用SHLoadImageFile(Filename)函数;需要Include "aygshell.h"
代码如下:
假设这段代码在OnDraw()函数中,并且FileName值已正确给定.可以加载显示jpg,gif类型的图片.
FileName为CString类型.
if(Filename!="")
{
CBitmap bitmap;
bitmap.Attach(SHLoadImageFile(Filename));
BITMAP bmpInfo;
bitmap.GetBitmap(&bmpInfo);
CDC bitmapDC;
bitmapDC.CreateCompatibleDC(pDC);
CBitmap* pOldBitmap = bitmapDC.SelectObject(&bitmap);
pDC->BitBlt(0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,&bitmapDC,0,0,SRCCOPY);
bitmapDC.SelectObject(pOldBitmap);
bitmap.DeleteObject();
}
如果要处理并保存JPG图片,用Independent Jpeg Group的JpegLib就可以.
#include "stdafx.h"
#include "initguid.h"
#include <imaging.h>
#include "ImageLoad.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CImageLoad::CImageLoad()
{
m_hBitmap = NULL;
m_nThumbHeight = 200;
m_nThumbWidth = 300;
m_nHeight = 0;
m_nWidth = 0;
m_nImageFrom = IMAGE_NO_LOAD;
}
CImageLoad::~CImageLoad()
{
if (m_nImageFrom == IMAGE_FROM_FILE){
if (m_hBitmap != NULL){
::DeleteObject(m_hBitmap);
m_hBitmap = NULL;
}
}
}
//加载图片文件,并创建与hdc兼容的位图
BOOL CImageLoad::LoadImageFromFile(HDC hdc, CString szFilepath)
{
IImagingFactory * pImgFactory = NULL;
IImage * pImage = NULL;
HRESULT hRet = ~S_OK;
if((m_nImageFrom == IMAGE_FROM_FILE) && (m_hBitmap != NULL)){
::DeleteObject(m_hBitmap);
m_hBitmap = NULL;
}
CoInitializeEx(NULL, COINIT_MULTITHREADED); //初始化
if(SUCCEEDED(CoCreateInstance(CLSID_ImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IImagingFactory,
(void **)&pImgFactory))){
if(SUCCEEDED(pImgFactory->CreateImageFromFile(szFilepath, &pImage))){
//获取图片信息
ImageInfo imageInfo;
pImage->GetImageInfo(&imageInfo);
m_nWidth = imageInfo.Width;
m_nHeight = imageInfo.Height;
RECT rc = {0, 0, imageInfo.Width, imageInfo.Height};
//为图片存放申请内存
HDC hdcMem = CreateCompatibleDC(hdc);
m_hBitmap = CreateCompatibleBitmap(hdc, imageInfo.Width, imageInfo.Height);
HBITMAP hBmpOld = (HBITMAP)::SelectObject(hdcMem, m_hBitmap);
//拷贝图像到内存空间
hRet = pImage->Draw(hdcMem, &rc, NULL);
pImage->Release();
//释放临时资源
::SelectObject(hdcMem, hBmpOld);
::DeleteDC(hdcMem);
}
pImgFactory->Release();
}
CoUninitialize();
BOOL bRet = TRUE;
m_nImageFrom = IMAGE_FROM_FILE;
if (hRet != S_OK){
if (m_hBitmap != NULL){
::DeleteObject(m_hBitmap);
m_hBitmap = NULL;
}
m_nImageFrom = IMAGE_NO_LOAD;
bRet = FALSE;
}
return bRet;
}
//从位图句柄加载图片
void CImageLoad::LoadImageFromHandle(HBITMAP hBitmap)
{
if((m_nImageFrom == IMAGE_FROM_FILE) && (m_hBitmap != NULL)){
::DeleteObject(m_hBitmap);
}
m_hBitmap = hBitmap;
m_nImageFrom = IMAGE_FROM_HADLE;
//获取位图大小
BITMAP bmp;
::GetObject(hBitmap, sizeof(BITMAP), &bmp);
m_nWidth = bmp.bmWidth;
m_nHeight = bmp.bmHeight;
}
//释放位图资源
void CImageLoad::Release()
{
if((m_nImageFrom == IMAGE_FROM_FILE) && (m_hBitmap != NULL)){
::DeleteObject(m_hBitmap);
}
m_hBitmap = NULL;
}
//取得图片尺寸大小
void CImageLoad::GetImageRect(CRect *rc)
{
rc->top = 0;
rc->left = 0;
rc->right = m_nWidth;
rc->bottom = m_nHeight;
}
//按设定大小,选定图片位置大小绘制到指定hdc
void CImageLoad::DrawToHdc(HDC hdc, CRect DstRc, CRect SrcRc)
{
if (m_nImageFrom == IMAGE_NO_LOAD) return;
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hBmpOld = (HBITMAP)::SelectObject(hdcMem, m_hBitmap);
::StretchBlt(hdc, DstRc.left, DstRc.top, DstRc.Width(), DstRc.Height(),
hdcMem, SrcRc.left, SrcRc.top, SrcRc.Width(), SrcRc.Height(), SRCCOPY);
::SelectObject(hdcMem, hBmpOld);
::DeleteDC(hdcMem);
}
//整个图片绘制到目标hdc的指定位置和大小
void CImageLoad::DrawToHdc(HDC hdc, CRect DstRc)
{
if (m_nImageFrom == IMAGE_NO_LOAD) return;
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hBmpOld = (HBITMAP)::SelectObject(hdcMem, m_hBitmap);
::StretchBlt(hdc, DstRc.left, DstRc.top, DstRc.Width(), DstRc.Height(),
hdcMem, 0, 0, m_nWidth, m_nHeight, SRCCOPY);
::SelectObject(hdcMem, hBmpOld);
::DeleteDC(hdcMem);
}
HBITMAP CImageLoad::GetBitmapHandle()
{
return m_hBitmap;
}
BOOL CImageLoad::IsLoad()
{
if (m_nImageFrom == IMAGE_NO_LOAD){
return FALSE;
}
else{
return TRUE;
}
}
void CTagButton::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
// TODO: Add your code to draw the specified item
BOOL bIsPressed = (lpDIS->itemState & ODS_SELECTED);
BOOL bIsFocused = (lpDIS->itemState & ODS_FOCUS);
BOOL bIsDisabled = (lpDIS->itemState & ODS_DISABLED);
HDC hdc;
hdc = lpDIS->hDC;
HDC hdcMem;
CRect rc = lpDIS->rcItem;
hdcMem = ::CreateCompatibleDC(hdc); //创建兼容内存设备上下文
HBITMAP hbmMem;
hbmMem = ::CreateCompatibleBitmap(hdc, rc.Width(), rc.Height()); //创建兼容位图
HBITMAP hOld = (HBITMAP)::SelectObject(hdcMem, hbmMem); //选入兼容位图到内存设备上下文进行操作
//填充绘制按钮背景
tbFillBackGround(hdcMem);
//绘制按钮图片
tbDrawBmp(hdcMem, bIsPressed);
CDC *pDC = CDC::FromHandle(hdcMem);
//绘制边框
tbDrawFrame(pDC, bIsPressed);
//绘制图标
tbDrawIcon(pDC, bIsPressed);
//绘制文本
tbDrawText(hdcMem, bIsPressed);
//拷贝内存图像到设备
::BitBlt(hdc, 0, 0, rc.Width(), rc.Height(), hdcMem, 0, 0, SRCCOPY);
//销毁hdcMem
::SelectObject(hdcMem, hOld);
::DeleteObject(hbmMem); //销毁创建的位图
::DeleteDC(hdcMem);
//
pDC->DeleteDC();
ReleaseDC(pDC);
AfxGetApp()->OnIdle(1);
}
//绘制按钮图片
void CTagButton::tbDrawBmp(HDC hdcMem, BOOL bIsPressed)
{
if (!m_Image.IsLoad()) return;
//拉伸拷贝按钮图片
int cx,cy,cw,ch;
CRect rc;
GetClientRect(&rc);
cx = rc.left;
cy = rc.top;
cw = rc.Width()-2;
ch = rc.Height() - 2;
if (!m_szCaption.IsEmpty()){
switch(m_capStyle){
case TBCS_TOP:
cy += m_nCapHeight;
ch -= m_nCapHeight;
break;
case TBCS_BOTTOM:
ch -= m_nCapHeight;
break;
case TBCS_VCENTER:
break;
}
}
if (!m_szTag.IsEmpty()){
switch(m_tagStyle){
case TBCS_TOP:
cy += m_nTagHeight;
ch -= m_nTagHeight;
break;
case TBCS_BOTTOM:
ch -= m_nTagHeight;
break;
case TBCS_VCENTER:
break;
}
}
if (bIsPressed){
cx +=2;
cy +=2;
}
m_Image.DrawToHdc(hdcMem, CRect(cx, cy, cx+cw, cy+ch));
}
//绘制按钮边框
void CTagButton::tbDrawFrame(CDC *pDC, BOOL bIsPressed)
{
if (bIsPressed) return;
int cx,cy,cw,ch;
CRect rc;
GetClientRect(&rc);
cx = rc.left;
cy = rc.top;
cw = rc.Width()-2;
ch = rc.Height() - 2;
if (!m_szCaption.IsEmpty()){
switch(m_capStyle){
case TBCS_TOP:
cy += m_nCapHeight;
ch -= m_nCapHeight;
break;
case TBCS_BOTTOM:
ch -= m_nCapHeight;
break;
case TBCS_VCENTER:
break;
}
}
if (!m_szTag.IsEmpty()){
switch(m_tagStyle){
case TBCS_TOP:
cy += m_nTagHeight;
ch -= m_nTagHeight;
break;
case TBCS_BOTTOM:
ch -= m_nTagHeight;
break;
case TBCS_VCENTER:
break;
}
}
//绘制线条
CPen pen, *oldPen;
pen.CreatePen(PS_SOLID,1,RGB(120,120,120));
oldPen = pDC->SelectObject(&pen);
pDC->MoveTo(1, cy + ch+1);
pDC->LineTo(cw+1, cy +ch+1);
pDC->LineTo(cw+1, cy+1);
pDC->MoveTo(cw+2, cy+1);
pDC->LineTo(cw+2, cy + ch+2);
pDC->LineTo(1, cy + ch+2);
pDC->SelectObject(oldPen);
::DeleteObject(pen);
}
//填充绘制按钮背景
void CTagButton::tbFillBackGround(HDC hdcMem)
{
//如果无背景图片,则用制定颜色创建画刷,填充背景
RECT rc;
GetClientRect(&rc);
if (m_bkImage == NULL){
HBRUSH hbr = ::CreateSolidBrush(m_bkColor);
::FillRect(hdcMem, &rc, hbr);
::DeleteObject(hbr);
}
else{
HWND hWnd = ::GetParent(this->m_hWnd);
::MapWindowPoints(this->m_hWnd, hWnd, (LPPOINT)&rc, 2);
// ClientToScreen(&rc);
int nWidth = rc.right - rc.left;
int nHeight = rc.bottom - rc.top;
HDC hdcSrc = ::CreateCompatibleDC(hdcMem);
HBITMAP hbmpOld = (HBITMAP)::SelectObject(hdcSrc, m_bkImage);
::BitBlt(hdcMem, 0, 0, nWidth, nWidth, hdcSrc, rc.left, rc.top, SRCCOPY);
::SelectObject(hdcSrc, hbmpOld);
::DeleteDC(hdcSrc);
}
}
//绘制文本
void CTagButton::tbDrawText(HDC hdcMem, BOOL bIsPressed)
{
CRect rc;
GetClientRect(&rc);
CFont tbFont;
CFont * oldFont;
if(!m_szCaption.IsEmpty()){
//设定标题文本显示位置
switch(m_capStyle){
default:
case TBCS_TOP:
rc.bottom = rc.top + m_nCapHeight;
break;
case TBCS_BOTTOM:
rc.top = rc.bottom - m_nCapHeight;
break;
case TBCS_VCENTER:
rc.top = rc.top + rc.Height()/2 - m_nCapHeight/2;
rc.bottom = rc.top + m_nCapHeight;
break;
}
//判断是否放置光标
if (m_hIcon != NULL){
switch(m_nIconPos){
case TBIC_LEFT: //放置于左侧
rc.left += m_nIconCx;
break;
case TBIC_RIGHT: //放置于右侧
rc.right -= m_nIconCx;
default:
break;
}
}
//判断是否按下
if (bIsPressed){
rc.OffsetRect(2,2);
}
//文本背景透明
SetBkMode(hdcMem, TRANSPARENT);
//设置标题文本颜色
::SetTextColor(hdcMem, m_colorCaption);
//创建标题字体
tbFont.CreateFont(m_nCapHeight,0,0,0,FW_BOLD, FALSE, FALSE, 0,
GB2312_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, _T("myFont"));
oldFont = (CFont*)SelectObject(hdcMem, tbFont);
::DrawText(hdcMem, m_szCaption,-1,&rc,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
SelectObject(hdcMem, oldFont);
tbFont.DeleteObject();
}
GetClientRect(&rc);
if(!m_szTag.IsEmpty()){
//设定标签文本显示位置
switch(m_tagStyle){
default:
case TBCS_TOP:
rc.bottom = rc.top + m_nTagHeight;
break;
case TBCS_BOTTOM:
rc.top = rc.bottom - m_nTagHeight;
break;
case TBCS_VCENTER:
rc.top = rc.top + rc.Height()/2 - m_nTagHeight/2;
rc.bottom = rc.top + m_nTagHeight;
break;
}
if (bIsPressed){
rc.OffsetRect(2,2);
}
//文本背景不透明
SetBkMode(hdcMem, OPAQUE);
::SetBkColor(hdcMem, RGB(200, 200, 200));
//设置标签文本颜色
::SetTextColor(hdcMem, m_colorTag);
//创建标签字体
tbFont.CreateFont(m_nTagHeight,0,0,0,FW_BOLD, FALSE, FALSE, 0,
GB2312_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, _T("myFont"));
oldFont = (CFont*)SelectObject(hdcMem, tbFont);
::DrawText(hdcMem, m_szTag,-1,&rc,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
SelectObject(hdcMem, oldFont);
tbFont.DeleteObject();
}
}
//绘制图标
void CTagButton::tbDrawIcon(CDC *pDC, BOOL bIsPressed)
{
if (m_hIcon == NULL) return;
int x,y,ch;
CRect rc;
GetClientRect(&rc);
x = rc.left;
y = rc.top;
ch = rc.Height();
if (!m_szCaption.IsEmpty()){
switch(m_capStyle){
case TBCS_TOP:
y += m_nCapHeight;
ch -= m_nCapHeight;
break;
case TBCS_BOTTOM:
ch -= m_nCapHeight;
break;
}
}
if (!m_szTag.IsEmpty()){
switch(m_tagStyle){
case TBCS_TOP:
y += m_nTagHeight;
ch -= m_nTagHeight;
break;
case TBCS_BOTTOM:
ch -= m_nTagHeight;
break;
}
}
switch(m_nIconPos){
default:
case TBIC_LEFT: //放置于左侧
x += 4;
y += (ch - m_nIconCy + 1)/2;
break;
case TBIC_CENTER: //放置于水平中央
x += (rc.Width() - m_nIconCx + 1)/2;
y += (ch - m_nIconCy + 1)/2;
break;
case TBIC_RIGHT: //放置于右侧
x = rc.right - 4 - m_nIconCx;
y += (ch - m_nIconCy + 1)/2;
break;
case TBIC_LEFTTOP: //放置于左上角
x += 2;
y += 2;
break;
case TBIC_RIGHTTOP: //放置于右上角
x = rc.right - 2 - m_nIconCx;
y += (ch - m_nIconCy + 1)/2;
break;
case TBIC_LEFTBOTTOM: //放置于左下角
x += 2;
y += ch - 2 - m_nIconCy;
break;
case TBIC_RIGHTBOTTOM: //放置于右下角
x = rc.right - 2 - m_nIconCx;
y += ch - 2 - m_nIconCy;
break;
}
if (bIsPressed){
x +=2;
y +=2;
}
pDC->DrawIcon(x, y, m_hIcon);
}
//设置按钮图片
BOOL CTagButton::SetBitmap(CString szFilepath)
{
if(szFilepath.IsEmpty()){
return FALSE;
}
HDC hdc = ::GetWindowDC(this->m_hWnd);
m_Image.LoadImageFromFile(hdc, szFilepath);
::ReleaseDC(this->m_hWnd, hdc);
Invalidate();
return TRUE;
}
//从位图句柄设置位图
BOOL CTagButton::SetBitmap(HBITMAP hBitmap)
{
if (hBitmap == NULL) return FALSE;
m_hImage = hBitmap;
m_Image.LoadImageFromHandle(hBitmap);
Invalidate();
return TRUE;
}
BOOL CTagButton::SetIcon(HICON hIcon, int cx, int cy, int nIconPos)
{
m_hIcon = hIcon;
m_nIconPos = nIconPos;
m_nIconCx = cx;
m_nIconCy = cy;
Invalidate();
return TRUE;
}
BOOL CTagButton::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Add your specialized code here and/or call the base class
return CButton::PreCreateWindow(cs);
}
void CTagButton::DrawFocus(HDC *hdc, COLORREF color)
{
}
BOOL CTagButton::Create(LPCTSTR lpszCaption, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
// TODO: Add your specialized code here and/or call the base class
m_nID = nID;
dwStyle |= BS_OWNERDRAW;
return CButton::Create(lpszCaption, dwStyle, rect, pParentWnd, nID);
}
void CTagButton::SetTag(CString str, COLORREF color, int style, int nHeight)
{
m_szTag = str;
m_colorTag = color;
m_tagStyle = style;
m_nTagHeight = nHeight;
Invalidate();
}
void CTagButton::SetCaption(CString str, COLORREF color, int style, int nHeight)
{
m_szCaption = str;
m_colorCaption = color;
m_capStyle = style;
m_nCapHeight = nHeight;
Invalidate();
}
void CTagButton::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CButton::OnLButtonDown(nFlags, point);
}
HBITMAP CTagButton::GetBitmap()
{
return m_Image.GetBitmapHandle();
}
BOOL CTagButton::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return TRUE;
//return CButton::OnEraseBkgnd(pDC);
}
void CTagButton::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
DRAWITEMSTRUCT DIS = {0};
DIS.CtlType = ODT_BUTTON;
DIS.CtlID = this->m_nID;
GetClientRect(&DIS.rcItem);
DIS.hDC = dc.m_hDC;
DrawItem(&DIS);
// Do not call CButton::OnPaint() for painting messages
}
BOOL CTagButton::SetBkImage(HBITMAP hBitmap)
{
m_bkImage = hBitmap;
return TRUE;
}
void CTagButton::SetBkColor(COLORREF color)
{
m_bkColor = color;
}
这篇博客详细介绍了在Windows CE环境下如何显示图片,包括使用VC中的IPicture接口和WinCE5.0以后的IImage接口。文章通过示例代码展示了如何加载、缩放图片,并解决在EVC模拟器和WinCE5.0平台上的显示问题。同时,还提到了使用SHLoadImageFile函数来加载和显示图片的方法。

2609

被折叠的 条评论
为什么被折叠?



