关于无闪烁绘图的进一步讨论






4.59/5 (14投票s)
2003年5月24日
2分钟阅读

205522
一篇关于如何解决闪烁问题的文章。
引言
本文旨在展示一些解决 CTreeCtrl
、CListCtrl
和 GDI+ 中闪烁问题的实用代码。它也可以看作是对 Keith Rule 的优秀文章“MFC 中的无闪烁绘制”的扩展。
背景
阅读 Keith Rule 的优秀文章是理解本文的前提。感谢他提供的优秀代码。我们将使用他提出的 CMemDC
类。
CTreeCtrl
对于一个 CTreeCtrl
派生类,如果想避免闪烁,可以执行以下步骤。
- 将文件 memdc.h 添加到你的项目中。
- 将行
#include "memdc.h"
添加到 stdafx.h 或所需的 .h 文件中。 - 添加一个公共的
CRect
变量,例如CRect m_rectClient;
- 添加
WM_ERASEBKGND
、WM_SIZE
和WM_PAINT
消息的处理程序。
然后应该添加以下代码
BOOL CTreeCtrl::OnEraseBkgnd(CDC* pDC) { // TODO: Add your message handler code here and/or call default UNUSED_ALWAYS(pDC); //return CTreeCtrl::OnEraseBkgnd(pDC); return TRUE; } void CTreeCtrl::OnSize(UINT nType, int cx, int cy) { CTreeCtrl::OnSize(nType, cx, cy); GetClientRect(m_rectClient); } void CTreeCtrl::OnPaint() { CPaintDC dc(this); // Paint to a memory device context to reduce screen flicker. CMemDC memDC(&dc, &m_rectClient); ...... // Let the window do its default painting... CWnd::DefWindowProc( WM_PAINT, (WPARAM)memDC.m_hDC, 0 ); }
然后你就能获得无闪烁的效果。
CListCtrl
对于一个 CListCtrl
派生类,所有步骤都相同,除了 OnSize
函数应该修改如下,以允许在报告模式下显示 CHeadCtrl
(如果存在)。
void CListCtrl::OnSize(UINT nType, int cx, int cy) { CListCtrl::OnSize(nType, cx, cy); GetClientRect(m_rectClient); CHeaderCtrl* pHC; pHC = GetHeaderCtrl(); if (pHC != NULL) { CRect rectHeader; pHC->GetItemRect( 0, &rectHeader ); m_rectClient.top += rectHeader.bottom; } }
然后你就能获得无闪烁的效果。
GDI+
我发现了一些关于 GDI+ 中无闪烁绘制的文章。但是,我想扩展 Keith Rule 的代码来完成同样的工作,并避免使用 CachedBitmap 重新实现双缓冲机制。因此,我使用以下方法。
- 将文件 memdc.h 添加到你的项目中。
- 将行
#include "memdc.h"
添加到 stdafx.h 或所需的 .h 文件中。 - 添加一个公共的
CRect
变量,例如CRect m_rectClient;
添加WM_ERASEBKGND
、WM_SIZE
和WM_PAINT
消息的处理程序。
然后应该添加以下代码
BOOL CView::OnEraseBkgnd(CDC* pDC) { // TODO: Add your message handler code here and/or call default UNUSED_ALWAYS(pDC); //return CView::OnEraseBkgnd(pDC); return TRUE; } void CView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); GetClientRect(m_rectClient); } void CView::OnPaint() { CPaintDC dc(this); // Paint to a memory device context to reduce screen flicker. CMemDC memDC(&dc, &m_rectClient); Graphics graphics(memDC); ...... }
然后你就能获得无闪烁的效果。这种方法在 CScrollView
中也能很好地工作。好的,最后,还有一个有趣的问题留给你:哪种方法会更快,这种方法还是由 CachedBitmap 实现的双缓冲?
历史
- 初始发布日期:2003-05-24。