我这样用双缓冲,怎么还是感觉闪烁啊?

秀小川 2012-07-28 05:30:56
void CDoubleDrawView::OnDraw(CDC* pDC)
{
CDoubleDrawDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CRect rect;
GetClientRect(&rect);
CDC dc;
CBitmap bmp;
dc.CreateCompatibleDC(pDC);
bmp.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());

CBitmap * pOldBmp = dc.SelectObject(&bmp);
srand((unsigned int) time(NULL));
dc.FillSolidRect(0,0,rect.Width(),rect.Height(),RGB(255,255,255));
dc.LineTo(rand(),rand());

pDC->BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),&dc,0,0,SRCCOPY);
pDC->SelectObject(pOldBmp);
// TODO: add draw code for native data here
}

这样用有什么错误吗?
我现在想用GDI+绘图,该怎么用双缓冲?
...全文
307 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
秀小川 2012-07-31
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 的回复:]

双缓冲不是省cpu的。
[/Quote]
好吧,为了方便只能牺牲CPU了!
用户 昵称 2012-07-31
  • 打赏
  • 举报
回复
双缓冲不是省cpu的。
skyandcode 2012-07-30
  • 打赏
  • 举报
回复
楼主不如把代码放到ONEAREASEBKGND()中试试,貌似可以。
youngwolf 2012-07-30
  • 打赏
  • 举报
回复
楼主这肯定是双缓冲,前面某些人回答得明显有问题。

闪烁可能是刷新了背景的原因(就是你试了可以那种方法)。

另外,楼主这代码简直想要耗死CPU了。双缓冲是最基本的技能,在双缓冲之后,我们还要注重代码的CPU使用量。

可以看我的博客,好几年前的文章,关于gdi的。
秀小川 2012-07-30
  • 打赏
  • 举报
回复
PS: 我上面的程序用了 SetTimer(0,200,NULL); 每200MS刷新一下! 主要是为了做出流动的直线效果!
秀小川 2012-07-30
  • 打赏
  • 举报
回复


void CGDITestDlg::myDraw()
{
CWnd *pWnd = GetDlgItem(IDC_FRAME);
CDC *pDC = GetDC();
CRect rect;
pWnd->GetClientRect(&rect);

CDC dc;//创建用于作图的内存DC
CBitmap bmp;//内存中承载临时图像的位图
CBitmap *pOldBmp = NULL;
dc.CreateCompatibleDC(pDC);//创建兼容内存DC
bmp.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());//创建兼容的位图
pOldBmp = dc.SelectObject(&bmp);
Graphics myGraphics(dc.m_hDC);
Pen * myPen ;
myPen = new Pen(Color(255, 255, 0, 0), 5);
myPen->SetDashStyle(DashStyleDash);
int x(20),y(0);
// myGraphics.TranslateTransform(0,0);
switch(flag)
{
case 1:
myGraphics.DrawLine(myPen,0,10,500,10);
break;
case 2:
myGraphics.DrawLine(myPen,5,10,500,10);
myGraphics.DrawLine(myPen,2,10,0,10);//补充留白
break;
case 3:
myGraphics.DrawLine(myPen,10,10,500,10);
myGraphics.DrawLine(myPen,6,10,0,10);
break;
case 4:
myGraphics.DrawLine(myPen,14,10,500,10);
myGraphics.DrawLine(myPen,10,10,0,10);
break;
default:
break;
}
delete(myPen);
pDC->BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),&dc,0,0,SRCCOPY);//缓冲区的图像拷到前台
dc.SelectObject(pOldBmp);
dc.DeleteDC();
bmp.DeleteObject();
pWnd->ReleaseDC(pDC)



还有一个问题,我感觉用双缓冲的时候,CPU占有率高达24%,这是个什么情况? 是要做什么优化吗?
赵4老师 2012-07-30
  • 打赏
  • 举报
回复
提醒:使用任何技术,也避免不了一帧全屏黑和下一帧全屏白交替显示时闪烁!(^_^)
傻X 2012-07-30
  • 打赏
  • 举报
回复
你这几行代码,有人跟你提双缓冲,感觉概念没吃透啊。主要是WM_ERASEBKGND 直接返回TRUE

秀小川 2012-07-30
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 的回复:]

楼主这肯定是双缓冲,前面某些人回答得明显有问题。

闪烁可能是刷新了背景的原因(就是你试了可以那种方法)。

另外,楼主这代码简直想要耗死CPU了。双缓冲是最基本的技能,在双缓冲之后,我们还要注重代码的CPU使用量。

可以看我的博客,好几年前的文章,关于gdi的。
[/Quote]
CPU消耗我的确没考虑到,谢谢提醒!这个是要考虑的!
zgl7903 2012-07-29
  • 打赏
  • 举报
回复
WM_ERASEBKGND 直接返回TRUE
schlafenhamster 2012-07-29
  • 打赏
  • 举报
回复
类有一个style叫CS_OWNDC。
这种类具有固定的DC
用户 昵称 2012-07-29
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]
其实DC也是用句柄来标识的,所以也具有句柄的不确定性,就是只能随用随取,不同时间两次取得的是不同的(使用过文件句柄地话,应该很容易理解的)。那么我们用全局变量保存的DC就没什么意义了,下次使用只是什么也画不出来。(这一点的理解可以这样: DC需要占用一定的内存,那么在频繁的页面调度中,位置难免改变,于是用来标志指针的句柄也就不同了)。
[/Quote]
OnDraw,OnPaint函数外面传进来的dc,当然是每次都是变化的,至于一个内存dc,没听说过什么不确定性。
秀小川 2012-07-29
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]

WM_ERASEBKGND 直接返回TRUE
[/Quote]
这个我试了可以!
秀小川 2012-07-29
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

为了这一句
dc.LineTo(rand(),rand());
你把背景都擦除了。
图像变化大,就会有闪烁的感觉,用双缓冲也不行的。
应该用NOTXOR画线
[/Quote]
我注释掉dc.FillSolidRect(0,0,rect.Width(),rect.Height(),RGB(255,255,255))之后,闪烁的更厉害了!
秀小川 2012-07-28
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]
你画的每次都变,又每次都重新创建dc,双缓冲是没什么用的

双缓冲有几个习惯的做法
1)全局的dc,直到不用了再销毁,而不是随用随创建,用完删除,删完了再建。
2)界面所显示的,都在内存dc中保存着,ondraw时只是bitblt一下
3)界面所显示的有变化,先在内存dc中画好,然后bitblt到界面中。
[/Quote]
我在别人的博客里面看到这么一段话,怎么理解?

其实DC也是用句柄来标识的,所以也具有句柄的不确定性,就是只能随用随取,不同时间两次取得的是不同的(使用过文件句柄地话,应该很容易理解的)。那么我们用全局变量保存的DC就没什么意义了,下次使用只是什么也画不出来。(这一点的理解可以这样: DC需要占用一定的内存,那么在频繁的页面调度中,位置难免改变,于是用来标志指针的句柄也就不同了)。
秀小川 2012-07-28
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]
你画的每次都变,又每次都重新创建dc,双缓冲是没什么用的

双缓冲有几个习惯的做法
1)全局的dc,直到不用了再销毁,而不是随用随创建,用完删除,删完了再建。
2)界面所显示的,都在内存dc中保存着,ondraw时只是bitblt一下
3)界面所显示的有变化,先在内存dc中画好,然后bitblt到界面中。
[/Quote]
谢谢,学习了! 我再去试试!
用户 昵称 2012-07-28
  • 打赏
  • 举报
回复
你画的每次都变,又每次都重新创建dc,双缓冲是没什么用的

双缓冲有几个习惯的做法
1)全局的dc,直到不用了再销毁,而不是随用随创建,用完删除,删完了再建。
2)界面所显示的,都在内存dc中保存着,ondraw时只是bitblt一下
3)界面所显示的有变化,先在内存dc中画好,然后bitblt到界面中。
秀小川 2012-07-28
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
为了这一句
dc.LineTo(rand(),rand());
你把背景都擦除了。
图像变化大,就会有闪烁的感觉,用双缓冲也不行的。
应该用NOTXOR画线
[/Quote]
哦,这样啊!
如果我用GDI+ 双缓冲怎么画图啊?
anddygon 2012-07-28
  • 打赏
  • 举报
回复
SetRop2(NOTXORPEN)
schlafenhamster 2012-07-28
  • 打赏
  • 举报
回复
为了这一句
dc.LineTo(rand(),rand());
你把背景都擦除了。
图像变化大,就会有闪烁的感觉,用双缓冲也不行的。
应该用NOTXOR画线
日历控件类名:CalendarMonthControl 开发平台:Visual Studio 2008 字符集:使用 Unicode 字符集 此项目的源码涉及到了以下方面的知识和技术: 1. Windows窗体坐标(逻辑坐标,客户区坐标概念)。 2. 图像自绘(不是MFC来绘制而是自已来管理一切)。 3. 双缓冲技术运用(有时侯自绘的控件可能会有“闪烁感”,在这里你可以找到解决方法)。 4. STL运用(软件开发第一准则:“不要重复造轮子”)。 5. DirectUI思想(思想决定一切)。 6. C++设计模式(清晰的构架对一个项目来说是至关重要的,而无论这个项目大小) 项目介绍: 虽然就技术上来讲重新设计和开发一个类似于Windows时间控件的技术并不难,但是如果能够在能够很好很方便的运行的基础上再考虑到美观,易用,可扩展性,构架清晰等方面那也不算太容易。从某种意义上来说这个项目算得上是STL的一个小作品,因为此项目所使用的数据结构和算法全部是由STL所提供的,由于大量使用STL来进行数据处理,以及在图像绘制方面使用了流行的双缓冲技术所以整个系统能够得到极高的性能,当然即便如此此项目仍然还有许多可以优化的空间,它的性能还没有被发挥到最优,例如显示月份的单元格是由vector动态的push_back,但是如果你认真分析后会发现实际上这些单元格是固定的,也就是说在构造函数中就可以new一个固定大小的内存空间来供vector使用,而不用每次都动态的push_back。我在整个项目的设计上花了一些时间来保证代码的层次结构清晰,同时也使用了一些C++里面的高级技术,例如多重继承,重载,虚函数,虽然不多,但是尽量保证了恰到好处。 作为一个程序开发的新手,或许能够从这个项目中得到一些思路。实际上这个项目被重写过一次,第一次的设计完全是面向过程的,谈不上设计,因为整个项目就是一个类,或许这段代码在以前可能称得上算是一个“牛X”的作品,但是在设计模式大行其道的今天最多算得上是污染开发人员视觉的产物,优其可读性和扩展性均不能达到要求,这一版本是完全基于面向对象的思想来进行设计的,所以比上一个版本更容易阅读也更具层次感觉。 此项目源代码虽然不多,但是在许多地方使用到的一些技巧仍然值得新手学习,例如在与用户交互事件设计及处理方面(OnClick,OnMove)就使用了DirectUI的思想,控件中将月份和年份的区域当作一个逻辑区域来对待,将每一天或每一月看作为一块小的逻辑区域(用RECT标识),最终将这些区域的逻辑图形绘制到一个DC上,同时使用统一的数据管理对象来管理这些区域的事件及处理(极到位的运用了C++类设计原则的部分思想),这样一方面保证了绘制效率,另一方面增强了控件的可扩展性和可管理。这也正是DirectUI的核心思想。 最后非常感谢你花时间来阅读这些文字,同时希望你认为花费这些时间是值得的。

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧