Click here to Skip to main content
15,891,136 members
Articles / Desktop Programming / MFC
Article

A flicker issue in MDI applications

Rate me:
Please Sign up or sign in to vote.
3.10/5 (13 votes)
23 Aug 20051 min read 178K   1.4K   38   30
Provides a fix to the flicker problem in MDI applications.

Sample Image - MDIFlickDemo.jpg

Issue

This article illustrates how to fix a common flicker problem in MDI applications when you create or activate an MDI child and an application is in maximized state. You catch a glimpse of the new activated MDI child shown at the picture above.

To reproduce the problem:

  1. Create a new MFC MDI application project.
  2. Run and maximize the application.
  3. In maximized state, create a few MDI children and try switching between them.

When you create a new or activate an inactive window, you will see the flicker.

Workaround

The solution to the problem is very simple. The flicker comes from drawing the caption, the frame and the client area of the restored MDI child. To eliminate it, override "WindowProc" in your class derived from CMDIChildWnd. For the non-client area, filter WM_NCPAINT message, and for the client area, handle WM_SIZE message like this:

if(message==WM_SIZE) // client area
{
    if(wParam==SIZE_MAXIMIZED && pChildFrame==this)
    // active and maximized
        return CMDIChildWnd::WindowProc(message, wParam, lParam);

    SetRedraw(FALSE); // disable drawing
    LRESULT ret = CMDIChildWnd::WindowProc(message, 
                   wParam, lParam); // default Window procedure
    SetRedraw(); // enable drawing
    return  ret;
}

In the previous version of this article I also filtered message 174. Ignoring this message prevents drawing non-themed caption buttons. The picture of the buttons looks like this:

Caption Buttons

This message is also sent when a window is restored. Now drawing for restored windows is disabled, so we don't need "message==174" in the "if" statement anymore.

I have also added if(message==WM_NCPAINT || message==WM_SIZE) as a first line in the window procedure. It prevents from assertion in objcore.cpp (AfxAssertValidObject) when you try to close the MDI child, the view is derived from CHtmlView and the active configuration is "Debug".

So the workaround code looks like this:

LRESULT CChildFrame::WindowProc(UINT message, 
                       WPARAM wParam, LPARAM lParam) 
{
    if(message==WM_NCPAINT || message==WM_SIZE)
    {
        BOOL bMax;
        CMDIFrameWnd* pParentFrame = (CMDIFrameWnd*)GetParentFrame();
        if(pParentFrame)
        {
            CMDIChildWnd* pChildFrame = pParentFrame->MDIGetActive(&bMax);
            if(bMax)
            {    
                if(message==WM_NCPAINT) // non client area
                    return 0;
                    
                if(message==WM_SIZE) // client area
                {
                    if(wParam==SIZE_MAXIMIZED && 
                       pChildFrame==this) // active and maximized
                      return CMDIChildWnd::WindowProc(message, wParam, lParam);

                    SetRedraw(FALSE);
                    LRESULT ret = 
                      CMDIChildWnd::WindowProc(message, wParam, lParam);
                    SetRedraw();
                    return  ret;
                }
            }
        }
    }
    return CMDIChildWnd::WindowProc(message, wParam, lParam);
}

A demo application

Check/uncheck the "FIX" button to enable/disable the fix code.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionA workaround solution for the flickering problem Pin
szorik31-Jul-11 22:55
szorik31-Jul-11 22:55 
QuestionMaximize window Pin
manojv18-Oct-07 0:51
manojv18-Oct-07 0:51 
GeneralSolution for Managed Code Pin
tonyt8-Jul-07 18:47
tonyt8-Jul-07 18:47 
GeneralKeyboard navigation Pin
Marcus Deecke27-Apr-07 1:26
Marcus Deecke27-Apr-07 1:26 
AnswerThe Real solutions Pin
Ali Rafiee9-Feb-06 5:30
Ali Rafiee9-Feb-06 5:30 
GeneralAlternative Pin
Gast12824-Aug-05 22:10
Gast12824-Aug-05 22:10 
GeneralSmall correction Pin
Andrzej Markowski14-Aug-05 7:44
Andrzej Markowski14-Aug-05 7:44 
GeneralA correct version of the code Pin
Andrzej Markowski13-Aug-05 10:04
Andrzej Markowski13-Aug-05 10:04 
GeneralGood enough to say, "Seemed to have solved the flickering issue." Pin
WREY13-Aug-05 11:51
WREY13-Aug-05 11:51 
GeneralCase where code doesnt work Pin
picazo23-Jan-06 12:14
picazo23-Jan-06 12:14 
GeneralRe: Case where code doesnt work Pin
Andrzej Markowski26-Jan-06 16:17
Andrzej Markowski26-Jan-06 16:17 
QuestionWouldn't LockWindowUpdate be better and easier? Pin
Member 218767811-Aug-05 4:45
Member 218767811-Aug-05 4:45 
AnswerRe: Wouldn't LockWindowUpdate be better and easier? Pin
robrich12-Aug-05 4:36
robrich12-Aug-05 4:36 
GeneralIn C# Pin
robrich10-Aug-05 21:05
robrich10-Aug-05 21:05 
GeneralRe: In C# Pin
robrich12-Aug-05 4:26
robrich12-Aug-05 4:26 
GeneralRe: In C# Pin
Tim McCurdy30-Aug-05 4:28
Tim McCurdy30-Aug-05 4:28 
GeneralRe: In C# Pin
robrich30-Aug-05 6:22
robrich30-Aug-05 6:22 
GeneralRe: In C# Pin
robrich30-Aug-05 6:30
robrich30-Aug-05 6:30 
GeneralRe: In C# Pin
Tim McCurdy30-Aug-05 16:01
Tim McCurdy30-Aug-05 16:01 
GeneralRe: In C# [modified] Pin
Ming Liu21-Jul-06 17:55
Ming Liu21-Jul-06 17:55 
The flicker bothered me too, so based on this article, I played around a little bit more. I haven't found the solution yet, but here is some information which may help somebody finding a solution:

The fact I observed is that, when the new child form is activated, old child form is deactivated. After the Deactivate event of the old child, there are always two resize events: first the new child form is maximaized (I don't understand why we need this one), then the old form is set to normal size. After Activated event of the new child form, there are two more resize events for the new child form (I don't know why we need two), both with windowstate-maximized.

It is the resizing of the old child to normal size who created flicker!

If I skip the resize event in child form by overriding WndProc (m.Msg == 5), I could get rid of the flicker. However, when I normal-size the child form (by clicking the double-window icon on the top-right corner), the old child form remains maximized - that's because we didn't normal-size it when deactivated.

Please let me know if you find a solution.

BTW, while we are on MDI topic, anybody ran into "Error creating window handle" problem? If you don't know what it is, google it and you will see a lot of discussions on it. In my case, I don't have too many handles (I only have about 210). I have two MDI appliactions, one doesn't have this problem (which could sometimes create up to 1200 handles), but the other one with only 211 handles created and it throws this error when trying to create the second instance of the same child form. It's inconsistent though, most of the time, I get this error when trying to create the second instance of a child form, sometimes I could get as many as 10 instances. I believe my memory is big enough. Any clue? If you have a solution for this, please let me know. Thank you very much!




-- modified at 23:57 Friday 21st July, 2006
GeneralRe: In C# Pin
Ivo Yueh20-Oct-06 11:39
Ivo Yueh20-Oct-06 11:39 
GeneralRe: In C# Pin
laurent p15-May-07 19:41
laurent p15-May-07 19:41 
GeneralRe: Infragistics TabbedMDIManager flicker Pin
Mark Treveil1-Jul-07 10:56
Mark Treveil1-Jul-07 10:56 
GeneralMy friend flicker Pin
RancidCrabtree10-Aug-05 13:10
RancidCrabtree10-Aug-05 13:10 
GeneralSometimes it still flickers. Pin
WREY4-Aug-05 6:57
WREY4-Aug-05 6:57 

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

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