如果要求那么快的速度的话,还是用DirectDraw吧,你用BitBlt再怎么也不行,你不可能把你要显示的全存在内存中呀。
解决方案 »
- 控制台程序,vs2008编译出来执行很慢
- 如何实现VC界面的多语言支持。
- 高分问一个关于字符串的简单问题
- 如何通过控制台命令按照 ActiveX 的cab包
- 如何取出一图片中的实体,再把这一实体贴在另一图片上或一动画上,
- 重金悬赏CScrollView中隐藏滚动条的问题
- ●无论CreateFont(...)里的参数怎么改,字体总是放不大,怎么回事?●
- 新手提问:关于使用CSocket,为什么我跟服务器建立连接后马上就断开呢
- 如何获得datagrid的当前行?
- MessageBox出错,怎么回事?
- 在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.