Click here to Skip to main content
Licence CPOL
First Posted 22 Apr 2003
Views 94,815
Bookmarked 19 times

FLICKER-free

By | 27 Apr 2003 | Article
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)

About the Author

moshe masas

Web Developer

Israel Israel

Member

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 !

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralMy vote of 4 Pinmemberitsho9:32 26 Sep '10  
GeneralNeed some help Pinmemberneelimakrishna16:56 5 Jan '05  
GeneralUse LVS_EX_DOUBLEBUFFER instead PinmemberAvdim1:13 8 May '03  
GeneralRe: Use LVS_EX_DOUBLEBUFFER instead PinmemberSteve_230934n513k5n132oi512309:38 11 May '05  
GeneralHebrew (and Arabic) Pinmemberquzi18:39 30 Apr '03  
GeneralRe: Hebrew (and Arabic) Pinmembermoshe masas11:35 1 May '03  
GeneralRe: Hebrew (and Arabic) Pinmemberdrecci22:51 6 May '03  
GeneralRe: Hebrew (and Arabic) Pinmemberquzi6:19 7 May '03  
GeneralRe: Hebrew (and Arabic) PinsussAnonymous11:37 7 May '03  
GeneralRe: Hebrew (and Arabic) Pinmembermoshe masas1:55 8 May '03  
GeneralIts FLICKER free, not flp-free Pinmemberarmentage7:04 24 Apr '03  
GeneralRe: Its FLICKER free, not flp-free PinmemberHockey11:01 24 Apr '03  
GeneralRe: Its FLICKER free, not flp-free PinmemberJohn M. Drescher13:06 28 Apr '03  
QuestionConfused? PinmemberJoseph Dempsey0:47 23 Apr '03  
AnswerRe: Confused? PinmemberDeLaTchoke6:58 23 Apr '03  
GeneralRe: Confused? PinsussAnonymous11:12 23 Apr '03  
AnswerRe: Confused? PinmemberMax Santos16:21 19 Jul '03  
GeneralRe: Confused? Pinmemberihawley4:24 7 Jun '04  
GeneralRe: Confused? PinmemberMax Santos10:37 7 Jun '04  
GeneralRe: Confused? Pinmemberihawley22:38 7 Jun '04  
GeneralSomething missing PinmemberJohn O'Byrne23:35 22 Apr '03  
GeneralResource Leaks PinmemberPeter Mares23:29 22 Apr '03  
GeneralRe: Resource Leaks PinmemberYangghi Min3:00 29 Apr '03  
GeneralRe: Resource Leaks Pinmembermoshe masas11:58 1 May '03  

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

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120517.1 | Last Updated 28 Apr 2003
Article Copyright 2003 by moshe masas
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid