TLabel 和 TGroupbox 标题在调整大小时闪烁
- 所以,我有一个应用程序加载不同的插件并创建一个 每个 TPageControl 上都有一个新选项卡。
- 每个 DLL 都有一个与其关联的 TForm。
- 创建表单时将其父级 hWnd 作为新的 TTabSheet。
由于就 VCL 而言,TTabSheets 不是表单的父级(不想使用动态 RTL 和其他语言制作的插件),我必须手动处理大小调整。我这样做如下:
<前><代码>变量 子句柄:DWORD; 开始 如果分配(pcMain.ActivePage) 那么 开始 ChildHandle := FindWindowEx(pcMain.ActivePage.Handle, 0, 'TfrmPluginForm', nil); 如果 ChildHandle > 0 那么 开始 SetWindowPos(ChildHandle, 0, 0, 0, pcMain.ActivePage.Width, pcMain.ActivePage.Height, SWP_NOZORDER + SWP_NOACTIVATE + SWP_NOCOPYBITS); 结尾; 结尾;
现在,我的问题是,当调整应用程序大小时,TGroupBoxes 内的所有 TGroupBox 和 TLabels 都会闪烁。不在 TGroupboxes 内的 TLabels 很好并且不会闪烁。
我尝试过的事情:
- WM_SETREDRAW,然后将
- TGroupBoxes 和 TLabels 上的 RedrawWindow ParentBackground 设置为 False
- DoubleBuffer := True
- LockWindowUpdate (是的,尽管我知道这是非常错误的 )
- 透明 := False (甚至覆盖 create 来编辑 ControlState)
有什么想法吗?
- So, I have an application that loads different plugins and creates a
new tab on a TPageControl for each one. - Each DLL has a TForm associated with it.
- The forms are created with their parent hWnd as the new TTabSheet.
Since the TTabSheets aren't a parent of the form as far as VCL is concerned (didn't want to use dynamic RTL, and plugins made in other languages) I have to handle resizes manually. I do this like below:
var ChildHandle : DWORD; begin If Assigned(pcMain.ActivePage) Then begin ChildHandle := FindWindowEx(pcMain.ActivePage.Handle, 0, 'TfrmPluginForm', nil); If ChildHandle > 0 Then begin SetWindowPos(ChildHandle, 0, 0, 0, pcMain.ActivePage.Width, pcMain.ActivePage.Height, SWP_NOZORDER + SWP_NOACTIVATE + SWP_NOCOPYBITS); end; end;
Now, my problem is that when the application is resized, all the TGroupBoxes and the TLabels inside the TGroupBoxes flicker. The TLabels that are not inside TGroupboxes are fine and don't flicker.
Things I've tried:
- WM_SETREDRAW followed by a RedrawWindow
- ParentBackground on the TGroupBoxes and TLabels set to False
- DoubleBuffer := True
- LockWindowUpdate (Yes, even though I know it's very very wrong)
- Transparent := False (even overriding create to edit ControlState)
Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我发现唯一有效的方法是使用
WS_EX_COMPOSITED
窗口样式。这是一个性能消耗大户,所以我只在调整大小循环时启用它。根据我的经验,使用内置控件,在我的应用程序中,仅在调整表单大小时才会发生闪烁。您应该首先执行快速测试,看看这种方法是否对您有帮助,只需将
WS_EX_COMPOSITED
窗口样式添加到所有窗口控件即可。如果这有效,您可以考虑下面更高级的方法:快速破解
例如,在
TForm
的OnShow
中调用此方法,传递表单实例。如果这有帮助,那么你真的应该更明智地实施它。我为您提供了我的代码的相关摘录,以说明我是如何做到这一点的。完整代码
这不会为您编译,但它应该包含一些有用的想法。
ControlEnumerator
是我的实用程序,用于将子控件的递归遍历转换为平面for
循环。请注意,我还使用了一个自定义拆分器,该拆分器在激活时调用 BeginSizing/EndSizing。另一个有用的技巧是使用
TStaticText
而不是TLabel
,当页面控件和面板有深度嵌套时,您偶尔需要这样做。我使用这段代码使我的应用程序 100% 无闪烁,但我花了很多年的时间进行实验才将其全部到位。希望其他人可以在这里找到有用的东西。
The only thing I have found to work well is to use the
WS_EX_COMPOSITED
window style. This is a performance hog so I only enable it when in a sizing loop. It is my experience that, with the built-in controls, in my app, flickering only occurs when resizing forms.You should first perform a quick test to see if this approach will help you by simply adding the
WS_EX_COMPOSITED
window style to all your windowed controls. If that works you can consider the more advanced approach below:Quick hack
Call this, for example, in the
OnShow
for yourTForm
, passing the form instance. If that helps then you really should implement it more discerningly. I give you the relevant extracts from my code to illustrate how I did that.Full code
This won't compile for you, but it should contain some useful ideas.
ControlEnumerator
is my utility to turn a recursive walk of the child controls into a flatfor
loop. Note that I also use a custom splitter that calls BeginSizing/EndSizing when it is active.Another useful trick is to use
TStaticText
instead ofTLabel
which you occasionally need to do when you have deep nesting of page controls and panels.I've used this code to make my app 100% flicker free but it took me ages and ages of experimenting to get it all in place. Hopefully others can find something of use in here.
使用 VCL 修复包,来自 安德烈亚斯·豪斯拉登。
另外:不要指定
SWP_NOCOPYBITS
标志,并设置 PageControl 的DoubleBuffered
:Use the VCL Fix Pack from Andreas Hausladen.
Additionally: do not specify the
SWP_NOCOPYBITS
flag, and setDoubleBuffered
of the PageControl:将其放在表单(界面)上方,或者将其全部放入新的最后一个单元中以包含:
将其放入实现部分,
对 TGroupBox 重复此步骤
Put above your form (interface) or put it all in a new last unit to include:
Put this in implementation part
repeat this step for TGroupBox
这是我在我的项目中成功用于多种表单的解决方案。它有点脏,因为它使用 WinAPI 函数。与大卫的回答相比,它不涉及性能损失。重点是覆盖窗体及其所有子窗口的
WM_ERASEBKGND
消息的消息处理程序,防止重复绘制到同一区域,从而导致闪烁。重要提示:如果您不想在侧面看到黑色条纹,则必须设置表单的
DoubleBuffered
属性!This is the solution I use with success in my project for a number of forms. It's a little bit dirty because it uses WinAPI functions. In comparison with David answer, it doesn't involve a performance penalty. The point is to overwrite the message handler for
WM_ERASEBKGND
messages for the form and all of its child windows, preventing repeated drawing to the same area, which causes flicker.Important note: The form's
DoubleBuffered
property must be set on if you don't want to see black stripes on the sides!