原理:
创建内存位图对象;
创建内存DC;
将位图对象选入到内存DC,便可以在内存DC中画图;
最后将内存DC中的图拷贝到窗口DC
在BOOL C***Dlg::OnEraseBkgnd(CDC* pDC) 中实现:
CDC MemDC; //定义一个显示设备对象
CBitmap MemBitmap;//定义一个内存位图对象
//随后建立与屏幕显示兼容的内存显示设备
MemDC.CreateCompatibleDC(NULL); //或者MemDC.CreateCompatibleDC(pDc);
//这时还不能绘图,因为没有地方画
//下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小
MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);
//将位图选入到内存显示设备中
//只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上
CBitmap *pOldBitmap = MemDC.SelectObject(&MemBitmap);
//先用背景色将位图清除干净,这里我用的是白色作为背景
//你也可以用自己应该用的颜色
MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));
//绘图内存图(如果是现成的位图,只要LoadBitmap一下资源就可以直接贴图了)
MemDC.MoveTo(……);
MemDC.LineTo(……);
...等等绘图操作
//最后再将内存中的图全部拷贝到屏幕上进行显示
pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);
//还原内存DC原来位图(通常省略)
memDC.SelectObject(pOldBitmap);
//绘图完成后的清理
MemBitmap.DeleteObject();
MemDC.DeleteDC();
例 1:
//加载图片
CBitmap m_BkGndBmp;
m_BkGndBmp.LoadBitmap(IDB_BITMAP3);
//获取窗口大小
CRect rcClient;
GetClientRect(&rcClient);
//获取图片大小
BITMAP bm;
m_BkGndBmp.GetBitmap(&bm);
//创建内存DC
CDC memDC;
memDC.CreateCompatibleDC(pDC);
//将为图选入DC
CBitmap *pOldBmp = memDC.SelectObject(&m_BkGndBmp);
//拷贝DC到窗口
pDC->StretchBlt(0, 0, rcClient.Width(), rcClient.Height(), &memDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
//清理内存
memDC.SelectObject(pOldBmp);
memDC.DeleteDC();
例 2:
//背景重绘
//注意: 为了避免动态进度条的闪烁,通过两个办法:
//(1).将所有要绘制的,如圆角边框,内部填充色,动态链接图片等等先画到内存,最后再从内存拷贝到屏幕
//(2).屏蔽系统的CDialogEx::OnEraseBkgnd(pDC);
BOOL CConnectDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//CDialogEx::OnEraseBkgnd(pDC); //屏蔽以避免闪烁
//窗口大小
CRect rc;
GetClientRect(&rc);
//创建内存DC
CDC dcTmp;
dcTmp.CreateCompatibleDC(pDC);
//创建内存位图(大小通常用窗口大小)
CBitmap bmpTmp;
bmpTmp.CreateCompatibleBitmap(pDC, rc.Width(), rc.Height());
//将位图选入内存DC
CBitmap *pOldBitmap = dcTmp.SelectObject(&bmpTmp);
//下面操作开始在内存DC中画图
//操作1:画窗口的圆角边框及内部填充色
POINT pt;
pt.x = 5;
pt.y = 5;
CRect rc2(rc); //画边框时需要向内缩进
rc2.right -= 1;
rc2.bottom -= 1;
CPen hNewPen(PS_SOLID, 1, RGB(170, 170, 170));
CPen* hOldPen = dcTmp.SelectObject(&hNewPen);
dcTmp.RoundRect(&rc2, pt); //注意:RoundRect()会将自动填充内部颜色为默认画笔的RGB(255,255,255)
dcTmp.SelectObject(hOldPen);
rc2.DeflateRect(CSize(GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE))); //区域向内缩进一个边框
CBrush brush(RGB(240, 240, 240)); //故画线后需要重新填充内部颜色
dcTmp.FillRect(&rc2, &brush);
brush.DeleteObject();
//操作2:加载图片
Graphics graphics(dcTmp.GetSafeHdc());
graphics.DrawImage(m_pImage1, m_nX, m_nY, m_nW, m_nH);
graphics.DrawImage(m_pImage2, m_rcProcess, m_nOffsetX, 0, m_rcProcess.Width, m_rcProcess.Height, UnitPixel);
//操作3:绘制按钮
DrawTitleButton(&dcTmp);
//然后将画好的内存图全部拷贝到屏幕上显示
pDC->BitBlt(0, 0, rc.Width(), rc.Height(), &dcTmp, 0, 0, SRCCOPY);
//还原原来的DC
dcTmp.SelectObject(pOldBitmap);
//最后清理内存
bmpTmp.DeleteObject();
dcTmp.DeleteDC();
return TRUE;
}
位图拷贝函数说明(区别在于StretchBlt()可进行图片拉伸或压缩):
该函数对指定的源设备环境区域中的像素进行位块(bit_block)转换,以传送到目标设备环境。
BOOL BitBlt(int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop);
函数从源矩形中复制一个位图到目标矩形,必要时按目标设备设置的模式进行图像的拉伸或压缩。
BOOL StretchBlt(int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop);