Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. double buffering issue...

double buffering issue...

Scheduled Pinned Locked Moved C / C++ / MFC
helpgraphicstutorialquestioncode-review
9 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • E Offline
    E Offline
    eli15021979
    wrote on last edited by
    #1

    Hi, In my project,I have to draw icon over a bitmap every 250msec. My problem is that sometimes the drawing over the bitmap is flickering in a very annoying way. I know that I need to draw over the bitmap using double buffering, and looked over some articles about it,but failed to understand how to do it. I can't use the classes of those articles (Safety issues...:~ ). Can anyone help me understand how to improve my drawing technique??? I use the following piece of code:

    void Frm_WkAtol::OnTimer(UINT_PTR nIDEvent)
    {
    // TODO: Add your message handler code here and/or call default
    m_AtolCorridorBitmap.Invalidate(); // cause the bitmap to redraw itself
    CDialog::OnTimer(nIDEvent);
    }

    void AtolCorridorBitmapClass::OnPaint()
    {
    CStatic::OnPaint();

    CRect CorridorRect;
    CDC \*pDC = GetDC();
        static int x = 0;
    
    // Set attributes of the DC
    pDC->SetTextColor(RED\_COLOR);
    pDC->SetBkMode(TRANSPARENT);   
    GetClientRect(&CorridorRect);
    szCaption.Format(\_T("Test %d") , x++);
    pDC->ExtTextOut(CorridorRect.left, CorridorRect.top + 30 , ETO\_OPAQUE , NULL , szCaption , NULL); 
    
    DrawIcon(pDC->m\_hDC, CorridorRect.left , CorridorRect.top  , m\_hUavInsideAtolCorridorIcon);
    
    ReleaseDC(pDC);
    

    }

    With best regards, Eli;P

    M M 2 Replies Last reply
    0
    • E eli15021979

      Hi, In my project,I have to draw icon over a bitmap every 250msec. My problem is that sometimes the drawing over the bitmap is flickering in a very annoying way. I know that I need to draw over the bitmap using double buffering, and looked over some articles about it,but failed to understand how to do it. I can't use the classes of those articles (Safety issues...:~ ). Can anyone help me understand how to improve my drawing technique??? I use the following piece of code:

      void Frm_WkAtol::OnTimer(UINT_PTR nIDEvent)
      {
      // TODO: Add your message handler code here and/or call default
      m_AtolCorridorBitmap.Invalidate(); // cause the bitmap to redraw itself
      CDialog::OnTimer(nIDEvent);
      }

      void AtolCorridorBitmapClass::OnPaint()
      {
      CStatic::OnPaint();

      CRect CorridorRect;
      CDC \*pDC = GetDC();
          static int x = 0;
      
      // Set attributes of the DC
      pDC->SetTextColor(RED\_COLOR);
      pDC->SetBkMode(TRANSPARENT);   
      GetClientRect(&CorridorRect);
      szCaption.Format(\_T("Test %d") , x++);
      pDC->ExtTextOut(CorridorRect.left, CorridorRect.top + 30 , ETO\_OPAQUE , NULL , szCaption , NULL); 
      
      DrawIcon(pDC->m\_hDC, CorridorRect.left , CorridorRect.top  , m\_hUavInsideAtolCorridorIcon);
      
      ReleaseDC(pDC);
      

      }

      With best regards, Eli;P

      M Offline
      M Offline
      Matthew Faithfull
      wrote on last edited by
      #2

      How about only invalidating only the rectangle that changes, then the only bit that needs redrawing is the icon, rather than the whole bitmap. I'd consider a separate overlaid windowless control if that doesn't work. Otherwise you need to incorporate the icon directly into the bitmap data so each change only redraws that area of the screen once. Remember to catch the erase background message and tell windows not to erase or you'll get really bad flicker whatever you do. :)

      Nothing is exactly what it seems but everything with seems can be unpicked.

      1 Reply Last reply
      0
      • E eli15021979

        Hi, In my project,I have to draw icon over a bitmap every 250msec. My problem is that sometimes the drawing over the bitmap is flickering in a very annoying way. I know that I need to draw over the bitmap using double buffering, and looked over some articles about it,but failed to understand how to do it. I can't use the classes of those articles (Safety issues...:~ ). Can anyone help me understand how to improve my drawing technique??? I use the following piece of code:

        void Frm_WkAtol::OnTimer(UINT_PTR nIDEvent)
        {
        // TODO: Add your message handler code here and/or call default
        m_AtolCorridorBitmap.Invalidate(); // cause the bitmap to redraw itself
        CDialog::OnTimer(nIDEvent);
        }

        void AtolCorridorBitmapClass::OnPaint()
        {
        CStatic::OnPaint();

        CRect CorridorRect;
        CDC \*pDC = GetDC();
            static int x = 0;
        
        // Set attributes of the DC
        pDC->SetTextColor(RED\_COLOR);
        pDC->SetBkMode(TRANSPARENT);   
        GetClientRect(&CorridorRect);
        szCaption.Format(\_T("Test %d") , x++);
        pDC->ExtTextOut(CorridorRect.left, CorridorRect.top + 30 , ETO\_OPAQUE , NULL , szCaption , NULL); 
        
        DrawIcon(pDC->m\_hDC, CorridorRect.left , CorridorRect.top  , m\_hUavInsideAtolCorridorIcon);
        
        ReleaseDC(pDC);
        

        }

        With best regards, Eli;P

        M Offline
        M Offline
        Mark Salsbery
        wrote on last edited by
        #3

        Here's an example of a double-buffered bitmap static control class...

        //------------------------------
        // DblBufferedStatic.h

        #pragma once

        // CDblBufferedStatic

        class CDblBufferedStatic : public CStatic
        {
        DECLARE_DYNAMIC(CDblBufferedStatic)

        protected:
        HBITMAP hStaticBitmap;
        CSize BackBufferSize;
        CDC BackBufferDC;
        CBitmap BackBufferBitmap;

        void InitBackBuffer();

        public:
        void RedrawBackBuffer();

        public:
        CDblBufferedStatic();
        virtual ~CDblBufferedStatic();

        protected:
        DECLARE_MESSAGE_MAP()
        public:
        afx_msg void OnPaint();
        afx_msg BOOL OnEraseBkgnd(CDC* pDC);
        };

        //------------------------------
        // DblBufferedStatic.cpp

        // DblBufferedStatic.cpp : implementation file
        //

        #include "stdafx.h"
        #include "MyApp.h"
        #include "DblBufferedStatic.h"
        #include ".\dblbufferedstatic.h"

        // CDblBufferedStatic

        IMPLEMENT_DYNAMIC(CDblBufferedStatic, CStatic)

        CDblBufferedStatic::CDblBufferedStatic()
        {
        hStaticBitmap = 0;
        }

        CDblBufferedStatic::~CDblBufferedStatic()
        {
        }

        BEGIN_MESSAGE_MAP(CDblBufferedStatic, CStatic)
        ON_WM_PAINT()
        ON_WM_ERASEBKGND()
        END_MESSAGE_MAP()

        void CDblBufferedStatic::InitBackBuffer()
        {
        // Get a handle to the bitmap associated with this control
        hStaticBitmap = GetBitmap();

        if (hStaticBitmap)
        {
        // Get the bitmap's dimensions
        BITMAP bitmapstruct;
        ::GetObject(hStaticBitmap, sizeof(BITMAP), &bitmapstruct);
        BackBufferSize.cx = bitmapstruct.bmWidth;
        BackBufferSize.cy = bitmapstruct.bmHeight;

          // Create the background buffer (DC and bitmap)
          CWindowDC WindowDC(this);
          BackBufferDC.CreateCompatibleDC(&WindowDC);
          BackBufferBitmap.CreateCompatibleBitmap(&WindowDC, BackBufferSize.cx, BackBufferSize.cy);
          `//*edit* removed BackBufferBitmap.GetObject(sizeof(BITMAP), &bitmapstruct);`
          BackBufferDC.SelectObject(&BackBufferBitmap);
        

        }
        }

        void CDblBufferedStatic::RedrawBackBuffer()
        {
        // Refresh (redraw) contents of background buffer

        if (hStaticBitmap)
        {
        // Draw original bitmap to offscreen buffer
        CDC TempDC;
        TempDC.CreateCompatibleDC(&BackBufferDC);
        CBitmap SrcBitmap;
        SrcBitmap.Attach(hStaticBitmap);
        CBitmap *pOldBitmap = TempDC.SelectObject(&SrcBitmap);
        BackBufferDC.BitBlt(0, 0, BackBufferSize.cx, BackBufferSize.cy, &TempDC, 0, 0, SRCCOPY);
        TempDC.SelectObject(pOldBitmap);
        SrcBitmap.Detach();

        E 2 Replies Last reply
        0
        • M Mark Salsbery

          Here's an example of a double-buffered bitmap static control class...

          //------------------------------
          // DblBufferedStatic.h

          #pragma once

          // CDblBufferedStatic

          class CDblBufferedStatic : public CStatic
          {
          DECLARE_DYNAMIC(CDblBufferedStatic)

          protected:
          HBITMAP hStaticBitmap;
          CSize BackBufferSize;
          CDC BackBufferDC;
          CBitmap BackBufferBitmap;

          void InitBackBuffer();

          public:
          void RedrawBackBuffer();

          public:
          CDblBufferedStatic();
          virtual ~CDblBufferedStatic();

          protected:
          DECLARE_MESSAGE_MAP()
          public:
          afx_msg void OnPaint();
          afx_msg BOOL OnEraseBkgnd(CDC* pDC);
          };

          //------------------------------
          // DblBufferedStatic.cpp

          // DblBufferedStatic.cpp : implementation file
          //

          #include "stdafx.h"
          #include "MyApp.h"
          #include "DblBufferedStatic.h"
          #include ".\dblbufferedstatic.h"

          // CDblBufferedStatic

          IMPLEMENT_DYNAMIC(CDblBufferedStatic, CStatic)

          CDblBufferedStatic::CDblBufferedStatic()
          {
          hStaticBitmap = 0;
          }

          CDblBufferedStatic::~CDblBufferedStatic()
          {
          }

          BEGIN_MESSAGE_MAP(CDblBufferedStatic, CStatic)
          ON_WM_PAINT()
          ON_WM_ERASEBKGND()
          END_MESSAGE_MAP()

          void CDblBufferedStatic::InitBackBuffer()
          {
          // Get a handle to the bitmap associated with this control
          hStaticBitmap = GetBitmap();

          if (hStaticBitmap)
          {
          // Get the bitmap's dimensions
          BITMAP bitmapstruct;
          ::GetObject(hStaticBitmap, sizeof(BITMAP), &bitmapstruct);
          BackBufferSize.cx = bitmapstruct.bmWidth;
          BackBufferSize.cy = bitmapstruct.bmHeight;

            // Create the background buffer (DC and bitmap)
            CWindowDC WindowDC(this);
            BackBufferDC.CreateCompatibleDC(&WindowDC);
            BackBufferBitmap.CreateCompatibleBitmap(&WindowDC, BackBufferSize.cx, BackBufferSize.cy);
            `//*edit* removed BackBufferBitmap.GetObject(sizeof(BITMAP), &bitmapstruct);`
            BackBufferDC.SelectObject(&BackBufferBitmap);
          

          }
          }

          void CDblBufferedStatic::RedrawBackBuffer()
          {
          // Refresh (redraw) contents of background buffer

          if (hStaticBitmap)
          {
          // Draw original bitmap to offscreen buffer
          CDC TempDC;
          TempDC.CreateCompatibleDC(&BackBufferDC);
          CBitmap SrcBitmap;
          SrcBitmap.Attach(hStaticBitmap);
          CBitmap *pOldBitmap = TempDC.SelectObject(&SrcBitmap);
          BackBufferDC.BitBlt(0, 0, BackBufferSize.cx, BackBufferSize.cy, &TempDC, 0, 0, SRCCOPY);
          TempDC.SelectObject(pOldBitmap);
          SrcBitmap.Detach();

          E Offline
          E Offline
          eli15021979
          wrote on last edited by
          #4

          Hi Mark, I couldn't ask for a better answer. It is working perfect. After reading your code - it seems to be so simple...:doh: THANK YOU VERY MUCH:-D:-D:-D With best regards, Eli

          1 Reply Last reply
          0
          • M Mark Salsbery

            Here's an example of a double-buffered bitmap static control class...

            //------------------------------
            // DblBufferedStatic.h

            #pragma once

            // CDblBufferedStatic

            class CDblBufferedStatic : public CStatic
            {
            DECLARE_DYNAMIC(CDblBufferedStatic)

            protected:
            HBITMAP hStaticBitmap;
            CSize BackBufferSize;
            CDC BackBufferDC;
            CBitmap BackBufferBitmap;

            void InitBackBuffer();

            public:
            void RedrawBackBuffer();

            public:
            CDblBufferedStatic();
            virtual ~CDblBufferedStatic();

            protected:
            DECLARE_MESSAGE_MAP()
            public:
            afx_msg void OnPaint();
            afx_msg BOOL OnEraseBkgnd(CDC* pDC);
            };

            //------------------------------
            // DblBufferedStatic.cpp

            // DblBufferedStatic.cpp : implementation file
            //

            #include "stdafx.h"
            #include "MyApp.h"
            #include "DblBufferedStatic.h"
            #include ".\dblbufferedstatic.h"

            // CDblBufferedStatic

            IMPLEMENT_DYNAMIC(CDblBufferedStatic, CStatic)

            CDblBufferedStatic::CDblBufferedStatic()
            {
            hStaticBitmap = 0;
            }

            CDblBufferedStatic::~CDblBufferedStatic()
            {
            }

            BEGIN_MESSAGE_MAP(CDblBufferedStatic, CStatic)
            ON_WM_PAINT()
            ON_WM_ERASEBKGND()
            END_MESSAGE_MAP()

            void CDblBufferedStatic::InitBackBuffer()
            {
            // Get a handle to the bitmap associated with this control
            hStaticBitmap = GetBitmap();

            if (hStaticBitmap)
            {
            // Get the bitmap's dimensions
            BITMAP bitmapstruct;
            ::GetObject(hStaticBitmap, sizeof(BITMAP), &bitmapstruct);
            BackBufferSize.cx = bitmapstruct.bmWidth;
            BackBufferSize.cy = bitmapstruct.bmHeight;

              // Create the background buffer (DC and bitmap)
              CWindowDC WindowDC(this);
              BackBufferDC.CreateCompatibleDC(&WindowDC);
              BackBufferBitmap.CreateCompatibleBitmap(&WindowDC, BackBufferSize.cx, BackBufferSize.cy);
              `//*edit* removed BackBufferBitmap.GetObject(sizeof(BITMAP), &bitmapstruct);`
              BackBufferDC.SelectObject(&BackBufferBitmap);
            

            }
            }

            void CDblBufferedStatic::RedrawBackBuffer()
            {
            // Refresh (redraw) contents of background buffer

            if (hStaticBitmap)
            {
            // Draw original bitmap to offscreen buffer
            CDC TempDC;
            TempDC.CreateCompatibleDC(&BackBufferDC);
            CBitmap SrcBitmap;
            SrcBitmap.Attach(hStaticBitmap);
            CBitmap *pOldBitmap = TempDC.SelectObject(&SrcBitmap);
            BackBufferDC.BitBlt(0, 0, BackBufferSize.cx, BackBufferSize.cy, &TempDC, 0, 0, SRCCOPY);
            TempDC.SelectObject(pOldBitmap);
            SrcBitmap.Detach();

            E Offline
            E Offline
            eli15021979
            wrote on last edited by
            #5

            Hi Mark, Just one more question.... I'm using the http://www.codeproject.com/listctrl/ReportControl.asp[^] in order to display a list control with different rows color and icons. The problem is that I need to update the list every 250msec, and guess what......the list is not flicker free... I know that updating a list control is very expensive, but I was wondering if I can use the double buffering technique also for the list control(which is owner drawn). With best regards, Eli

            M 1 Reply Last reply
            0
            • E eli15021979

              Hi Mark, Just one more question.... I'm using the http://www.codeproject.com/listctrl/ReportControl.asp[^] in order to display a list control with different rows color and icons. The problem is that I need to update the list every 250msec, and guess what......the list is not flicker free... I know that updating a list control is very expensive, but I was wondering if I can use the double buffering technique also for the list control(which is owner drawn). With best regards, Eli

              M Offline
              M Offline
              Mark Salsbery
              wrote on last edited by
              #6

              What happens if you use WM_SETREDRAW... m_ListCtl.SendMessage(WM_SETREDRAW, (WPARAM)FALSE, 0); ... ...do stuff with the listview contents... ... m_ListCtl.SendMessage(WM_SETREDRAW, (WPARAM)TRUE, 0); m_ListCtl.Invalidate(); m_ListCtl.UpdateWindow();

              "Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder

              E 1 Reply Last reply
              0
              • M Mark Salsbery

                What happens if you use WM_SETREDRAW... m_ListCtl.SendMessage(WM_SETREDRAW, (WPARAM)FALSE, 0); ... ...do stuff with the listview contents... ... m_ListCtl.SendMessage(WM_SETREDRAW, (WPARAM)TRUE, 0); m_ListCtl.Invalidate(); m_ListCtl.UpdateWindow();

                "Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder

                E Offline
                E Offline
                eli15021979
                wrote on last edited by
                #7

                Hi Mark, Instead of sending WM_SETREDRAW message,I'm using m_ListCtrl.SetRedraw() and m_ListCtrl.SetRedraw(FALSE). But still,the list control is blinking. I thought that double buffering drawing will solve the problem,but since the control is owner drawn,I don't have access to the drawing functions.... Maybe it is not possible???:sigh: Thanks, Eli

                M 1 Reply Last reply
                0
                • E eli15021979

                  Hi Mark, Instead of sending WM_SETREDRAW message,I'm using m_ListCtrl.SetRedraw() and m_ListCtrl.SetRedraw(FALSE). But still,the list control is blinking. I thought that double buffering drawing will solve the problem,but since the control is owner drawn,I don't have access to the drawing functions.... Maybe it is not possible???:sigh: Thanks, Eli

                  M Offline
                  M Offline
                  Mark Salsbery
                  wrote on last edited by
                  #8

                  It should be possible - You may have to do most of the drawing yourself. In the source you linked to, the author is only providing custom colors although the framework is there to do the drawing. What parts flicker specifically? Is it the text on the background? Mark

                  "Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder

                  E 1 Reply Last reply
                  0
                  • M Mark Salsbery

                    It should be possible - You may have to do most of the drawing yourself. In the source you linked to, the author is only providing custom colors although the framework is there to do the drawing. What parts flicker specifically? Is it the text on the background? Mark

                    "Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder

                    E Offline
                    E Offline
                    eli15021979
                    wrote on last edited by
                    #9

                    Hi Mark, Thanks for your patience:-D

                    Mark Salsbery wrote:

                    What parts flicker specifically? Is it the text on the background?

                    No,Only the background is flickering(and not allways). I don't know if this could help,but the following function is being called every time that the list needs to be updated(i.e every 250msec).

                    void Frm_WKFailureList::UpdateList(iGendevBit::BitMatrixResultListType &p_FailuresListRef)
                    {
                    iGendevBit::BitMatrixResultClass *CurrentElement;
                    dDbsrvNotif::notificationTextType NotifText;
                    COLORREF SeverityColor;
                    UINT uiCurrentRow = 0;
                    UINT uiCurrentErrorsCounter = 0;

                    m\_FailureList.SetRedraw(FALSE);
                    
                    // Adjust the list's last column according to
                    // the right scroll bar existent 
                    if (p\_FailuresListRef.GetElementNum() > MAX\_VISIBLE\_ITEM\_WITH\_NO\_SCROLL)
                    {
                    	m\_FailureList.SetColumnWidth(2 , 30);
                    }
                    else
                    {
                    	m\_FailureList.SetColumnWidth(2 , 48);
                    }
                    
                    uiCurrentErrorsCounter = p\_FailuresListRef.GetElementNum();
                    p\_FailuresListRef.ScanInit(bTypesCnt::FROM\_TAIL);
                    while ((CurrentElement = p\_FailuresListRef.ScanNext()) != NULL)
                    {
                    
                    	// Get failure severity
                    	switch(CurrentElement->m\_Severity)
                    	{
                    		case iGendevBit::SLIGHT:
                    			// in the future  - do not show "Slight" severity in the list.
                    			// For now - show with with background
                    			SeverityColor = RGB(255 , 255 , 0);
                    			break;
                    		case iGendevBit::MEDIUM:
                    			SeverityColor = RGB(255 , 255 , 0);
                    			break;
                    		case iGendevBit::SEVERE:
                    			SeverityColor = RGB(255 , 0 , 0);
                    			break;
                    	}
                    
                    	// Get failure text
                    	dDbsrvNotif::GetNotifText(NotifText , CurrentElement->m\_NotiffId);
                    	CString szError , szTime;
                    
                    	szError = NotifText;
                    	szTime = CurrentElement->m\_FailureTime.GetFormattedTod(bTimeTod::HH\_MM\_SS);
                    	if (m\_FailureList.GetItemCount() < (uiCurrentRow + 1))
                    	{
                    		m\_FailureList.InsertItem(uiCurrentRow  , \_T(""));
                    	}
                    	static int x = 0;
                    	szTime.Format(\_T("%d") , x++);
                    
                    	m\_FailureList.SetItemText(uiCurrentRow , 0 , szTime);
                    	m\_FailureList.SetItemText(uiCurrentRow , 1 , szError);
                    
                    	// Get failure check list existents
                    	CHECK\_LIST\_ENUM IsCheckListExist = NO\_CHECK\_LIST;
                    	SetLineBkColorAndIcon(uiCurrentRow , SeverityColor , IsCheckListExist); // Set the icon and background color for the current row
                    	
                    	uiCurrentRow++;
                    	m\_bListIsEmpty = FALSE;
                    }
                    
                    if (uiCurrentRow < m\_LastErrorsCounter)
                    {
                    	for (UINT uiIndex = uiCur
                    
                    1 Reply Last reply
                    0
                    Reply
                    • Reply as topic
                    Log in to reply
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes


                    • Login

                    • Don't have an account? Register

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • World
                    • Users
                    • Groups