wince 使用 iimage的问题

pshchao 2011-09-20 10:29:15
在wince中,我要显示设备的信号强度
信号强度用一张PNG的透明图来表示

现在的问题是,贴图的话,只能整张贴出来,我想实现的是根据信号的强度来绘制信号图片的某一部分

比如信号强度在1-10之间,只用绘制一格信号
信号强度满的时候,我才用绘制整张图片

g_pSignalImg->Draw(*pDC,&signalRC,&signalSrcRc);

最后一个参数是资源RC,我尝试更改资源RC的大小实现,但是没有成功,请问各位大牛们,怎么能实现呢?
...全文
270 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
asdwdg 2012-05-29
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]
引用 4 楼 stallion5632 的回复:
这不都是你一个人吗?楼主的这种精神值得尊敬。。:-)


呵呵,没人回答我的问题,我就从其它网上找了半天,找到解决方法了,就贴出来了
[/Quote]
楼主你好!看到了你的帖子,请教一下一个问题:这个IImage是怎么使用的啊,需要什么?
橘色的喵 2011-09-20
  • 打赏
  • 举报
回复
这不都是你一个人吗?楼主的这种精神值得尊敬。。:-)
pshchao 2011-09-20
  • 打赏
  • 举报
回复
问题已解决,楼上为解决方法。 结贴
pshchao 2011-09-20
  • 打赏
  • 举报
回复
IImage的图片显示
2008-01-16 16:19
//========================================================================
//TITLE:
// 详聊IImage的图片显示
//AUTHOR:
// norains
//DATE:
// Sunday 26-August-2007
//Environment:
// EVC4.0 + Windows CE 5.0 Standard SDK
//========================================================================
IImage是WinCE5.0之后才加入的COM组件,用处正如其名,更为方便显示图片.WinCE 5.0之后,我们就可以喜新厌旧,抛弃imgdecmp,转投IImage,呵呵~虽然个人觉得这两个解码,论速度不相伯仲,都是一样的----慢,特别是绘制大图片的时候还有限制,但毕竟有总好过无,所以我们就来看看今天的主角吧!

用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();
OK,就是这么简单,只要OS中只要包含了相应的解码器组件,以上代码显示大部分的图片应该是没问题的.好吧,既然如此,那么这篇豆腐块也就可以结束了~:-)

然而可惜的是,微软向来不会将事情做得很完满,要不然这篇豆腐块到这里确实是尽善尽美了.

这段代码之中,本应风平浪静,但偏偏有一个函数表现怪异,且很容易调用失败,它乃IImage::Draw()!

1)显示源文件特定区域

显示整副图片没啥问题,只要将srcRect参数赋值NULL即可.但如果是显示特定的区域呢?比如说,有一副800*600的图片,我只想显示一半,那该咋办?估计很多人(恩,也包括我),不会仔细看文档,而会是凭借经验直接这么写:

RECT rcSrc = {0,0,400,600};
m_pImage->Draw(hdc,&rcWnd,&rcSrc);

噢,我的上帝,运行这段代码吧!你会看到什么?如果幸运的话,你会一个一个小方块!这时候,估计很多人会问候微软的父母,噢,等等,微软的东西是有不少bug,但这么简单的东西,还不至于让其如此糊涂的.

仔细看看文档关于该参数的说明:An optional pointer to a RECT that specifies, in 0.01mm units, the portion of the image to be drawn in dstRect.

看到最重要的一句了么:in 0.01mm units !! 以0.01mm为单位,非像素点! 虽然微软的出发点是好的,让其显示的精度更为准确,但这个确实给我们带来不少的麻烦.但既然微软接口都如此定义了,与其在这里干跺脚,抱怨微软,还不如我们做点实际的,毕竟我们还是要完成任务,领取每个月的薪水养家糊口.:-(

天无绝人之路,OK,让我们看看单位的转换吧:
m_pImage->GetImageInfo(&ImageInfo);

double dDotPermmX = ImageInfo.Xdpi / 25.4;
double dDotPermmY = ImageInfo.Ydpi / 25.4;

//pSrcRect指向以像素点为单位的区域
RECT rcSrc = {(LONG)(pSrcRect->left / dDotPermmX / 0.01),
(LONG)(pSrcRect->top / dDotPermmY / 0.01),
(LONG)(pSrcRect->right / dDotPermmX / 0.01),
(LONG)(pSrcRect->bottom / dDotPermmY / 0.01)};

m_pImage->Draw(hdc,&rcDraw,&rcSrc);
虽然这样能够基本正常显示指定的区域,但还是有一定的误差,不过接下来讨论的另一个问题,恰好可以解决.


2)IImage::Draw()耗时久

这是一个没有办法的问题,因为IImage::Draw()需要经历一些的解码才能绘制到目标DC,特别是在显示一些特别大的JPEG(如果能够显示的话:-))时更为明显.如果图片仅仅是显示一次,也许问题尚且不那么严重,但如果是需要多次调用,比方说拖动图片,那么这种速度绝对无法忍受的.当然咯,这个问题在将来是肯定不会出现的,并且这个将来也不会很久,不用等到人老珠黄或是为伊消得人憔悴,只要嵌入式设备的解码速度和目前主流的PC相差无几.这一天不会远了,只是对于解决今天的问题却是远水救不了近火,还是乖乖地用技巧解决吧! :-)

方法其实很简单,IImage::Draw()耗时久嘛,那我们只要第一次绘制时将图像保存到内存DC中,然后再把内存DC的数据绘制到目标DC即可.这样一来,仅仅是第一次绘图时感到不愉快(如果你脾气暴躁,也许会感到烦躁),但之后的每次都是畅快之旅.以一次换来一劳永逸,还有比这更便宜的事嘛?

//获取图片属性
m_pImage->GetImageInfo(&ImageInfo);

//创建一个内存DC,用来存储图片数据
hBitmap = CreateCompatibleBitmap(hdc,ImageInfo.Width,ImageInfo.Height);
hdcMem = CreateCompatibleDC(hdc);
hOldSel = SelectObject(hdcMem,hBitmap);

...

//将图片数据存储到内存DC中
rcMemDC = {0,0,ImageInfo.Width,ImageInfo.Height};
m_pImage->Draw(hdcMem,&rcMemDC,NULL);

...

//将图片绘制到目标DC
StretchBlt(hdc,
pDstRect->left,
pDstRect->top,
pDstRect->right - pDstRect->left,
pDstRect->bottom - pDstRect->top,
hdcMem,
pSrcRect->left,
pSrcRect->top,
pSrcRect->right - pSrcRect->left,
pSrcRect->bottom - pSrcRect->top,
SRCCOPY);

只要第一次将图片数据保存到hdcMem中,以后绘制图片时只要绘制hdcMem数据即可,这比还需要经历一次解码过程的IImage::Draw()快多了!

也许有细心的朋友可能会注意到StretchBlt()的形参.恩,在此对这些朋友表示我由衷的敬意.没错,是的,将图片数据保存到hdcMem后,带来的额外一个好处就是,绘制图片某个区域时再也不用转换单位啦!

因为是将整张图片数据存储到hdcMem,所以参数只要设置为NULL;保存到hedMem后,采用StretchBlt()函数绘制只需要以像素为单位.呵呵,是的,没错,无形中我们就避免了单位转换可能带来的损失.所谓的一箭双雕乎?


3)绘制大图片失败

在调用IImage::Draw()绘制大图片时,很有可能导致的后果是:绘制失败.而提示的错误,更多是:E_OUTOFMEMORY,内存不足.这是一个很无奈的现实.虽然我的设备内存已经很明显大于图片所需的,但由于受限制于WinCE5.0 32M虚拟内存,即使是采用旁门左道分配更多的虚拟内存,其结果无非也是:失败!没办法,恩,至少我是没找到解决的方法.

当然咯,万事没绝对,如果对图片质量要求不高,倒还是有法子让其显示的.很简单,只要获取缩略图实例,然后再绘制即可.
m_pImage->GetThumbnail(WIDTH,HEIGHT,&m_pThum);
m_pThum->Draw(hdc,&rcDC,NULL);
这次IImage::Draw()应该不会失败了.当然,如果还是那么倒霉,那唯一的方法就是将WIDTH和HEIGHT减小,直到能正常显示为止.不过,随着数值的减小,图片的质量也会随之降低.
pshchao 2011-09-20
  • 打赏
  • 举报
回复
顶上去,大牛们呢
pshchao 2011-09-20
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 stallion5632 的回复:]
这不都是你一个人吗?楼主的这种精神值得尊敬。。:-)
[/Quote]

呵呵,没人回答我的问题,我就从其它网上找了半天,找到解决方法了,就贴出来了

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧