VC双缓冲实现

   续前面的聚类算法实验,想要达到可视化的实时更新,并且对聚类的图形进行染色,这里单独开辟一个线程刷新界面,这里为设定一个100ms的计时器不停的invalidate(),然后刷新,这时候发现屏幕上的图形一闪一闪的,或者一行一行的刷新,这样效果不是很理想,这时想到了java里双缓冲的一种实现方法,java中调用repaint()的时候中间会先进行update(),然后在进行paint(),这里MFC调用invalidate()的时候会先调用OnEraseBkgnd(CDC* pDC)函数进行背景填充,然后调用OnDraw(CDC* pDC)函数进行重新绘制。闪烁现象就是因为擦除、重绘这两种的颜色反差导致的,所以这里要取消这种反差。

    实现方法就是不进行擦除,每次重绘的时候在内存中绘制出一张和客户区同样大小的图片,背景颜色及为客户区的颜色,其他元素是你绘制上去的,绘制好这么一张图片之后直接利用CDC的BitBlt方法将内存位图绘制在客户区,这样就消除了闪烁,也及实现了双缓冲,聚类算法实验中实现代码如下:

   

void CDataMiningExample1View::OnDraw(CDC* pDC)
{
	CDataMiningExample1Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO: 在此处为本机数据添加绘制代码
	/*
	int i,length=m_cCluster.m_dataPoints.size(),k=kMeans.size();
	//绘制每个点
	for (i=0;i<length;i++)
	{
		if (m_bEmplify)
		{
			m_cCluster.m_dataPoints[i]->drawSelf(pDC);
		}
		else
		{
			m_cCluster.m_dataPoints[i]->drawNormalSelf(pDC);
		}
	}
	for (i=0;i<k;i++)
	{
		kMeans[i]->drawSelf(pDC);
	}
	*/
	CRect rect;
	GetClientRect(&rect);  //获取客户区的大小
	CDC dcmem;              //创建一个内存DC
	CBitmap bmp;            //创建一个内存位图
	dcmem.CreateCompatibleDC(pDC); //创建一个内存DC
	bmp.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height()); //创建一个内存位图
	dcmem.SelectObject(&bmp); //关联内存DC和内存位图
	dcmem.FillSolidRect(rect,pDC->GetBkColor());//这个相当于擦除的步骤,背景保持背景颜色

	
	int i,length=m_cCluster.m_dataPoints.size(),k=kMeans.size();
	//绘制每个点
	for (i=0;i<length;i++)
	{
		if (m_bEmplify)
		{
			m_cCluster.m_dataPoints[i]->drawSelf(&dcmem);
		}
		else
		{
			m_cCluster.m_dataPoints[i]->drawNormalSelf(&dcmem);
		}
	}
	for (i=0;i<k;i++)
	{
		kMeans[i]->drawSelf(&dcmem);
	}
	//以上是绘制部分
	pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcmem,0,0,SRCCOPY);//内存位图显示出来
	dcmem.DeleteDC();
	bmp.DeleteObject();//清理工作
}

  

BOOL CDataMiningExample1View::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	//return CScrollView::OnEraseBkgnd(pDC);
	return TRUE;
}

  

  以上就是双缓冲的基本实现,其他可以参照。

   

posted @ 2012-12-20 22:23  weixliu  阅读(1921)  评论(0编辑  收藏