Answered Flicker at owner drawn button

  • Friday, January 29, 2010 7:52 PM
     
     
    I subclassed CButton  and made it owner drawn by setting the BS_OWNERDRAW style in PreSubclassWindow() and override DrawItem(..) to do the painting. It all works fine except I get a short flickering every time I click the button.

    I've set a debug break point at the beginning of my DrawItem() function and clicked the button. The break point is hit and I let the application run. After that the DrawItem() function is hit a second time. This time I can see in the emulator that the area of the button is filled with a solid color. This is causing the flicker. So between the two DrawItem calls the CButton class seems to clear the client area with some color. How can I surpress that?

    I've overridden OnEraseBkgnd() and just returned TRUE and also added the Message handler for this. But this doesn't help the function gets called sometimes (so I know it is wired up correctly) but not between the two DrawItem() calles mentioned above even though the background gets erased between the calls.

    Anyone any ideas on how to avoid this?

    Thanks

Answers

  • Saturday, January 30, 2010 5:45 PM
     
     Answered Has Code
    If anyone else has this problem, here is the solution for my problem:
    Handle the WM_CTLCOLOR_REFLECT message in your subclass with this function:
    HBRUSH CMyButton::CtlColor(CDC* pDC, UINT nCtlColor) 
    {
        return (HBRUSH)GetStockObject(HOLLOW_BRUSH);
    }
    Returning a non NULL value stops the framework from sending the WM_CTLCOLOR message to the parent.
    This technique is called message reflection, check the MSDN for more information.

    • Marked As Answer by MSWiege Saturday, January 30, 2010 5:45 PM
    •  

All Replies

  • Friday, January 29, 2010 8:41 PM
     
     
    I now found out that I can suppress the flickering if I catch the WM_CTLCOLOR message in the parent window that contain the buttons and return a (HBRUSH)GetStockObject(HOLLOW_BRUSH). With that the background does not get repainted between the two DrawItem calls and the flickering is gone.

    But does anyone know how I can achieve the same within my CButton subclass without the need to do changes to the parent windows? I couldn't figure out which method to override in my class to suppress the WM_CTLCOLOR message (and return a hollow brush myself).
  • Saturday, January 30, 2010 5:45 PM
     
     Answered Has Code
    If anyone else has this problem, here is the solution for my problem:
    Handle the WM_CTLCOLOR_REFLECT message in your subclass with this function:
    HBRUSH CMyButton::CtlColor(CDC* pDC, UINT nCtlColor) 
    {
        return (HBRUSH)GetStockObject(HOLLOW_BRUSH);
    }
    Returning a non NULL value stops the framework from sending the WM_CTLCOLOR message to the parent.
    This technique is called message reflection, check the MSDN for more information.

    • Marked As Answer by MSWiege Saturday, January 30, 2010 5:45 PM
    •