使用 IPicture 和 MemDC
6/16/2007 2:38:32 PM
前一段时间,用MFC作个界面程序:画图并在上面写一段文字。原来用IPicture 在DC上 Render ,然后用DC TextOut 出文字,结果文字闪耀。在 OnEraseBkgnd(CDC* pDC) 用了 Mem dc 也没有起作用, 初始还以为刷新快不能做到不闪耀,后来才发现 mem dc 忘了设置 Bitmap ,没有 bitmap 对于内存dc不能画上内容,而 OnPaint 中又没有使用内存DC。导致一直是OnPaint 中DC在画图和写字。
bool DrawPicture(CDC* pdc, IPicture* pic, const CRect& rcBounds)
{
CDC MemDC; //定义内存DC
MemDC.CreateCompatibleDC(NULL); //注意不要写成.CreateCompatibleDC(pdc);
MemDC.SetBkMode(TRANSPARENT); //设置透明,Textout写字没有白色的背景块
//得到图片的宽度和高度
SIZE sizeInHiMetric;
pic->get_Width(&sizeInHiMetric.cx); //获取加载进pic的图像宽度和高度
pic->get_Height(&sizeInHiMetric.cy);
{
CDC MemDC; //定义内存DC
MemDC.CreateCompatibleDC(NULL); //注意不要写成.CreateCompatibleDC(pdc);
MemDC.SetBkMode(TRANSPARENT); //设置透明,Textout写字没有白色的背景块
//得到图片的宽度和高度
SIZE sizeInHiMetric;
pic->get_Width(&sizeInHiMetric.cx); //获取加载进pic的图像宽度和高度
pic->get_Height(&sizeInHiMetric.cy);
CBitmap bmpFace; //创建bitmap
bmpFace.CreateCompatibleBitmap(pdc, rcBounds.Width(), rcBounds.Height());
bmpFace.CreateCompatibleBitmap(pdc, rcBounds.Width(), rcBounds.Height());
//将这幅图片选入内存DC,原来memdc不起作用就是因为,bmp图片没有选入到dc中.郁闷
CBitmap* pOldBmp = MemDC.SelectObject(&bmpFace);
CBitmap* pOldBmp = MemDC.SelectObject(&bmpFace);
//把整个图片 {0,cy,cx,-cy} .拷贝到 memdc 的rcBounds 区域
pic->Render(MemDC.GetSafeHdc(), rcBounds.left, rcBounds.top, rcBounds.right, rcBounds.bottom,
0, sizeInHiMetric.cy, sizeInHiMetric.cx, -sizeInHiMetric.cy, &rcBounds);
0, sizeInHiMetric.cy, sizeInHiMetric.cx, -sizeInHiMetric.cy, &rcBounds);
MemDC.SetTextColor(RGB(0,255,0));
MemDC.TextOut(3,3,m_strFileTips);
MemDC.TextOut(3,3,m_strFileTips);
//拷贝memdc (0,0,rcbounds.width,rcbounds.height) 区域到 pdc
pdc->BitBlt(0,0,rcBounds.Width(),rcBounds.Height(),&MemDC,0,0,SRCCOPY); //拷贝 memdc - > dc
pdc->BitBlt(0,0,rcBounds.Width(),rcBounds.Height(),&MemDC,0,0,SRCCOPY); //拷贝 memdc - > dc
MemDC.SelectObject(pOldBmp);
bmpFace.DeleteObject();
MemDC.DeleteDC();
return true;
}
bmpFace.DeleteObject();
MemDC.DeleteDC();
return true;
}
对于镂空图可以使用
void DrawTransPic(IPicture* pic,const CRect& rc,COLORREF clr)
{
if(pic == NULL)
return;
CDC dc; //内存DC
dc.CreateCompatibleDC(NULL);
CBitmap bmp;
bmp.CreateCompatibleBitmap(&m_MemDC,m_RtDC.Width(),m_RtDC.Height()); //m_RtDC为内存DC区域
CBitmap* pold = dc.SelectObject(&bmp);
SIZE sizeInHiMetric;
pic->get_Width(&sizeInHiMetric.cx);
pic->get_Height(&sizeInHiMetric.cy);
{
if(pic == NULL)
return;
CDC dc; //内存DC
dc.CreateCompatibleDC(NULL);
CBitmap bmp;
bmp.CreateCompatibleBitmap(&m_MemDC,m_RtDC.Width(),m_RtDC.Height()); //m_RtDC为内存DC区域
CBitmap* pold = dc.SelectObject(&bmp);
SIZE sizeInHiMetric;
pic->get_Width(&sizeInHiMetric.cx);
pic->get_Height(&sizeInHiMetric.cy);
//拷贝整个图片到dc整个客户区
pic->Render(dc.GetSafeHdc(), 0, 0, m_RtDC.Width(), m_RtDC.Height(),
0, sizeInHiMetric.cy, sizeInHiMetric.cx, -sizeInHiMetric.cy, NULL); //把 pic 画到真个dc 上
pic->Render(dc.GetSafeHdc(), 0, 0, m_RtDC.Width(), m_RtDC.Height(),
0, sizeInHiMetric.cy, sizeInHiMetric.cx, -sizeInHiMetric.cy, NULL); //把 pic 画到真个dc 上
//这里的m_MemDC 也是内存DC,拷贝dc 整个区域到m_MemDC 的 rc 区域,clr 为要剔除掉的关键色
m_MemDC.TransparentBlt(rc.left,rc.top,rc.Width(),rc.Height(),&dc,0,0,m_RtDC.Width(),m_RtDC.Height(),clr);
bmp.DeleteObject();
dc.SelectObject(pold);
dc.DeleteDC();
}
m_MemDC.TransparentBlt(rc.left,rc.top,rc.Width(),rc.Height(),&dc,0,0,m_RtDC.Width(),m_RtDC.Height(),clr);
bmp.DeleteObject();
dc.SelectObject(pold);
dc.DeleteDC();
}
最后 m_RealDC 真正的设备 dc, 获取全部 memdc 内容
m_RealDC->BitBlt(0,0,m_RtDC.Width(),m_RtDC.Height(),&m_MemDC,0,0,SRCCOPY);
可以在 OnPaint() 和 OnEraseBkgnd(CDC* pDC) 调用该函数DrawPicture 函数,OnEraseBkgnd(CDC* pDC) 注意要 return TRUE;
使用后不再有闪耀的问题。
当然镂空图最好的方法是layerwindow
当然镂空图最好的方法是layerwindow
浙公网安备 33010602011771号