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. ATL / WTL / STL
  4. How to create an flicker free owner draw listbox using CDoubleBufferWindowImpl?

How to create an flicker free owner draw listbox using CDoubleBufferWindowImpl?

Scheduled Pinned Locked Moved ATL / WTL / STL
tutorialquestion
3 Posts 2 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.
  • P Offline
    P Offline
    Philipp Kursawe
    wrote on last edited by
    #1

    Hello, I am struggling to fit CListBoxCtrl and CDoubleBufferWindowImpl together. I have a owner drawn listbox ready, whose MSG_WM_DRAWITEM I handle in the parent control for now. I guess the first step would be to move the MSG_WM_DRAWITEM message handling to my custom listbox control. How would I then also fit in the double buffer technique? My solution was something like in the DoPaint method to call the original controls DefWndProc but that does not work. Any ideas?

    Happy coding, Philipp Kursawe

    A 1 Reply Last reply
    0
    • P Philipp Kursawe

      Hello, I am struggling to fit CListBoxCtrl and CDoubleBufferWindowImpl together. I have a owner drawn listbox ready, whose MSG_WM_DRAWITEM I handle in the parent control for now. I guess the first step would be to move the MSG_WM_DRAWITEM message handling to my custom listbox control. How would I then also fit in the double buffer technique? My solution was something like in the DoPaint method to call the original controls DefWndProc but that does not work. Any ideas?

      Happy coding, Philipp Kursawe

      A Offline
      A Offline
      Alain Rist
      wrote on last edited by
      #2

      Hi Philipp,

      Philipp Kursawe wrote:

      I guess the first step would be to move the MSG_WM_DRAWITEM message handling to my custom listbox control

      It may be your choice but it's not the first step. You need to use a double buffered CListBox, for instance:

      class CMyListBox : public CDoubleBufferWindowImpl<CMyListBox, CListBox, ATL::CControlWinTraits>
      {
      BEGIN_MSG_MAP(CMyListBox)
      CHAIN_MSG_MAP(CDoubleBufferWindowImpl)
      END_MSG_MAP()
      void DoPaint(HDC hdc)
      {
      DefWindowProc(WM_PAINT, (WPARAM)hdc, 0);
      }
      };

      If you subclass the listbox in your parent dialog OnInit(), you can check with breakpoints that the dc referenced in your DrawItem() member is the MemoryDC set in CMyListBox::DoPaint(). My test code:

      class CTest0View :
      public CDialogImpl<CTest0View>,
      public COwnerDraw<CTest0View>
      {
      public:
      enum { IDD = IDD_TEST0_FORM };
      CMyListBox m_lb;
      void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
      {
      // must be implemented
      return;
      }
      BEGIN_MSG_MAP(CTest0View)
      MESSAGE_HANDLER(WM_INITDIALOG, OnInit)
      CHAIN_MSG_MAP(COwnerDraw<CTest0View>)
      FORWARD_NOTIFICATIONS()
      END_MSG_MAP()

      LRESULT OnInit(UINT /\*uMsg\*/, WPARAM /\*wParam\*/, LPARAM /\*lParam\*/, BOOL& bHandled)
      {
      	m\_lb.SubclassWindow(GetDlgItem(IDC\_LIST1));
      	m\_lb.AddString(L"Titi");
      	m\_lb.AddString(L"Tata");
      	m\_lb.AddString(L"Toto");
      
      	return bHandled = FALSE;
      }
      

      };

      cheers, AR

      When the wise (person) points at the moon the fool looks at the finger (Chinese proverb)

      P 1 Reply Last reply
      0
      • A Alain Rist

        Hi Philipp,

        Philipp Kursawe wrote:

        I guess the first step would be to move the MSG_WM_DRAWITEM message handling to my custom listbox control

        It may be your choice but it's not the first step. You need to use a double buffered CListBox, for instance:

        class CMyListBox : public CDoubleBufferWindowImpl<CMyListBox, CListBox, ATL::CControlWinTraits>
        {
        BEGIN_MSG_MAP(CMyListBox)
        CHAIN_MSG_MAP(CDoubleBufferWindowImpl)
        END_MSG_MAP()
        void DoPaint(HDC hdc)
        {
        DefWindowProc(WM_PAINT, (WPARAM)hdc, 0);
        }
        };

        If you subclass the listbox in your parent dialog OnInit(), you can check with breakpoints that the dc referenced in your DrawItem() member is the MemoryDC set in CMyListBox::DoPaint(). My test code:

        class CTest0View :
        public CDialogImpl<CTest0View>,
        public COwnerDraw<CTest0View>
        {
        public:
        enum { IDD = IDD_TEST0_FORM };
        CMyListBox m_lb;
        void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
        {
        // must be implemented
        return;
        }
        BEGIN_MSG_MAP(CTest0View)
        MESSAGE_HANDLER(WM_INITDIALOG, OnInit)
        CHAIN_MSG_MAP(COwnerDraw<CTest0View>)
        FORWARD_NOTIFICATIONS()
        END_MSG_MAP()

        LRESULT OnInit(UINT /\*uMsg\*/, WPARAM /\*wParam\*/, LPARAM /\*lParam\*/, BOOL& bHandled)
        {
        	m\_lb.SubclassWindow(GetDlgItem(IDC\_LIST1));
        	m\_lb.AddString(L"Titi");
        	m\_lb.AddString(L"Tata");
        	m\_lb.AddString(L"Toto");
        
        	return bHandled = FALSE;
        }
        

        };

        cheers, AR

        When the wise (person) points at the moon the fool looks at the finger (Chinese proverb)

        P Offline
        P Offline
        Philipp Kursawe
        wrote on last edited by
        #3

        Thanks Alain, this works (almost)! I am using your WTL::CControlDialogImpl to show the listbox in a modal dialog. The drawing is a little off now.

        void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT item)
        if (item->itemID == -1) return;

        WTL::CDCHandle dc(item->hDC);
        
        dc.GradientFillRect(item->rcItem, RGB(200,200,200), RGB(10,10,10), false);
        if (item->itemState == ODS\_FOCUS) {
          dc.SetTextColor(RGB(255,255,255));
        } else {
          dc.SetTextColor(RGB(255,255,255));
        }
        WCHAR text\[1024\];
        int chars = m\_Ctrl.GetText(item->itemID, text);
        dc.SetBkMode(TRANSPARENT);
        dc.SelectFont(font);
        dc.DrawText(text, chars, &item->rcItem, DT\_NOPREFIX | DT\_SINGLELINE | DT\_CENTER | DT\_VCENTER | DT\_END\_ELLIPSIS);
        

        }

        After some rows the gradients stop to show up and the background is just the standard window color.

        Happy coding, Philipp Kursawe

        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