我有一个使用WTL 8.1开发的Windows XP SP3 VS2008 C ++应用程序。我的应用程序包含一个选项卡控件,在调整应用程序边框大小时闪烁。
我的窗口层次结构如下所示:
CFrameWindowImpl CMainFrm
|-CSplitterWindow Splitter
|-CTabView Configuration Tabs
| |-CDialogImpl Configuration View 1
| |-CDialogImpl Configuration View 2
| |-CDialogImpl Configuration View 3
|-CDialogImpl Control View
我正在尝试的解决方案是使CFrameWindowImpl
派生类使用WS_EX_COMPOSITED
样式,其下的所有窗口都使用WS_EX_TRANSPARENT
样式。不幸的是,这使得选项卡控件按钮显示为空黑条,并且任何配置视图的控件都根本不显示。
如果我删除了WS_EX_COMPOSITED
和WS_EX_TRANSPARENT
样式,表单会正常显示,但CTabView
及其下方的所有内容在调整大小时都会出现可怕的情况。
我需要更改什么才能消除闪烁并正确绘制控件?
谢谢, PaulH
编辑:
搞定了。我根据Mark Ransom的建议删除了所有WS_EX_TRANSPARENT
个样式。我将WS_EX_COMPOSITED
样式仅放在上 CTabCtrl
(包含在CTabView
中)。其他控件根据需要通过WTL::CDoubleBufferImpl<>
获得双缓冲。
答案 0 :(得分:2)
MSDN中没有提到的是桌面窗口管理器 - 在Windows Vista和7上挂钩窗口绘画的组件,用于执行获得空气玻璃效果所需的桌面组合 - 不实现WS_EX_COMPOSITED。
这意味着你在XP上使用这种风格所做的所有工作注定会在Vista或更高版本上变得无关紧要。
WS_EX_COMPOSITED的另一个问题 - 以及它为什么是可选样式而不是XP上的默认值:双缓冲只捕获在父窗口的BeginPaint / EndPaint块期间执行的绘制。很多甚至是标准控件都在WM_PAINT处理程序之外执行绘制,因此后备缓冲区只能部分绘制。
可悲的是,结果是,在本机API应用程序中“消除”闪烁的唯一方法是尝试将其最小化:如果您没有重叠控件,WS_CLIPCHILDREN和WS_CLIPSIBLINGS可以提供帮助 - 确保每个控件的区域仅绘制一次。并确保主对话框不会在WM_ERASEBKGND中执行任何填充
答案 1 :(得分:1)
窗口闪烁,因为它在绘制之前会被删除。要消除这种情况,您需要完全禁用窗口的擦除并使用双缓冲 - 将窗口内容绘制到位图中,然后将位图复制到窗口。因为位图包含整个内容,包括背景,所以不再需要擦除。
看起来WS_EX_COMPOSITED将自动处理双缓冲,但您仍可能需要使用NULL背景画笔和/或处理WM_ERASEBKGND消息。
答案 2 :(得分:0)
根据我的经验,对于包含子控件的任何东西都不可能使用双缓冲(除非它们都完全支持WM_PRINT,但大多数都不支持)。