OnDraw中绘图的闪烁问题,高分~!

hhoking 2002-05-07 10:59:43
在OnDraw中显示一幅图像,当拉动窗口的大小时,图像有很严重的闪烁感,请问怎么解决?我是open一个bmp文件,得到dib句柄,然后调用StretchDIBits函数。也可以得到Gdi句柄,调用StretchBlt函数,结果都一样有很严重的闪烁,哪位大哥有解决办法?
...全文
339 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
hhoking 2002-05-07
  • 打赏
  • 举报
回复
请上面各位朋友到
http://www.csdn.net/expert/topic/701/701397.xml?temp=.7425959
up一下,顺便领分!
hhoking 2002-05-07
  • 打赏
  • 举报
回复
多谢各位的回答。其实问题就是在OnDraw中画图(不管是用简单的曲线函数,还是位图显示函数)好像不能避免闪烁。当然,一般情况是不明显,当你设置系统的显示效果为:“拖动时显示窗口内容”时,就会发现,你用鼠标改变窗口大小,窗口内的内容闪烁的厉害。
edrftgyh 2002-05-07
  • 打赏
  • 举报
回复
你可以用InvalidateRect()函数进行局部刷新试试!
halcyon 2002-05-07
  • 打赏
  • 举报
回复
同意楼上的,觉得应该重载ONPAINT,通过双缓冲解决试试看,我没试过,不知道效果怎么样。不过,C#里的GDI+函数默认就使用了双缓冲的机制,怎么样,有没有意思转到C#上去,毕竟VC在做界面上不是专长,很痛苦的,连改变按钮的背景色的很麻烦,VB/DELPHI多简单,我真的不想在这方面越陷越深了。
axin_online 2002-05-07
  • 打赏
  • 举报
回复
你的问题出在 CBitmap 类实例用作局部变量,闪烁是
因为位图加载需要时间。你应该在类中声明一个CBitmap
darkbb 2002-05-07
  • 打赏
  • 举报
回复
haozhu yi
admireO 2002-05-07
  • 打赏
  • 举报
回复
强烈推荐使用fz_zhou(vcfan) 的方法
crazy_lazy_pig 2002-05-07
  • 打赏
  • 举报
回复
你的OnSize是自己重载吧,不要在里面用Invalidate();
在其他地方也不要频繁使用Invalidate();
能不重画的地方请使用Invalidate(FALSE);
需重画的东西不多时请使用CClientDC对象,自己一点点画。
OnDraw 2002-05-07
  • 打赏
  • 举报
回复
同意楼上的
我不是大明 2002-05-07
  • 打赏
  • 举报
回复
用又CMemDC,可以让图形不闪!

在知道图形显示闪烁的原因之后,对症下药就好办了。首先当然是去掉MFC
提供的背景绘制过程了。实现的方法很多,
* 可以在窗口形成时给窗口的注册类的背景刷付NULL
* 也可以在形成以后修改背景
static CBrush brush(RGB(255,0,0));
SetClassLong(this->m_hWnd,GCL_HBRBACKGROUND,(LONG)(HBRUSH)brush);
* 要简单也可以重载OnEraseBkgnd(CDC* pDC)直接返回TRUE
这样背景没有了,结果图形显示的确不闪了,但是显示也象前面所说的一样,
变得一团乱。怎么办?这就要用到双缓存的方法了。双缓冲就是除了在屏幕上有
图形进行显示以外,在内存中也有图形在绘制。我们可以把要显示的图形先在内存中
绘制好,然后再一次性的将内存中的图形按照一个点一个点地覆盖到屏幕上去(这个
过程非常快,因为是非常规整的内存拷贝)。这样在内存中绘图时,随便用什么反差
大的背景色进行清除都不会闪,因为看不见。当贴到屏幕上时,因为内存中最终的图形
与屏幕显示图形差别很小(如果没有运动,当然就没有差别),这样看起来就不会闪。


3、如何实现双缓冲
首先给出实现的程序,然后再解释,同样是在OnDraw(CDC *pDC)中:

CDC MemDC; //首先定义一个显示设备对象
CBitmap MemBitmap;//定义一个位图对象

//随后建立与屏幕显示兼容的内存显示设备
MemDC.CreateCompatibleDC(NULL);
//这时还不能绘图,因为没有地方画 ^_^
//下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小
MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);

//将位图选入到内存显示设备中
//只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上
CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);

//先用背景色将位图清除干净,这里我用的是白色作为背景
//你也可以用自己应该用的颜色
MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));

//绘图
MemDC.MoveTo(……);
MemDC.LineTo(……);

//将内存中的图拷贝到屏幕上进行显示
pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);

//绘图完成后的清理
MemBitmap.DeleteObject();
MemDC.DeleteDC();
akademecia 2002-05-07
  • 打赏
  • 举报
回复
首先,应该尽量少在ondraw()里写大段的代码,以加速显示速度。
其次,如上面所说,通过PAINTSTRUCT得到需要重绘区域的Rect,然后在OnDraw里重绘需要的区域
checkitout 2002-05-07
  • 打赏
  • 举报
回复
“直接”写缓冲就可以解决!
先得到显示区的指针,然后用StretchBlt也好,
MEMCOPY也好,就搞定了!
你可以参考,微软给的例程,里面有标准做法。

但我觉得,照你说的做法,应该不会闪得很“严重”!
是不是刷新的涵树调用有问题?
zhanglynx 2002-05-07
  • 打赏
  • 举报
回复
我用的方法是重载WM_PAINT函数,通过PAINTSTRUCT得到需要重绘区域的Rect,然后在OnDraw里重绘需要的区域!也可不用OnDraw重写自己的绘图函数!
hhoking 2002-05-07
  • 打赏
  • 举报
回复
具体怎么做呢?那两个API函数怎么知道只重绘一部分?
tokens 2002-05-07
  • 打赏
  • 举报
回复
已经显示的图,不要再刷新了。。
只把需要刷新的图刷一下就可以了。。。
hhoking 2002-05-07
  • 打赏
  • 举报
回复
to asett1(asett1)
gdi+能否说的详细点?比如怎么在VC++中用?
asett1 2002-05-07
  • 打赏
  • 举报
回复
补充一句:gdi+不是c#的专利,vc++里也可以一样使用,并且相当方便
gdi+充分体现了面向对象的特点,用过就知道了

16,548

社区成员

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

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

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