如果要求那么快的速度的话,还是用DirectDraw吧,你用BitBlt再怎么也不行,你不可能把你要显示的全存在内存中呀。

解决方案 »

  1.   

    directdraw我刚学,很难,但很强大,真的!
      

  2.   

    用DDraw!绝对没问题!SetTimer的interval单位是毫秒吧,我设成1那surface愣是没闪一下。用一个offscreen Surface来bit就行了,一样可用DC的GDI函数。
      

  3.   

    Use "false" for the third parameter in InvaildateRect()... not "true"
    Example : 
    InvalidateRect(hwnd, &rect, false);
      

  4.   

    To minkerui: 由我上面的描述中,就是按双缓存的。即,对画的操作是对内存位图进行的操作,直到画完后,才一次性的BitBlt给OnDraw中的pDC。
      

  5.   

    35就不闪了REALPLAY一般到这个数就没事了
      

  6.   

    You can try to use GDIPlus.
    Easy and Simple.
      

  7.   

    什么是GDIPlue,能说明一下嘛?
      

  8.   

    GDIPlus是什么呀?能说明一下吗?
      

  9.   

    你可以试着用将背景划分成N个区域,每隔一段时间InvalidateRegion()一个不同的区域,通过这样的方法来画完整个背景,我想应该不会闪烁
      

  10.   

    哈哈,你是要做程序的splash吧!
    不用timer,只要在中途处理消息就行了。
      

  11.   

    To huapu: 我用过中途处理消息,但是依然被阻塞:(
    To Ah: 我测过相同图形,一样要闪烁的。再说,我需要的是图形的渐变,自然不是相同的图形,只是每次图形的变化不大就是。
      

  12.   

    好像OnTimer最快每秒钟只能触发18.2次。
      

  13.   

    为什么要刷新整个位图?只是刷新你需要显示的部分就可以了,InvalidateRect()即可
      

  14.   

    不要用Invalidate的方法,可以写一个函数假如;
    CDC m_memDC;//.h中声明一个内存DC
    Draw()
    {
    CClientDC dc(this);
    dc.BitBlt(0, 0, 0, 0, &m_memDC, 0, 0, SRCCOPY);
    }
    MakeMemBmp()
    {
    //根据参数把图片画到m_memDC中
    ...
    }然后在Timer中调用MakeMemBmp()和Draw()就可以了.
      

  15.   

    还有就是在OnDraw(CDC *pDC):
    pDC->BitBlt(0,  0,  0,  0,  &  m_memDC,  0,  0,  SRCCOPY);
    这样就保证了,当其他窗口覆盖本窗口时可以自动刷新.
      

  16.   

    为什么不给bluekite(bluekite)分呢?
    InvalidateRect(hwnd,  &  rect,  false);
      

  17.   

    这样就不要用Timer了,还是分立一个线程。
    双缓冲就可以保证不闪烁。
    BitBlt速度不够快,
    如果不想用DDraw,可以用vfw的相关函数,性能肯定够,还支持Dither
      

  18.   

    试试响应WM_ERASEBKGND消息,直接返回TRUE。
      

  19.   

    不用invalidate();直接在timer中画。
      

  20.   

    我也是用的GDI用了双缓冲,一秒最多10帧也不会闪啊
      

  21.   

    次数不限,用
    Invalidate(FALSE);
    刷新.
      

  22.   

    就算一秒钟从1到100幅都是不会闪的。你的问题是你用了Invalidate()!!!!
    你直接BitBlt();绝对不可能闪。如果用DDraw,你不断的清空背景才画图,一样闪到你晕。我的意思是你不要在定时器中触发Invalidate();你要直接BitBlt。
      

  23.   

    应该是CPU刷新不过来吧!
    你应该做更多的细节工作!
      

  24.   

    用OnTimer,你设置是50MS但实际有很多次是接格几百MS运行一次
      

  25.   

    你可以使用缓冲机制,这样不会闪烁,只是性能太查,cpu站用过大。
      

  26.   

    如果是我做的(BCB),我会设计两个图像控件,
      1、将第一个的显示特性设为禁止,
      2、将要显示的图形复制到禁止显示的图像控件上
      3、将第一个图像控件的显示特性设为允许,第二个设为禁;
      4、转到第二步如此重复,我曾做过25帧,但没有做过50帧。
      

  27.   

    帧数和闪烁无关,关键问题是如果一个图片画到屏幕前,先清空屏幕的话(也就是把窗口覆盖上颜色),就会闪烁,就是说不能让窗口自己画,也就是不能调用Invalidate(),直接把内存位图BitBlt到DC就可以了
      

  28.   

    很巧,我也在onpaint()里频繁更新图像,但使用双缓冲后并没有闪烁感。
    我觉得你可以参考这篇文章http://www.5xsoft.com/data/200112/2508190801.htm我现在有个问题,望高手指教。就是下面这段代码:
    在OnPaint() 中 CPaintDC dc(this); // device context for painting
    // dc.TextOut(clientrect.CenterPoint().x,clientrect.CenterPoint().y,"dcdfffffffffff");
    CDC* pDC=(CDC*) &dc;
    //利用双缓存技术

    CDC MemDC;
    CBitmap MemBitmap;
    MemDC.CreateCompatibleDC(NULL);
    int nWidth,nHeight;
    nWidth=nHeight=radius*2;
    MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);
    CBitmap* pOldBitmap=MemDC.SelectObject(&MemBitmap);
    MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(rand()%255,rand()%255,rand()%255));
    CBrush* pBlackBrush;
    CBrush* pWhiteBrush;
    CBrush BlackBrush;
    CBrush WhiteBrush;
    BlackBrush.CreateSolidBrush(RGB(0,0,0));
    WhiteBrush.CreateSolidBrush(RGB(255,255,255));

    pBlackBrush=&BlackBrush;
    pWhiteBrush=&WhiteBrush;
    //暂时保存clientrect
    CRect rr=clientrect;
    clientrect.right=nWidth;
    clientrect.bottom=nHeight;
    //pBlackBrush=new CBrush(RGB(0,0,0));
    //pWhiteBrush=new CBrush(RGB(255,255,255));
    // CBrush* pOldBrush=MemDC.SelectObject(pBlackBrush);
    // dc.FillRect(&clientrect,pBlackBrush);
    MemDC.SelectObject(pWhiteBrush);
    CPoint pt;
    pt.x=clientrect.CenterPoint().x;
    pt.y=clientrect.CenterPoint().y;
    int startangle,endangle;
    //画黑大半圆
    startangle=(angle)%360;
    endangle=(angle+180)%360;
    MemDC.SelectObject(pBlackBrush);
    PaintPie(&MemDC,pt,radius,startangle,endangle);

    //画白大半圆
    startangle=(angle+180)%360;
    endangle=(angle)%360;
    MemDC.SelectObject(pWhiteBrush);
    PaintPie(&MemDC,pt,radius,startangle,endangle); //画小白半圆
    startangle=angle;
    endangle=(angle+180)%360;
    pt.x=clientrect.CenterPoint().x-radius*cos(angle*PI/180.0)/2.0;
    pt.y=clientrect.CenterPoint().y+radius*sin(angle*PI/180.0)/2.0;
         MemDC.SelectObject(pWhiteBrush);
    PaintPie(&MemDC,pt,radius/2,startangle,endangle);

    //画小黑半圆
    startangle=(angle+180)%360;
    endangle=angle;
         pt.x=clientrect.CenterPoint().x+radius*cos(endangle*PI/180.0)/2.0;
    pt.y=clientrect.CenterPoint().y-radius*sin(endangle*PI/180.0)/2.0;
    MemDC.SelectObject(pBlackBrush);
    PaintPie(&MemDC,pt,radius/2,startangle,endangle);

    //画小白圆圈 MemDC.SelectObject(pWhiteBrush);
    PaintPie(&MemDC,pt,radius/10,0,360);

    //画小黑圆圈
    pt.x=clientrect.CenterPoint().x-radius*cos(angle*PI/180.0)/2.0;
    pt.y=clientrect.CenterPoint().y+radius*sin(angle*PI/180.0)/2.0;
    MemDC.SelectObject(pBlackBrush);
    PaintPie(&MemDC,pt,radius/10,0,360);

    clientrect=rr;//恢复clientrect
    pDC->BitBlt(clientrect.CenterPoint().x-adius,clientrect.CenterPoint\
    ().y-radius,clientrect.CenterPoint().x+radius,clientrect.CenterPoint
    ().y+radius,&MemDC,0,0,SRCCOPY);


    MemBitmap.DeleteObject();
    MemDC.DeleteDC();

    CDialog::OnPaint();
    }在OnTimer()中改变angle,然后Invalidate(false),频繁调用onpaint()后,
    好像出现了内存泄漏,图像变换越来越慢,硬盘狂响,其它程序也慢了。
    但是最后MemBitmap和MemDC已经删除了,还有什么地方没有考虑到呢?各位老大,这厢有礼了!
    //fxniao
      

  29.   

    ///////////////  闪烁具体原因及*简便*解决方法大全/////////////////////
    闪烁原因是因为每次调用Invalidate会发出一个WM_ERASEBKGND,而缺省的WM_ERASEBKGND消息处理函数会把背景重画一遍,也就是你每刷新一次画面,就会把画面画上两次,第一次是自动画背景,第二次才是你自己的,在背景反差大,或刷新频繁的时候,就会有不可避免的闪烁。解决的方法很多,也很简单,主要有两类:
    1、自己控制刷新全过程,不要调用Invalidate,既然上面的大虾已经写好了,我就粘一下了,不要见怪 ;)
    回复人: dongfa(阿东) (  ) 信誉:100  2002-3-5  9:22:39  得分:0  
     
     
      不要用Invalidate的方法,可以写一个函数假如;
      CDC  m_memDC;//.h中声明一个内存DC
      Draw()
      {
      CClientDC  dc(this);
      dc.BitBlt(0,  0,  0,  0,  &  m_memDC,  0,  0,  SRCCOPY);
      }
      MakeMemBmp()
      {
      //根据参数把图片画到m_memDC中
      ...
      }
      
      然后在Timer中调用MakeMemBmp()和Draw()就可以了.
       
    Top 
     
     回复人: dongfa(阿东) (  ) 信誉:100  2002-3-5  9:24:47  得分:0  
     
     
      还有就是在OnDraw(CDC  *pDC):
      pDC->  BitBlt(0,    0,    0,    0,    &      m_memDC,    0,    0,    SRCCOPY);
      这样就保证了,当其他窗口覆盖本窗口时可以自动刷新.
    2、仍然调用Invalidate,但接管WM_ERASEBKGND处理函数,然后啥也不干。再粘一下了 :P 回复人: begin(编程新手) (  ) 信誉:100  2002-3-5  12:59:33  得分:0  
     
     
      试试响应WM_ERASEBKGND消息,直接返回TRUE。 
    Note: 你也可用DDraw的,不过要注意同样的问题,但我觉得如果你的画面面积不大的话,用DDraw并没有什么特别的优势,麻烦……祝你好运!///////////////  具体原因及*简便*解决方法大全/////////////////////
      

  30.   

    用Invalidate(FALSE)就可以了,如果你用Invalidate(TRUE),那是铁定要闪烁的,因为它会把你的背景刷新一遍
      

  31.   

    完全赞同dolphi(李江)的 思路,双缓冲表现出来是每次用新的图象直接覆盖原图象,而不是不停的先清背景后画图,那样的话,就是每秒1万次,也一样闪,因为你看到的是单色背景跟你要的图片在做不停的交替显示,如果用我前面说的方式,每秒2幅,那怕10秒一次更新也不可能闪,看看flash就知道了,它很多时候就是一秒才几幅的更新。当然,硬件的双缓冲更简单,用ddraw就可以完成。
      

  32.   

    你试试
    CRect rc(0,0,1,1);
    InvalidateRect(&rc);
    应该可以了!如果可以,不妨寄个E_mail给我,[email protected]
      

  33.   

    综合上面几种方法:
    1双缓存
    2可以在EraseBkgnd()里画,或是直接返回TRUE.
      

  34.   

    OK!经过大家的谈论,我明白我错误的根本原因是:Invalidate(TRUE)了。因此,虽然,我也采用了双缓冲,但是由于背景也被重刷,与我所要贴的图相差太多,所以,出现闪烁!!!多谢各位的捧场。分数有效,就给几个一针见血指出要害的兄弟吧。