计机羊咩咩 发表于 2014-8-10 19:51:42

【转载】GetDC函数导致窗口闪烁的原因

这是个windows编程问题。
第一种情况显示出来的字很正常。
case WM_PAINT:
         gdc = BeginPaint (hwnd, &ps);
         TextOut (gdc, 0, 0, s, strlen (s));
         EndPaint (hwnd, &ps);
break;
第二种情况显示的字不停闪烁。
case WM_PAINT:
         gdc = GetDC (hwnd);
         TextOut (gdc, 0, 0, s, strlen (s));
         ReleaseDC (hwnd, gdc);
break;

两种函数的区别:

BeginPaint() 和EndPaint() 可以删除消息队列中的WM_PAINT消息,并使无效区域有效。

GetDC()和ReleaseDC()并不删除也不能使无效区域有效,因此当程序跳出 WM_PAINT 时 ,无效区域仍然存在。系统就回不断发送WM_PAINT消息,于是程序不断处理WM_PAINT消息。

相当于BeginPaint、EndPaint会告诉GDI内部,这个窗口需要重画的地方已经重画了,这样WM_PAINT处理完返回给系统后,系统不会再重发WM_PAINT,而GetDC没有告诉系统这个窗口需要重画的地方已经画过,在你把程序返回给系统后,系统一直以为通知你的重画命令你还没有乖乖的执行或者执行出错,所以在消息空闲时,它还会不断地发WM_PAINT催促你画,导致程序卡死。


无效区域 :

无效区域就是指需要重画的区域,无效的意思是:当前内容是旧的,过时的。

假设A是新弹出的一个对话框或被激活的现有对话框,A对话框置于原来的活动对话框B前面,造成对话框B的部分或全部被覆盖,当对话框A移开或关闭后,使对话框B原来被覆盖的地方重新可见。那部分被覆盖的地方就称为无效区域。

只有当一个窗口消息空闲时,系统才会抽空检查一下这个窗口的无效区域是否为非空(WM_PAINT的优先级是最低的。这也就是为什么系统很忙时窗口和桌面往往会出现变白、刷新不了、留拖拽痕迹等现象的原因),如果非空,系统就发送WM_PAINT。所以一定要用BeginPaint、EndPaint把无效区域设为空,否则WM_PAINT将一直被发送。


为什么WINDOWS要提出无效区域的概念?

这是为了加速。

因为BeginPaint和EndPaint用到的设备描述符只会在当前的无效区域内绘画,在有效区域内的绘画会自动被过滤,大家都知道,WIN GDI的绘画速度是比较慢的,所以能节省一个象素就节省一个,不用吝啬,这样可以有效加快绘画速度。

可见BeginPaint、EndPaint是比较“被动”的,只在窗口新建时和被摧残时才重画。

而GetDC用于主动绘制,只要你指到哪,它就打到哪。它不加判断就都画上去,无效区域跟它没关系。对话框没被覆盖没被摧残,它很健康,系统没要求它重画,但开发者有些情况下需要它主动重画:比如一个定时换外观的窗口,这时候就要在WM_TIMER处理代码用GetDC。这时候再用BeginPaint、EndPaint的话,会因为无效区域为空,所有绘画操作都将被过滤掉。


Angel丶L 发表于 2014-8-10 20:22:40

支持了 学习了 谢谢楼主了

小甲鱼 发表于 2014-8-10 20:51:39

不错,好东西应该分享~

小毛奇 发表于 2014-8-11 14:09:54

学习了,感谢{:1_1:}

黑暗漩涡 发表于 2014-8-15 13:49:02

回帖是一种美德

irvine726 发表于 2014-8-21 13:16:56

谢谢分享

irvine726 发表于 2014-8-28 09:53:57

支持楼主~

郭兴华 发表于 2014-8-31 13:37:40

强烈支持楼主ing……

OSKer 发表于 2014-10-13 18:25:46

谢谢楼主分享

OSKer 发表于 2014-10-13 18:26:21

谢谢楼主分享

l605361413 发表于 2015-3-16 21:24:41

难怪 WM_PAINT 时用GetDC()和ReleaseDC()会出现问题 卡死了!:mad:

freeparty 发表于 2015-3-16 21:40:56

学习了

tiandiweicheng1 发表于 2015-7-8 15:21:19

谢谢楼主解释原因

哥哥123 发表于 2015-7-20 21:03:24

刷点鱼币 只为下载 路过

864195847@aa.co 发表于 2015-7-25 20:42:13

我来看看
页: [1]
查看完整版本: 【转载】GetDC函数导致窗口闪烁的原因