CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 20
  1. #1
    Join Date
    Nov 2003
    Location
    Portland, OR
    Posts
    894

    CStatic control flicker only when running with Windows Classic theme

    I'm dealing with a very weird visual bug. Let me explain.

    I have a C++/MFC application that displays a count in a window:

    Name:  1.png
Views: 3169
Size:  5.3 KB

    The count (text) is displayed via a `CStatic` control. The mechanism is very simple. I call it every 1000 ms and update the text as such:

    Code:
        void CTestCountdownFlickerDlg::RedrawCounter(LPCTSTR pText)
        {
        	CStatic* pTxtBox = (CStatic*)this->GetDlgItem(IDC_STATIC_COUNTER);
        	ASSERT(pTxtBox);
        
        	//Get previous text
        	CString strPrevText;
        	pTxtBox->GetWindowText(strPrevText);
        
        	//Update only if different
        	if(strPrevText.Compare(pText) != 0)
        	{
        		//Set next text
        		pTxtBox->SetWindowText(pText);
        	}
        }
    What happens is that the `CStatic` control updates without any issues on the OS with visual themes enabled, but if I run it on the OS with the Windows Classic theme (for instance, the screenshot above is from Windows 7) the `CStatic` control produces a visible flicker every time it updates the text.

    Well, I understand that I'm nitpicking here, still I would really like to get rid of this flicker.

    Here's what I tried:

    1. In my actual project I tried subclassing the `CStatic` control and removed the processing of `WM_ERASEBACKGROUND` by simply returning 1. That didn't help.

    2. In the same subclass for `CStatic` control I tried to override `WM_PAINT`, but that didn't work at all. So I'm not sure if I'm going too far with it at this point.

    I'm attaching the C++/MFC source code for my test project I made the screenshot above for.
    Attached Files Attached Files

  2. #2
    VictorN's Avatar
    VictorN is online now Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,395

    Re: CStatic control flicker only when running with Windows Classic theme

    hYou could change your design placing the "count number" in another static control and then update only this one.
    Or you could replace the static control with a read-only edit one and then use CEdit::SetSel / CEdit::ReplaceSel to only replace the "count number" in the text.
    Victor Nijegorodov

  3. #3
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: CStatic control flicker only when running with Windows Classic theme

    Rather than call GetDlgItem on each timer click, why not use a DDX CString variable? Also no need to over-optimize by calling GetWindowText when the text is always going to need updating. Eliminating these two calls may reduce the flickering.

  4. #4
    Join Date
    Nov 2003
    Location
    Portland, OR
    Posts
    894

    Re: CStatic control flicker only when running with Windows Classic theme

    Thank you guys. Since I posted this question I was able to resolve it (the hard way.) I ended up making it an owner-drawn static control (by setting the SS_OWNERDRAW style) and then doing my own rendering in WM_DRAWITEM and by eliminating WM_ERASEBACKGROUND (by simply returning 1 from it.) The flicker is produced because of a two-stage drawing process: first, the background is erased while processing the WM_ERASEBACKGROUND notification, and then the actual rendering is done in the WM_PAINT notification. I don't know why they went with this method in the first place? Probably due to slow computers of the time. In this day and age such separation is totally outdated. So I think it is optimized by the OS when the modern themes are enabled, but that optimization is suppressed when "Windows Classic" is enabled, which in turn produces the flicker. So the bottom line, rendering the static control on my own is not fun (one needs a lot of code) but it fixes the issue in the first place, once the control is rendered in one place.

  5. #5
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: CStatic control flicker only when running with Windows Classic theme

    The inherent problem is that of "on demand painting".

    In the last few instances of windows you may have come accustomed to a "new" way of painting and that is one where windows keeps a current bitmap of the application and the desktop manager uses that bitmap for creating the thumbnails in the task bar, the 3D window flipper and for composing the desktop with alpha transparencies.

    You can disable that and then the old bahaviour returns, where each update causes a WM_PAINT and this in turn causes each window to paint in turn.

    The flicker you see is not really caused by the static control, rather, it's being cause by the dialog painting it's client area in the 3D color prior to painting it's children.

    you can fix this, but "does it really matter". If this is really such a big deal, then the suggestion by Victor is probably a better one. Leave the text as is, have the counter in a separate control. It won't remove flicker entirely, but it may limit it enough to not make it an issue anymore.

  6. #6
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,234

    Re: CStatic control flicker only when running with Windows Classic theme

    This is a little bit tricky but it's simple and it works:

    Code:
    // TestCountdownFlickerDlg.h
    
    class CTestCountdownFlickerDlg : public CDialog
    {
        CBrush m_brush;
    // ...
    // ...
        afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    };
    Code:
    // TestCountdownFlickerDlg.cpp
    
    BEGIN_MESSAGE_MAP(CTestCountdownFlickerDlg, CDialog)
        // ...
        ON_WM_CTLCOLOR()
    END_MESSAGE_MAP()
    
    HBRUSH CTestCountdownFlickerDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    {
        HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
    
        if(CTLCOLOR_STATIC == nCtlColor)
        {
            if(NULL == m_brush.GetSafeHandle())
                m_brush.CreateStockObject(NULL_BRUSH);
            else
                return m_brush;
        
        }
        return hbr;
    }
    It paints the static control background only once, avoiding further flickering.
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  7. #7
    Join Date
    Jul 2002
    Posts
    2,543

    Re: CStatic control flicker only when running with Windows Classic theme

    Quote Originally Posted by OReubens View Post
    The flicker you see is not really caused by the static control, rather, it's being cause by the dialog painting it's client area in the 3D color prior to painting it's children.
    So, maybe WS_CLIPCHILDREN parent style is the solution?

  8. #8
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,234

    Re: CStatic control flicker only when running with Windows Classic theme

    Quote Originally Posted by Alex F View Post
    So, maybe WS_CLIPCHILDREN parent style is the solution?
    Testing it, I've found it's not.
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  9. #9
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: CStatic control flicker only when running with Windows Classic theme

    WS_CLIPCHILDREN... note that you need to set this on the dialog, not the control.

    Maybe, but then you'll have to provide your own background which may introduce the flicker again. And it may cause other painting issues, especially if your dialog or controls are sizable.

    As I said before, typically speaking "don't worry about this". If the flicker is really that much of an issue, then you should really consider a window with a custom paint rather than trying to "fix" a dialog.

    THe problem with trying to "fix" dialogs is that they're used in all kinds of different modes and there are things like Terminal server, RDP, Remote desktop, Desktop composition, video drivers (accelerators), screen readers, disability services etc that will "mess up" if you try to "fix" too much. SO you may end up fixing the flicker, and introducing a bunch of other problems on another PC with another Windows setup. (that and the fact it's a lot of work to achieve little )

  10. #10
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,234

    Re: CStatic control flicker only when running with Windows Classic theme

    Quote Originally Posted by OReubens View Post
    [...]
    THe problem with trying to "fix" dialogs is that they're used in all kinds of different modes and there are things like Terminal server, RDP, Remote desktop, Desktop composition, video drivers (accelerators), screen readers, disability services etc that will "mess up" if you try to "fix" too much. SO you may end up fixing the flicker, and introducing a bunch of other problems on another PC with another Windows setup. (that and the fact it's a lot of work to achieve little )
    Sounds like "it has no much sense to build as long as one day, an asteroid will hit Earth..."

    Of course, the solution #2 (placing the count number in another static) is generally more kosher.
    However, in this particular case, #5 (by handling WM_CTLCOLOR), although as I said is a little bit tricky, works as well. Except case someone wise has the brilliant idea to make sizeable a poor static text control, intended just to display a counter.

    BTW. Just for curiosity and for fun, here is tested on a remote desktop connection. Both server (Windows Server 2012) and client (Windows 7) are hosted in virtual machines. Pretty hard conditions, isn't it?
    As expected, no blinking, no flicker and no any other catastrophic issue happened...

    Name:  RD_Test.jpg
Views: 2479
Size:  43.1 KB
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  11. #11
    Join Date
    Jul 2002
    Posts
    2,543

    Re: CStatic control flicker only when running with Windows Classic theme

    Quote Originally Posted by ovidiucucu View Post
    It has no much sense to build as long as one day, an asteroid will hit Earth...
    Well, actually, this is correct.

  12. #12
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: CStatic control flicker only when running with Windows Classic theme

    Quote Originally Posted by ovidiucucu View Post
    Sounds like "it has no much sense to build as long as one day, an asteroid will hit Earth..."
    heh.
    Not what I was trying to convey. More as in. Use windowsfeatures the way they're intended, and accept that some things work the way they do.

    Yes you can fix some minor issues, but don't take it too far. I've seen a lot of apps mess up by making dialogs and certain controls do things they weren't intended, and they fail horribad on the next version of windows that did things slightly different or need massive rework for the next UI change.


    and btw. asteroids hit earth EVERY DAY !
    Luckily usually too small to do more damage than a small dent in a plate of pudding. But even fist to football sized asteroids hit earth regularly.

  13. #13
    Join Date
    Jul 2002
    Posts
    2,543

    Re: CStatic control flicker only when running with Windows Classic theme

    Quote Originally Posted by OReubens View Post
    But even fist to football sized asteroids hit earth regularly.
    Fist sized asteroid hit my head 15 years ago, and I started to write C++ programs, instead of good old Visual Basic.

  14. #14
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: CStatic control flicker only when running with Windows Classic theme

    Quote Originally Posted by Alex F View Post
    Fist sized asteroid hit my head 15 years ago, and I started to write C++ programs, instead of good old Visual Basic.
    They also cause folks to want to 'fix' minor UI display issues.

  15. #15
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,234

    Re: CStatic control flicker only when running with Windows Classic theme

    Quote Originally Posted by Arjay View Post
    They also cause folks to want to 'fix' minor UI display issues.
    ...while fixing major UI display issues needs much bigger asteroids.
    Last edited by ovidiucucu; November 22nd, 2013 at 03:01 AM.
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured