65.9K
CodeProject 正在变化。 阅读更多。
Home

MDI 应用程序中的闪烁问题

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.10/5 (13投票s)

2005年8月3日

1分钟阅读

viewsIcon

181807

downloadIcon

1423

提供了一个解决MDI应用程序中闪烁问题的方案。

Sample Image - MDIFlickDemo.jpg

Issue

本文说明了如何在MDI应用程序中修复一个常见的闪烁问题,当您创建或激活一个MDI子窗口并且应用程序处于最大化状态时,会出现此问题。 您会瞥见上面图片中显示的新激活的MDI子窗口。

重现问题的方法

  1. 创建一个新的MFC MDI应用程序项目。
  2. 运行并最大化应用程序。
  3. 在最大化状态下,创建几个MDI子窗口并尝试在它们之间切换。

当您创建新窗口或激活非活动窗口时,您会看到闪烁。

解决方法

解决这个问题的方法非常简单。 闪烁来自于绘制恢复的MDI子窗口的标题栏、边框和客户端区域。 为了消除它,请在从CMDIChildWnd派生的类中重写“WindowProc”。 对于非客户端区域,过滤WM_NCPAINT消息,对于客户端区域,像这样处理WM_SIZE消息

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;
}

在本文的早期版本中,我还过滤了消息174。 忽略此消息会阻止绘制非主题化的标题按钮。 按钮的图片如下所示

Caption Buttons

当窗口恢复时也会发送此消息。 现在恢复窗口的绘制已被禁用,因此不再需要在“if”语句中包含“message==174”了。

我还将if(message==WM_NCPAINT || message==WM_SIZE)作为窗口过程的第一行添加了进去。 这可以防止在objcore.cpp (AfxAssertValidObject) 中出现断言,当您尝试关闭MDI子窗口,视图是从CHtmlView派生的,并且活动配置是“Debug”时。

因此,解决方法代码如下所示

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);
}

一个演示应用程序

选中/取消选中“FIX”按钮以启用/禁用修复代码。

© . All rights reserved.