VS之双缓冲技术

当数据量很大时,绘图可能需要几秒钟甚至更长的时间,而且有时还会出现闪烁现象,为了解决这些问题,可采用双缓冲技术来绘图。

双缓冲即在内存中创建一个与屏幕绘图区域一致的对象,先将图形绘制到内存中的这个对象上,再一次性将这个对象上的图形拷贝到屏幕上,这样能大大加快绘图的速度。


下面使用一个简单的例子来说明

不使用双缓冲技术代码:

void CMyStatic::Draw1(CPaintDC& dc)
{
	RECT rect;
	GetClientRect(&rect);

	CBrush brush0(RGB(240,240,240));
	dc.FillRect(&rect,&brush0);

	RECT rt = rect;	
	
	UINT  nFormat;
	HFONT hFont = ::CreateFontIndirect(&m_LogFont);
	HFONT hOldFont = (HFONT)::SelectObject(dc.m_hDC,hFont);
	dc.SetBkMode(TRANSPARENT);

	//name 
	nFormat = DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_END_ELLIPSIS;
	dc.SetTextColor(m_dwNameColor);

	rt.right = rt.left + m_nNameWidth;
	rt.bottom  = rt.top + m_nHeight;
	dc.DrawText(m_sSignalName,&rt,nFormat);

	//value
	nFormat = DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_END_ELLIPSIS;
	rt.left  = rt.right;
	rt.right = rt.left + m_nValueWidth;
	dc.FillSolidRect(&rt,m_dwSignalBgColor);
	dc.SetTextColor(m_dwSignalTxtColor);
	dc.DrawText(m_sSignalValue,&rt,nFormat);

	//unit
	rt.left = rt.right;
	rt.right = rt.left + m_nUnitWidth;
	dc.SetTextColor(m_dwNameColor);
	dc.DrawText(m_sSignalUnit,&rt,nFormat);

	CPen bkPen(PS_SOLID,3,RGB(192,192,192));
	hFont = (HFONT)::SelectObject(dc.m_hDC,hOldFont);
	::DeleteObject(hFont);
}

使用双缓冲技术代码:

void CMyStatic::Draw2(CPaintDC& dc)
{
	CRect rect;
	GetClientRect(&rect);

	CDC dcMem;
	dcMem.CreateCompatibleDC(&dc);//创建与视图的设备相兼容的内存设备,新的设备不具有与原设备相同的设备属性与背景色.

	CBitmap bmp;
	if(bmp.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height()))//创建一个与视图兼容的位图,只有根据原设备来创建位图,才能从设备中获取像素点组成位图,因为双缓冲需要保留原设备中已有的图像,因此需要调用这个方法
	{
		CBitmap* pOldBmp = dcMem.SelectObject(&bmp);//选择位图,只是修改了设备属性,并没有真正绘图.

		CBrush brush0(RGB(240,240,240));
		dcMem.FillRect(&rect,&brush0);

		RECT rt = rect;
		
		UINT  nFormat;
		HFONT hFont = ::CreateFontIndirect(&m_LogFont);
		HFONT hOldFont = (HFONT)::SelectObject(dcMem.m_hDC,hFont);
		dcMem.SetBkMode(TRANSPARENT);

		//name 
		nFormat = DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_END_ELLIPSIS;
		dcMem.SetTextColor(m_dwNameColor);//画文字
		rt.right = rt.left + m_nNameWidth;
		rt.bottom  = rt.top + m_nHeight;
		dcMem.DrawText(m_sSignalName,&rt,nFormat);

		//value
		nFormat = DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_END_ELLIPSIS;
		rt.left  = rt.right;
		rt.right = rt.left + m_nValueWidth;
		dcMem.FillSolidRect(&rt,m_dwSignalBgColor);
		dcMem.SetTextColor(m_dwSignalTxtColor);
		dcMem.DrawText(m_sSignalValue,&rt,nFormat);

		//unit
		rt.left = rt.right;
		rt.right = rt.left + m_nUnitWidth;
		dcMem.SetTextColor(m_dwNameColor);
		dcMem.DrawText(m_sSignalUnit,&rt,nFormat);

		CPen bkPen(PS_SOLID,3,RGB(192,192,192));
		hFont = (HFONT)::SelectObject(dcMem.m_hDC,hOldFont);
		::DeleteObject(hFont);

		// paint the window onto the memory bitmap
		//CWnd::DefWindowProc(WM_PAINT, (WPARAM)dcMem.m_hDC, 0);

		// copy it to the window's DC
		dc.BitBlt(0, 0, rect.right, rect.bottom, &dcMem, 0, 0, SRCCOPY);//将在内存中绘制好的图像重新显示到视图中,pDC与dcMem不必兼容.

		dcMem.SelectObject(pOldBmp);

		bmp.DeleteObject();
	}
	dcMem.DeleteDC();
}

对比发现,在程序中,我们需要实现双缓冲技术,操作很方便,只需要添加如下代码即可

	CRect rect;
	GetClientRect(&rect);

	CDC dcMem;
	dcMem.CreateCompatibleDC(&dc);//创建与视图的设备相兼容的内存设备,新的设备不具有与原设备相同的设备属性与背景色.

	CBitmap bmp;
	if(bmp.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height()))//创建一个与视图兼容的位图,只有根据原设备来创建位图,才能从设备中获取像素点组成位图,因为双缓冲需要保留原设备中已有的图像,因此需要调用这个方法
	{
		CBitmap* pOldBmp = dcMem.SelectObject(&bmp);//选择位图,只是修改了设备属性,并没有真正绘图.

		/*技术实现*/
		
		// paint the window onto the memory bitmap
		//CWnd::DefWindowProc(WM_PAINT, (WPARAM)dcMem.m_hDC, 0);

		// copy it to the window's DC
		dc.BitBlt(0, 0, rect.right, rect.bottom, &dcMem, 0, 0, SRCCOPY);//将在内存中绘制好的图像重新显示到视图中,pDC与dcMem不必兼容.

		dcMem.SelectObject(pOldBmp);

		bmp.DeleteObject();
	}
	dcMem.DeleteDC();



你可能感兴趣的:(vs,双缓冲)