双缓冲显示位图

原理:

创建内存位图对象;

创建内存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);



你可能感兴趣的:(双缓冲显示位图)