Click here to Skip to main content
15,907,183 members
Articles / Desktop Programming / MFC

FLICKER-free

Rate me:
Please Sign up or sign in to vote.
1.33/5 (30 votes)
27 Apr 2003CPOL1 min read 125.1K   20   24
how to implement double buffer in the list cnntrol to avoid flipping

Introduction

This is the main window of the cabnet project.

As you see - the list control contains the driver's numbers identification - placed time sortly. Cabnet - usging the list control without
flickering

While usually the MFC technique to draw the list controls items is sufficient, i had confronted a crises with my last project. the drawing operations inside the internal OnPaint function was truely heavy, And the view was flickly disaster.

Conclusion : don't take the flicking - flippancy !!! To avoid flicking in the list control you have to create your own extention to the original CListCtrl class and to implement the following functions.

class CListCtrlEx : public CListCtrl 
{
    protected:
    void DrawItem(LPDRAWITEMSTRUCT);
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    afx_msg void OnPaint();
    public:  
    void SetCustomFont(int nSize,LPCSTR szName)
    protected :

    TEXTMETRIC m_fnt_tm;
    CFont m_fntCustom;
    ...
    ...
    
    DECLARE_MESSAGE_MAP()
}

You could choose a custom font :

void CListCtrlEx::SetCustomFont(int nSize,LPCSTR szName)
{

    if (m_fntCustom,GetSafeHandle())
        m_fntCustom.DestroyFont();
    m_fntCustom.CreateFont(nSize, 0, 0, 0, 400, FALSE, FALSE, 0,
                    DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
                    CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
                    DEFAULT_PITCH | FF_SWISS,szName);
    SetFontHeight()

}
void CListCtrlEx::SetFontHeight()
 {
     CClientDC dc(this);
     // select font or stay with the default font
     CFont *pFontOld = NULL; 
     if (m_fntCustom.GetSafeHandle())
         pFontOld = dc.SelectObject(&m_fntCustom);

     TEXTMETRIC tm;
     ::GetTextMetrics(dc.m_hDC,&tm);     
     m_fnt_tm = tm;
     // drop font
     if (pFontOld) dc.SelectObject(pFontOld);
 }
BOOL CListCtrlEx::OnEraseBkgnd(CDC* pDC) 
{
    return 1;
    //return CListCtrl::OnEraseBkgnd(pDC); // this is the criminal 
                                               // who make the most flicking problems...

}
void CListCtrlEx::OnPaint() 
{
    CPaintDC dc(this); // device context for painting
    int nVertPos;
    CDC dcm;    
    CRect rc;
    GetClientRect(rc);
    dcm.CreateCompatibleDC(&dc);
    CBitmap bmt;
    bmt.CreateCompatibleBitmap(&dc,rc.Width(),rc.Height());
    CBitmap *pBitmapOld = dcm.SelectObject(&bmt);
    
    dcm.Rectangle(rc);// make the work of the OnEraseBkgnd function
        
    DRAWITEMSTRUCT dd;
    dd.hwndItem = m_hWnd;
    dd.hDC = dc.m_hDC;
        dc.SetBkMode(TRANSPARENT); 
    // select objects as && if you like 
       
        nVertPos = GetScrollPos(SB_VERT);
      if (nVertPos!=0) {
      nVertPos = nVertPos/m_fnt_tm.tmHeight;
}


    for (int v=0; v<rc.Height()/m_fnt_tm.tmHeight; v++) {
     
        dd.itemID = v+nVertPos;    
        DrawItem(&dd);


    }
    BitBlt(dc.m_hDC,0,0,rc.Width(),rc.Height(),dcm.m_hDC,0,0,SRCCOPY);

    dcm.SelectObject(pBitmapOld);
    // drop other objects from the dc context memory - if there are.


}
void CListCtrlEx::DrawItem(LPDRAWITEMSTRUCT ld) 
{
         CHeaderCtrl* pHeader = GetHeaderCtrl( );
         int nCols = pHeader->GetItemCount( );
         CRect rf;
         int nVertPos = GetScrollPos(SB_VERT);
         
         for (int nIndex=0; nIndex<nCols; nIndex++) 
         {
              GetSubItemRect( ld->itemID, nIndex,LVIR_BOUNDS , rf);
              rf.top -= nVertPos;
              rf.bottom = rf.top + m_fnt_tm.tmHeight;
                        
             // draw what ever you like on the rf rectangle...
         }
}
Finally, you have to create the list control with the LVS_OWNERDRAWFIXED style.

note : if you decide to choose custom font you have also to implement the GetSubItemRect function because the re-paint rectangle should be in regard to the custom font size.

BOOL CListCtrlEx::GetSubItemRect(int iItem, int iSubItem, int nArea, CRect &ref)
{
        BOOL bRet = CListCtrl::GetSubItemRect( iItem, iSubItem, nArea, ref );
        if (!m_fntCustom.GetSafeHandle()) return bRet;
        ref.top = (iItem*m_fnt_tm.tmHeight);
        ref.bottom=ref.top+m_fnt_tm.tmHeight;
        return bRet;
}
p.s : If the list control has the WS_HSCROLL style - you have to adjust the drawing the same way we used for the WS_VSCROLL case - by using the GetScrollPos() function with the value SB_HORZ for its argument.

tip

bitmap store for speedness and memory saving

If you have multiple windows to draw by yourself - consider to use big CBitmap variable stored in stack or in the heap for the life of the app, and take it as your memory storeroom for all your painting.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Israel Israel
I'm just a small brain connected to an un-limited
brains network, which lead directly to the top ten
giant minds. Which lead me to the
thought : who am i?

I am just a jerry-built god !

Comments and Discussions

 
GeneralMy vote of 4 Pin
itsho26-Sep-10 9:32
itsho26-Sep-10 9:32 
nice info, even thow could be replaced with short api
GeneralNeed some help Pin
neelimakrishna5-Jan-05 16:56
neelimakrishna5-Jan-05 16:56 
GeneralUse LVS_EX_DOUBLEBUFFER instead Pin
Avdim8-May-03 1:13
Avdim8-May-03 1:13 
GeneralRe: Use LVS_EX_DOUBLEBUFFER instead Pin
Steve_230934n513k5n132oi5123011-May-05 9:38
Steve_230934n513k5n132oi5123011-May-05 9:38 
GeneralHebrew (and Arabic) Pin
quzi30-Apr-03 18:39
quzi30-Apr-03 18:39 
GeneralRe: Hebrew (and Arabic) Pin
moshe masas1-May-03 11:35
moshe masas1-May-03 11:35 
GeneralRe: Hebrew (and Arabic) Pin
drecci6-May-03 22:51
drecci6-May-03 22:51 
GeneralRe: Hebrew (and Arabic) Pin
quzi7-May-03 6:19
quzi7-May-03 6:19 
GeneralRe: Hebrew (and Arabic) Pin
Anonymous7-May-03 11:37
Anonymous7-May-03 11:37 
GeneralRe: Hebrew (and Arabic) Pin
moshe masas8-May-03 1:55
moshe masas8-May-03 1:55 
GeneralIts FLICKER free, not flp-free Pin
armentage24-Apr-03 7:04
armentage24-Apr-03 7:04 
GeneralRe: Its FLICKER free, not flp-free Pin
alex.barylski24-Apr-03 11:01
alex.barylski24-Apr-03 11:01 
GeneralRe: Its FLICKER free, not flp-free Pin
John M. Drescher28-Apr-03 13:06
John M. Drescher28-Apr-03 13:06 
QuestionConfused? Pin
Joseph Dempsey23-Apr-03 0:47
Joseph Dempsey23-Apr-03 0:47 
AnswerRe: Confused? Pin
DeLaTchoke23-Apr-03 6:58
DeLaTchoke23-Apr-03 6:58 
GeneralRe: Confused? Pin
Anonymous23-Apr-03 11:12
Anonymous23-Apr-03 11:12 
AnswerRe: Confused? Pin
Max Santos19-Jul-03 16:21
Max Santos19-Jul-03 16:21 
GeneralRe: Confused? Pin
ihawley7-Jun-04 4:24
ihawley7-Jun-04 4:24 
GeneralRe: Confused? Pin
Max Santos7-Jun-04 10:37
Max Santos7-Jun-04 10:37 
GeneralRe: Confused? Pin
ihawley7-Jun-04 22:38
ihawley7-Jun-04 22:38 
GeneralSomething missing Pin
John O'Byrne22-Apr-03 23:35
John O'Byrne22-Apr-03 23:35 
GeneralResource Leaks Pin
Peter Mares22-Apr-03 23:29
Peter Mares22-Apr-03 23:29 
GeneralRe: Resource Leaks Pin
Yangghi Min29-Apr-03 3:00
Yangghi Min29-Apr-03 3:00 
GeneralRe: Resource Leaks Pin
moshe masas1-May-03 11:58
moshe masas1-May-03 11:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.