如果一位图画在背景上,以50次/秒的速度刷新,有没有可能不闪烁??? 如果要求那么快的速度的话,还是用DirectDraw吧,你用BitBlt再怎么也不行,你不可能把你要显示的全存在内存中呀。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 directdraw我刚学,很难,但很强大,真的! 用DDraw!绝对没问题!SetTimer的interval单位是毫秒吧,我设成1那surface愣是没闪一下。用一个offscreen Surface来bit就行了,一样可用DC的GDI函数。 Use "false" for the third parameter in InvaildateRect()... not "true"Example : InvalidateRect(hwnd, &rect, false); To minkerui: 由我上面的描述中,就是按双缓存的。即,对画的操作是对内存位图进行的操作,直到画完后,才一次性的BitBlt给OnDraw中的pDC。 35就不闪了REALPLAY一般到这个数就没事了 You can try to use GDIPlus.Easy and Simple. 什么是GDIPlue,能说明一下嘛? GDIPlus是什么呀?能说明一下吗? 你可以试着用将背景划分成N个区域,每隔一段时间InvalidateRegion()一个不同的区域,通过这样的方法来画完整个背景,我想应该不会闪烁 哈哈,你是要做程序的splash吧!不用timer,只要在中途处理消息就行了。 To huapu: 我用过中途处理消息,但是依然被阻塞:(To Ah: 我测过相同图形,一样要闪烁的。再说,我需要的是图形的渐变,自然不是相同的图形,只是每次图形的变化不大就是。 好像OnTimer最快每秒钟只能触发18.2次。 为什么要刷新整个位图?只是刷新你需要显示的部分就可以了,InvalidateRect()即可 不要用Invalidate的方法,可以写一个函数假如;CDC m_memDC;//.h中声明一个内存DCDraw(){CClientDC dc(this);dc.BitBlt(0, 0, 0, 0, &m_memDC, 0, 0, SRCCOPY);}MakeMemBmp(){//根据参数把图片画到m_memDC中...}然后在Timer中调用MakeMemBmp()和Draw()就可以了. 还有就是在OnDraw(CDC *pDC):pDC->BitBlt(0, 0, 0, 0, & m_memDC, 0, 0, SRCCOPY);这样就保证了,当其他窗口覆盖本窗口时可以自动刷新. 为什么不给bluekite(bluekite)分呢?InvalidateRect(hwnd, & rect, false); 这样就不要用Timer了,还是分立一个线程。双缓冲就可以保证不闪烁。BitBlt速度不够快,如果不想用DDraw,可以用vfw的相关函数,性能肯定够,还支持Dither 试试响应WM_ERASEBKGND消息,直接返回TRUE。 不用invalidate();直接在timer中画。 我也是用的GDI用了双缓冲,一秒最多10帧也不会闪啊 次数不限,用Invalidate(FALSE);刷新. 就算一秒钟从1到100幅都是不会闪的。你的问题是你用了Invalidate()!!!!你直接BitBlt();绝对不可能闪。如果用DDraw,你不断的清空背景才画图,一样闪到你晕。我的意思是你不要在定时器中触发Invalidate();你要直接BitBlt。 应该是CPU刷新不过来吧!你应该做更多的细节工作! 用OnTimer,你设置是50MS但实际有很多次是接格几百MS运行一次 你可以使用缓冲机制,这样不会闪烁,只是性能太查,cpu站用过大。 如果是我做的(BCB),我会设计两个图像控件, 1、将第一个的显示特性设为禁止, 2、将要显示的图形复制到禁止显示的图像控件上 3、将第一个图像控件的显示特性设为允许,第二个设为禁; 4、转到第二步如此重复,我曾做过25帧,但没有做过50帧。 帧数和闪烁无关,关键问题是如果一个图片画到屏幕前,先清空屏幕的话(也就是把窗口覆盖上颜色),就会闪烁,就是说不能让窗口自己画,也就是不能调用Invalidate(),直接把内存位图BitBlt到DC就可以了 很巧,我也在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;//恢复clientrectpDC->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 /////////////// 闪烁具体原因及*简便*解决方法大全/////////////////////闪烁原因是因为每次调用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并没有什么特别的优势,麻烦……祝你好运!/////////////// 具体原因及*简便*解决方法大全///////////////////// 用Invalidate(FALSE)就可以了,如果你用Invalidate(TRUE),那是铁定要闪烁的,因为它会把你的背景刷新一遍 完全赞同dolphi(李江)的 思路,双缓冲表现出来是每次用新的图象直接覆盖原图象,而不是不停的先清背景后画图,那样的话,就是每秒1万次,也一样闪,因为你看到的是单色背景跟你要的图片在做不停的交替显示,如果用我前面说的方式,每秒2幅,那怕10秒一次更新也不可能闪,看看flash就知道了,它很多时候就是一秒才几幅的更新。当然,硬件的双缓冲更简单,用ddraw就可以完成。 你试试CRect rc(0,0,1,1);InvalidateRect(&rc);应该可以了!如果可以,不妨寄个E_mail给我,[email protected] 综合上面几种方法:1双缓存2可以在EraseBkgnd()里画,或是直接返回TRUE. OK!经过大家的谈论,我明白我错误的根本原因是:Invalidate(TRUE)了。因此,虽然,我也采用了双缓冲,但是由于背景也被重刷,与我所要贴的图相差太多,所以,出现闪烁!!!多谢各位的捧场。分数有效,就给几个一针见血指出要害的兄弟吧。 VS2008操作excel遇到的问题 想学习VC控件制作,请推荐教材,或者哪里有好的网络教程。 大家帮帮忙吧 vector的使用问题 提个HOOK问题,关于SetWindowsHookEx失败的原因! 如何打开文件? 做过截取窗体内容的朋友进来看看这个问题~~~~ 网络入侵监测的源代码 控制台程序的int main(argc,argv[])中,argc的值为1,这是在哪儿给定的,argv[]又怎样赋值? 如何得到本机网卡地址 ? 在C语言中,语句while (scanf("%c",&c)==1);怎样才能使它不等于1? 怎样读取硬盘上指定位置的位图文件?(VC)
Example :
InvalidateRect(hwnd, &rect, false);
Easy and Simple.
不用timer,只要在中途处理消息就行了。
To Ah: 我测过相同图形,一样要闪烁的。再说,我需要的是图形的渐变,自然不是相同的图形,只是每次图形的变化不大就是。
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()就可以了.
pDC->BitBlt(0, 0, 0, 0, & m_memDC, 0, 0, SRCCOPY);
这样就保证了,当其他窗口覆盖本窗口时可以自动刷新.
InvalidateRect(hwnd, & rect, false);
双缓冲就可以保证不闪烁。
BitBlt速度不够快,
如果不想用DDraw,可以用vfw的相关函数,性能肯定够,还支持Dither
Invalidate(FALSE);
刷新.
你直接BitBlt();绝对不可能闪。如果用DDraw,你不断的清空背景才画图,一样闪到你晕。我的意思是你不要在定时器中触发Invalidate();你要直接BitBlt。
你应该做更多的细节工作!
1、将第一个的显示特性设为禁止,
2、将要显示的图形复制到禁止显示的图像控件上
3、将第一个图像控件的显示特性设为允许,第二个设为禁;
4、转到第二步如此重复,我曾做过25帧,但没有做过50帧。
我觉得你可以参考这篇文章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
闪烁原因是因为每次调用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并没有什么特别的优势,麻烦……祝你好运!/////////////// 具体原因及*简便*解决方法大全/////////////////////
CRect rc(0,0,1,1);
InvalidateRect(&rc);
应该可以了!如果可以,不妨寄个E_mail给我,[email protected]
1双缓存
2可以在EraseBkgnd()里画,或是直接返回TRUE.