MFC app main window activation/deactivation painting issue

To reproduce this issue please follow these steps…

  1. Enable a non-Aero theme like Windows 7 Basic theme
  2. Create a new MFC application.
    image
  3. Please make sure you’ve selected “Windows 7” for visual style and colors.
  4. Also you might notice that the issue is only reproducible when the application runs for the first time on a machine. This is because the value of visual style is read from the registry. So please edit the code in CMainFrame constructor likewise…
    image
    Hard code the value to use “Windows 7” visual styling.
  5. Run the application.
  6. Try activating or deactivating
  7. You’ll see that the application title bar is not redrawn!

This is how the application looks like when deactivated…

image

This has been identified as a bug in MFC. This incorrect redrawing occurred under non-Aero themes only. We’ve found a workaround and the workaround is as follows…

Please derive a class from CMFCVisualManagerWindows7 and override OnNcActivate virtual method. For now lets call the class as CMyVisualManagerWindows7 derived from CMFCVisualManagerWindows7.

class CMyVisualManagerWindows7 : public CMFCVisualManagerWindows7
{
    DECLARE_DYNCREATE(CMyVisualManagerWindows7)
    virtual BOOL OnNcActivate(CWnd* pWnd, BOOL bActive)
    {
        if (pWnd->GetSafeHwnd() != NULL)
        {
            CMFCRibbonBar* pBar = GetRibbonBar(pWnd);
            if (pBar->GetSafeHwnd() == NULL || !pBar->IsWindowVisible() || !pBar->IsReplaceFrameCaption())
            {
                return FALSE;
            }
        }
        return CMFCVisualManagerWindows7::OnNcActivate(pWnd, bActive);
    }
};

Also in MainFrame.cpp please make sure CMyVisualManagerWindows7 is instantiated instead of its parent class CMFCVisualManagerWindows7 so that the derived class implementation of OnNcActivate takes effect.

case ID_VIEW_APPLOOK_WINDOWS_7:
              CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMyVisualManagerWindows7));
              CDockingManager::SetDockingMode(DT_SMART);
              break;

This fixed the issue. Just in case you are facing a similar issue…