MDI 应用程序中的闪烁问题






3.10/5 (13投票s)
2005年8月3日
1分钟阅读

181807

1423
提供了一个解决MDI应用程序中闪烁问题的方案。
Issue
本文说明了如何在MDI应用程序中修复一个常见的闪烁问题,当您创建或激活一个MDI子窗口并且应用程序处于最大化状态时,会出现此问题。 您会瞥见上面图片中显示的新激活的MDI子窗口。
重现问题的方法
- 创建一个新的MFC MDI应用程序项目。
- 运行并最大化应用程序。
- 在最大化状态下,创建几个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
。 忽略此消息会阻止绘制非主题化的标题按钮。 按钮的图片如下所示
当窗口恢复时也会发送此消息。 现在恢复窗口的绘制已被禁用,因此不再需要在“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”按钮以启用/禁用修复代码。