六 12
邱金武wtl && atl && win, 其他, 转载
【http://hi.baidu.com/techicey/blog/item/16a55ffcec749cf6fd037f19.html】
首先说一下产生闪烁的原因,当窗口由于任何原因需要重绘时,总是先用背景色或背景图象将显示区清除,然后才显示图象,这样在短时间内背景色与显示图形交替出现,使得显示窗口看起来在闪。如果将背景刷设置成NULL,这样无论怎样重绘图形都不会闪了,但是会使得窗口的显示乱成一团,因为重绘时没有背景色对原来绘制的图形进行清除,而又叠加上了新的图形。
一般的解决方法就是采用双缓冲,创建一幅内存图象,把背景和图片先绘制到该图象,然后把绘制好的该图象显示到窗口,这样就不会产生闪烁,其实就是隐藏了图象的显示过程,原来是在前台,给你看到先在画布上刷上背景,再画上图象,现在是在后台画好了再拿出来给你看。
看起来好象解决方法是需要一次性绘制好图象,其实关键是不能让任何背景及图片在绘制时产生重叠,跟是否一次性绘制没多大关系。电脑的绘制速度还是很快的,不信可以试试把背景刷设置成NULL,这样不会闪烁,然后循环调用BitBlt把一幅小图片铺满整个窗口,虽然是多次绘制,一样不会闪烁,但是如果改变一下循环步长,让图片产生重叠,就会开始闪烁了。
知道了闪烁的原因,不用双缓冲的解决办法就不难找到了,调用ExcludeClipRect,可以排除掉绘制区域,先绘制图片,ExcludeClipRect掉图片的区域,再绘制背景,相当于把一幅挖了一个洞的画布贴到窗口,这样不产生绘制重叠部分,就不会产生闪烁了。
API代码,始终在窗口右下角显示一幅300*200的图片,窗口背景为黑色:
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rc;
HDC hMemDC;
GetClientRect(hWnd,&rc);
BeginPaint(hWnd,&ps);
hMemDC = CreateCompatibleDC(ps.hdc);
SelectObject(hMemDC,hbmp);
BitBlt(ps.hdc,rc.right-300,rc.bottom-200,300,200,hMemDC,0,0,SRCCOPY);
ExcludeClipRect(ps.hdc,rc.right-300,rc.bottom-200,rc.right,rc.bottom);
FillRect(ps.hdc,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH));
DeleteDC(hMemDC);
EndPaint(m_hWnd,&ps);
return 0;
}
有时候因为刷新区域的问题,可能调整窗口但是WM_PAINT的代码不起作用,这时需要响应WM_SIZE消息,通知画面更新一下:
case WM_SIZE:
InvalidateRect(hWnd,NULL,FALSE);
break;
对于显示多幅图象,这个方法也是适用的,只要每绘制完一幅图象,ExcludeClipRect掉该图象区域就可以,但是注意如果图象有重叠,绘制顺序是反过来的,即盖在最上面的图象需要最先绘制,最后给整个窗口刷上背景就OK了。
六 11
邱金武wtl && atl && win, 其他, 转载
最近在学习《WTL for MFC Programmer》系列文章的一些小结和感受
相同点:
1.都是通知消息,都可以被反射回控件类自行处理。
2.都和自定义控件的绘画有关。
区别:
MSDN对WM_DRAWITEM描述:
The WM_DRAWITEM message is sent to the parent window of an owner-drawn button, combo box, list box, or menu when a visual aspect of the button, combo box, list box, or menu has changed.
MSDN对NM_CUSTOMDRAW的描述:
Sent by some common controls to notify their parent windows about drawing operations. This notification is sent in the form of a WM_NOTIFY message.
1.可以看出,前者是对Owner-Draw风格的按钮,复选框,列表框和菜单有效的,树形控件并没在此列。所以在系列文章的第五篇中,自定义按钮是继承了COwnerDraw,树形控件是继承了CCustomDraw,MSDN中也列出了一些NM_CUSTOMDRAW有关的控件:
List view
NMLVCUSTOMDRAW
ToolTip
NMTTCUSTOMDRAW
Tree view
NMTVCUSTOMDRAW
Toolbar
NMTBCUSTOMDRAW
All other supported controls
NMCUSTOMDRAW
2.前者若想进行一些gdi动作,那基本上就是整个区域需要绘画,gdi的一些操作比较多,后者使用更简单,一些属性(比如字体颜色)只需要设置一些变量即可。
3.前者是一个独立的消息,后者是被包含在WM_NOTIFY消息中被发送的。
4.NM_CUSTOMDRAW分好多个阶段,可以通过重载某些方法来改变行为,这些方法包括OnPrePaint, OnItemPrePaint等等(细节只能看wtl源代码了,MSDN中也稍有介绍)。
猜测:他们应用在不同的控件上,但是NM_CUSTOMDRAW貌似是WM_DRAWITEM的加强版,呵呵
欢迎大家多多批评指教~
以下是在MSDN上找到的一些解释,链接是相关的一篇文章地址
所有者绘制
控制控件绘制的另一种方法是利用所有者绘制。事实上,您也许听开发人员提到过所有者 绘制控件,因为它是用于开发自定义控件最普通的技术。该技术普遍使用的主要原因在于,Windows 可为您提供很多帮助。在呈现控件的那一刻,Windows 就已经创建并填写了设备上下文,决定了控件的大小和位置,并且向您传递信息以使您了解此刻绘制的需求。对于列表控件(例如,列表框和列表视图), Windows 将为列表中的每一项调用绘制代码,这意味着您只需绘制这些项,而无需考虑控件的其他方面。注意,所有者绘制可用于大多数控件。然而,它不能用于编辑控件; 并且考虑到列表控件,它只能用于报表视图样式。
自定义绘制
对于绘制自己的控件而言,这可能是最少 为人所知的技术。事实上,许多技术能力较高的开发人员也混淆了术语所有者绘制 (owner-draw) 和自定义绘制 (custom-draw)。关于自定义控件,首先需要了解,它仅针对于指定的公共控件:标头、列表视图、rebar、工具栏、工具提示、跟踪条和树视 图。此外,尽管所有者绘制只允许绘制报告视图风格的列表视图控件,而自定义绘制则使您能够处理列表视图控件所有视图风格的绘制。使用自定义绘制的另一个明 显优势是,您可以对希望绘制的内容进行严格挑选。实现方式是,在控件绘制的每个阶段由 Windows 向代码发送一个消息。这样,您可以决定在每个阶段是自己进行所有的绘制工作,增加默认的绘制,还是允许 Windows 为该阶段执行所有的绘制。(鉴于自定义绘制是本文的一个主题,因此您很快会看到它的工作方式。)
文章地址: http://msdn2.microsoft.com/zh-cn/library/ms364048(VS.80).aspx
最近在学习《WTL for MFC Programmer》系列文章的一些小结和感受相同点:1.都是通知消息,都可以被反射回控件类自行处理。2.都和自定义控件的绘画有关。
区别:MSDN对WM_DRAWITEM描述:The WM_DRAWITEM message is sent to the parent window of an owner-drawn button, combo box, list box, or menu when a visual aspect of the button, combo box, list box, or menu has changed.
MSDN对NM_CUSTOMDRAW的描述:Sent by some common controls to notify their parent windows about drawing operations. This notification is sent in the form of a WM_NOTIFY message.
1.可以看出,前者是对Owner-Draw风格的按钮,复选框,列表框和菜单有效的,树形控件并没在此列。所以在系列文章的第五篇中,自定义按钮是继承了COwnerDraw,树形控件是继承了CCustomDraw,MSDN中也列出了一些NM_CUSTOMDRAW有关的控件:List view NMLVCUSTOMDRAWToolTip NMTTCUSTOMDRAWTree view NMTVCUSTOMDRAWToolbar NMTBCUSTOMDRAWAll other supported controls NMCUSTOMDRAW2.前者若想进行一些gdi动作,那基本上就是整个区域需要绘画,gdi的一些操作比较多,后者使用更简单,一些属性(比如字体颜色)只需要设置一些变量即可。3.前者是一个独立的消息,后者是被包含在WM_NOTIFY消息中被发送的。4.NM_CUSTOMDRAW分好多个阶段,可以通过重载某些方法来改变行为,这些方法包括OnPrePaint, OnItemPrePaint等等(细节只能看wtl源代码了,MSDN中也稍有介绍)。
猜测:他们应用在不同的控件上,但是NM_CUSTOMDRAW貌似是WM_DRAWITEM的加强版,呵呵欢迎大家多多批评指教~
以下是在MSDN上找到的一些解释,链接是相关的一篇文章地址所有者绘制
控制控件绘制的另一种方法是利用所有者绘制。事实上,您也许听开发人员提到过所有者 绘制控件,因为它是用于开发自定义控件最普通的技术。该技术普遍使用的主要原因在于,Windows 可为您提供很多帮助。在呈现控件的那一刻,Windows 就已经创建并填写了设备上下文,决定了控件的大小和位置,并且向您传递信息以使您了解此刻绘制的需求。对于列表控件(例如,列表框和列表视图), Windows 将为列表中的每一项调用绘制代码,这意味着您只需绘制这些项,而无需考虑控件的其他方面。注意,所有者绘制可用于大多数控件。然而,它不能用于编辑控件; 并且考虑到列表控件,它只能用于报表视图样式。
自定义绘制
对于绘制自己的控件而言,这可能是最少 为人所知的技术。事实上,许多技术能力较高的开发人员也混淆了术语所有者绘制 (owner-draw) 和自定义绘制 (custom-draw)。关于自定义控件,首先需要了解,它仅针对于指定的公共控件:标头、列表视图、rebar、工具栏、工具提示、跟踪条和树视 图。此外,尽管所有者绘制只允许绘制报告视图风格的列表视图控件,而自定义绘制则使您能够处理列表视图控件所有视图风格的绘制。使用自定义绘制的另一个明 显优势是,您可以对希望绘制的内容进行严格挑选。实现方式是,在控件绘制的每个阶段由 Windows 向代码发送一个消息。这样,您可以决定在每个阶段是自己进行所有的绘制工作,增加默认的绘制,还是允许 Windows 为该阶段执行所有的绘制。(鉴于自定义绘制是本文的一个主题,因此您很快会看到它的工作方式。)
文章地址: http://msdn2.microsoft.com/zh-cn/library/ms364048(VS.80).aspx
最近评论