春天花会开

***********

统计

留言簿(4)

阅读排行榜

评论排行榜

2010年6月19日 #

Windows GDI、GDI+ 绘图 防闪烁

“闪烁”的原因是擦除背景(用背景色重新填充)与绘制前景图像之间有时间差,而且背景和前景颜色有差异,导致眼睛看上去好像在闪烁。
“闪烁”并不主要是因为GDI或GDI+效率低造成的。

解决这个问题需从两个方面入手:1.缩短(或消除)前后景绘图时间差,2.减少绘制次数
1.缩短(或消除)前后景绘图时间差
OnEraseBkgnd(CDC* pDC)
{
    return TRUE;
}

实际上背景填充是必须,否则前景图像与残留的背景混在一起非常杂乱,
这里取消的步骤,其实移到绘图过程了(见2.),合成一张完整图像。

2.减少绘制次数
采用“双缓冲”技术,先在内存缓冲区中完成绘图,再贴到屏幕上
另外如果缓冲图像内容不是变化的,应存为成员对象之类,不要每次去画
一般在OnDraw(CDC* pDC)中完成
///////////////////////////--GDI --////////////////////////////////////
int nWidth=1000;
int nHeight=1000;
CDC MemDC; //首先定义一个显示设备对象
CBitmap MemBitmap;//定义一个位图对象
//随后建立与屏幕显示兼容的内存显示设备
MemDC.CreateCompatibleDC(pDC); //这时还不能绘图,因为没有地方画 ^_^
//下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小
//,也可以自己定义(如:有滚动条时就要大于当前窗口的大小,在BitBlt时决定拷贝内存的哪部分到屏幕上)

MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);
//将位图选入到内存显示设备中
//只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上

CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);
//先用背景色将位图清除干净,这里用原背景色作为背景
//你也可以用自己应该用的颜色

MemDC.FillSolidRect(0,0,nWidth,nHeight,pDC->GetBkColor());
//绘图
CBrush brush(RGB(0,255,0));
 for(int i=0;i<50;i++)
 {
  for(int j=0;j<80;j++)
  {
   //MemDC.Rectangle(10*j,10*i,9,9);
   CRect rc(10*j,10*i,10*j+8,10*i+8);
   MemDC.FillRect(&rc,&brush);
  }
 }
//将内存中的图拷贝到屏幕上进行显示
pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);
//绘图完成后的清理
MemBitmap.DeleteObject();
MemDC.DeleteDC();


///////////////////////////--GDI+ --////////////////////////////////////
 Bitmap* buf=new Bitmap(2000,2000) ;
 Graphics gc(buf);//Graphics.FromImage(buf);
 //反锯齿
 //gc.SetSmoothingMode(SmoothingModeAntiAlias);
 SolidBrush bgbrush(Color(255,255,255,255));
 gc.FillRectangle(&bgbrush,0,0,2000,2000);//背景填充
 Pen      pen(Color(255, 0, 0, 255));
 SolidBrush sbrush(Color(255,0,255,255));
 for(int i=0;i<60;i++)
 {
  for(int j=0;j<60;j++)
   gc.FillRectangle(&sbrush,10*j,10*i,9,9);
 }
 Graphics G(pDC->GetSafeHdc()); 
 G.DrawImage(buf ,0,0);

 

posted @ 2010-06-19 16:09 春天花会开 阅读(2616) | 评论 (1)编辑 收藏