2010-03-21 94 views
3

我在虛擬模式(LVS_OWNERDATA)下使用CListCtrl/CListView報告視圖(LVS_REPORT),啓用了LVS_EX_DOUBLEBUFFER,我遇到了難看的閃爍。雙緩衝區具有真正的效果,但並不會停止所有閃爍(沒有非常緩慢)。如何防止CListCtrl閃爍?

我不找切換至需要返工(如ObjectListView)高量的其他控件

如何閃爍的行爲:

  • 在列調整大小 - 背景是第一使用lightgray清潔,之後顯示文字(背景爲白色)
  • 鼠標滾動(動畫) - 在很短的時間內會在要顯示新行的區域顯示lightgray-bar。

看起來它使用默認的窗口背景顏色(lightgray)清理背景,用於重繪的區域。

如何解決閃爍問題?

回答

2

嘗試執行以下操作: - 爲列表控件的對齊對話框設置剪輯子項和剪輯同級。 - 從CListCtrl類生成。在這個類中覆寫OnEraseBkgnd。在OnEraseBkgnd中填充列表中可見項目周圍的背景顏色區域。 的OnEraseBkgnd可以關注一下:

BOOL CListCtrlEx::OnEraseBkgnd(CDC* pDC) 
{ 
    CBrush br; 
    CRect rcCli; 
    CRect rcItemsRect(0, 0, 0, 0); 
    int  nHeadHeight = 0; 
    int  nItems  = GetItemCount(); 

    GetClientRect(&rcCli); 

    CHeaderCtrl* pHeadCtrl = GetHeaderCtrl(); 
    if (pHeadCtrl) 
    { 
     CRect rcHead; 
     pHeadCtrl->GetWindowRect(&rcHead); 
     nHeadHeight = rcHead.Height(); 
    } 
    rcCli.top += nHeadHeight; 

    if (nItems > 0) 
    { 
     CPoint ptItem; 
     CRect rcItem; 

     GetItemRect(nItems - 1, &rcItem, LVIR_BOUNDS); 
     GetItemPosition(nItems - 1, &ptItem); 

     rcItemsRect.top = rcCli.top; 
     rcItemsRect.left = ptItem.x; 
     rcItemsRect.right = rcItem.right; 
     rcItemsRect.bottom = rcItem.bottom; 

     if (GetExtendedStyle() & LVS_EX_CHECKBOXES) 
      rcItemsRect.left -= GetSystemMetrics(SM_CXEDGE) + 16; 
    } 

    br.CreateSolidBrush(GetBkColor()); 

    if (rcItemsRect.IsRectEmpty()) 
     pDC->FillRect(rcCli, &br); 
    else 
    { 
     if (rcItemsRect.left > rcCli.left)  // fill left rectangle 
      pDC->FillRect(
       CRect(0, rcCli.top, rcItemsRect.left, rcCli.bottom), &br); 
     if (rcItemsRect.bottom < rcCli.bottom) // fill bottom rectangle 
      pDC->FillRect(
       CRect(0, rcItemsRect.bottom, rcCli.right, rcCli.bottom), &br); 
     if (rcItemsRect.right < rcCli.right) // fill right rectangle 
      pDC->FillRect(
       CRect(rcItemsRect.right, rcCli.top, rcCli.right, rcCli.bottom), &br); 
    } 

    return TRUE; 
} 
0

我只知道有免費使用雙緩衝或MemDC閃爍的方式。

已經發現這篇文章:Flicker-free-drawing-of-any-control

本文介紹了很好如何快速進行非閃爍在你的CListCtrl繪製。 它工作出色。

PS:VS 2005沒有CMemDC類類,你將需要實現它你自己,或者使用下面的代碼:

// 
// CMemDC.h header file 
// 
#pragma once 

class CMemDC 
{ 
public: 
    CMemDC(CDC& dc, CWnd* pWnd); 
    CMemDC(CDC& dc, const CRect& rect); 

    virtual ~CMemDC(); 

    CDC& GetDC() { return m_bMemDC ? m_dcMem : m_dc; } 
    BOOL IsMemDC() const { return m_bMemDC; } 
    BOOL IsVistaDC() const { return m_hBufferedPaint != NULL; } 

    void EraseBkClip(); 
protected: 
    CDC&  m_dc; 
    BOOL  m_bMemDC; 
    HANDLE m_hBufferedPaint; 
    CDC  m_dcMem; 
    CBitmap m_bmp; 
    CBitmap* m_pOldBmp; 
    CRect m_rect; 
}; 

// 
// CMemDC.cpp source file 
// 
#include "CMemDC.h" 

CMemDC::CMemDC(CDC& dc, CWnd* pWnd) : 
    m_dc(dc), m_bMemDC(FALSE), m_hBufferedPaint(NULL), m_pOldBmp(NULL) 
{ 
    ASSERT_VALID(pWnd); 

    pWnd->GetClientRect(m_rect); 
    m_rect.right += pWnd->GetScrollPos(SB_HORZ); 
    m_rect.bottom += pWnd->GetScrollPos(SB_VERT); 
    if (m_dcMem.CreateCompatibleDC(&m_dc) && 
     m_bmp.CreateCompatibleBitmap(&m_dc, m_rect.Width(), m_rect.Height())) 
    { 
     m_bMemDC = TRUE; 
     m_pOldBmp = m_dcMem.SelectObject(&m_bmp); 
    } 
} 

CMemDC::CMemDC(CDC& dc, const CRect& rect) : 
    m_dc(dc), m_bMemDC(FALSE), m_hBufferedPaint(NULL), m_pOldBmp(NULL), m_rect(rect) 
{ 
    ASSERT(!m_rect.IsRectEmpty()); 
    if (m_dcMem.CreateCompatibleDC(&m_dc) && 
     m_bmp.CreateCompatibleBitmap(&m_dc, m_rect.Width(), m_rect.Height())) 
    { 
     m_bMemDC = TRUE; 
     m_pOldBmp = m_dcMem.SelectObject(&m_bmp); 
    } 
} 

CMemDC::~CMemDC() 
{ 
    if (m_bMemDC) 
    { 
     CRect rectClip; 
     int nClipType = m_dc.GetClipBox(rectClip); 

     if (nClipType != NULLREGION) 
     { 
      if (nClipType != SIMPLEREGION) 
      { 
       rectClip = m_rect; 
      } 
      m_dc.BitBlt(rectClip.left, rectClip.top, rectClip.Width(), rectClip.Height(), &m_dcMem, rectClip.left, rectClip.top, SRCCOPY); 
     } 

     m_dcMem.SelectObject(m_pOldBmp); 
    } 
} 

void CMemDC::EraseBkClip() 
{ 
    CRect clip; 
    m_dcMem.GetClipBox(&clip); 
    m_dcMem.FillSolidRect(clip, GetSysColor(COLOR_WINDOW)); 
}