delphi – TLabel和TGroupbox Captions Flicker on Resize

前端之家收集整理的这篇文章主要介绍了delphi – TLabel和TGroupbox Captions Flicker on Resize前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
>所以,我有一个应用程序加载不同的插件并创建一个
每个TPageControl上的新选项卡。
>每个DLL都有一个与它相关联的TForm。
>这些表单是用他们的父hWnd作为新的TTabSheet创建的。
>由于TTabSheets不是VCL的父表单(不想使用动态RTL和其他语言的插件),因此我必须手动调整大小。我这样做如下:
  1. var
  2. ChildHandle : DWORD;
  3. begin
  4. If Assigned(pcMain.ActivePage) Then
  5. begin
  6. ChildHandle := FindWindowEx(pcMain.ActivePage.Handle,'TfrmPluginForm',nil);
  7. If ChildHandle > 0 Then
  8. begin
  9. SetWindowPos(ChildHandle,pcMain.ActivePage.Width,pcMain.ActivePage.Height,SWP_NOZORDER + SWP_NOACTIVATE + SWP_NOCOPYBITS);
  10. end;
  11. end;

现在,我的问题是当应用程序调整大小时,TGroupBox中的所有TGroupBox和TLabels闪烁。不在TGroupBox内的TLabel很好,不闪烁。

我试过的事情

> WM_SETREDRAW,后跟一个RedrawWindow
> ParentBackground在TGroupBoxes和TLabels设置为False
> DoubleBuffer:= True
> LockWindowUpdate(是的,即使我知道这是非常错误的)
> Transparent:= False(甚至覆盖创建来编辑ControlState)

有任何想法吗?

解决方法

我发现唯一可以正常工作的是使用WS_EX_COMPOSITED窗口样式。这是一个性能猪,所以我只是在大小循环中启用它。我的经验是,使用内置的控件,在我的应用程序中,只有在调整窗体大小时才会发生闪烁。

您应该首先执行一个快速测试,看看这种方法是否可以帮助您,只需将WS_EX_COMPOSITED窗口样式添加到所有窗口控件。如果这样工作,你可以考虑下面更先进的方法

快攻

  1. procedure EnableComposited(WinControl: TWinControl);
  2. var
  3. i: Integer;
  4. NewExStyle: DWORD;
  5. begin
  6. NewExStyle := GetWindowLong(WinControl.Handle,GWL_EXSTYLE) or WS_EX_COMPOSITED;
  7. SetWindowLong(WinControl.Handle,GWL_EXSTYLE,NewExStyle);
  8.  
  9. for i := 0 to WinControl.ControlCount-1 do
  10. if WinControl.Controls[i] is TWinControl then
  11. EnableComposited(TWinControl(WinControl.Controls[i]));
  12. end;

调用这个,例如,在您的TForm的OnShow中,传递表单实例。如果这有帮助,那么你真的应该更明智地实施它。我向我提供了我的代码中的相关摘录,以说明我是如何做到的。

代码

  1. procedure TMyForm.WMEnterSizeMove(var Message: TMessage);
  2. begin
  3. inherited;
  4. BeginSizing;
  5. end;
  6.  
  7. procedure TMyForm.WMExitSizeMove(var Message: TMessage);
  8. begin
  9. EndSizing;
  10. inherited;
  11. end;
  12.  
  13. procedure SetComposited(WinControl: TWinControl; Value: Boolean);
  14. var
  15. ExStyle,NewExStyle: DWORD;
  16. begin
  17. ExStyle := GetWindowLong(WinControl.Handle,GWL_EXSTYLE);
  18. if Value then begin
  19. NewExStyle := ExStyle or WS_EX_COMPOSITED;
  20. end else begin
  21. NewExStyle := ExStyle and not WS_EX_COMPOSITED;
  22. end;
  23. if NewExStyle<>ExStyle then begin
  24. SetWindowLong(WinControl.Handle,NewExStyle);
  25. end;
  26. end;
  27.  
  28. function TMyForm.SizingCompositionIsPerformed: Boolean;
  29. begin
  30. //see The Old New Thing,Taxes: Remote Desktop Connection and painting
  31. Result := not InRemoteSession;
  32. end;
  33. procedure TMyForm.BeginSizing;
  34. var
  35. UseCompositedWindowStyleExclusively: Boolean;
  36. Control: TControl;
  37. WinControl: TWinControl;
  38. begin
  39. if SizingCompositionIsPerformed then begin
  40. UseCompositedWindowStyleExclusively := Win32MajorVersion>=6;//XP can't handle too many windows with WS_EX_COMPOSITED
  41. for Control in ControlEnumerator(TWinControl) do begin
  42. WinControl := TWinControl(Control);
  43. if UseCompositedWindowStyleExclusively then begin
  44. SetComposited(WinControl,True);
  45. end else begin
  46. if WinControl is TPanel then begin
  47. TPanel(WinControl).FullRepaint := False;
  48. end;
  49. if (WinControl is TCustomGroupBox) or (WinControl is TCustomRadioGroup) or (WinControl is TCustomGrid) then begin
  50. //can't find another way to make these awkward customers stop flickering
  51. SetComposited(WinControl,True);
  52. end else if ControlSupportsDoubleBuffered(WinControl) then begin
  53. WinControl.DoubleBuffered := True;
  54. end;
  55. end;
  56. end;
  57. end;
  58. end;
  59.  
  60. procedure TMyForm.EndSizing;
  61. var
  62. Control: TControl;
  63. WinControl: TWinControl;
  64. begin
  65. if SizingCompositionIsPerformed then begin
  66. for Control in ControlEnumerator(TWinControl) do begin
  67. WinControl := TWinControl(Control);
  68. if WinControl is TPanel then begin
  69. TPanel(WinControl).FullRepaint := True;
  70. end;
  71. UpdateDoubleBuffered(WinControl);
  72. SetComposited(WinControl,False);
  73. end;
  74. end;
  75. end;
  76.  
  77. function TMyForm.ControlSupportsDoubleBuffered(Control: TWinControl): Boolean;
  78. const
  79. NotSupportedClasses: array [0..1] of TControlClass = (
  80. TCustomForm,//general policy is not to double buffer forms
  81. TCustomRichEdit//simply fails to draw if double buffered
  82. );
  83. var
  84. i: Integer;
  85. begin
  86. for i := low(NotSupportedClasses) to high(NotSupportedClasses) do begin
  87. if Control is NotSupportedClasses[i] then begin
  88. Result := False;
  89. exit;
  90. end;
  91. end;
  92. Result := True;
  93. end;
  94.  
  95. procedure TMyForm.UpdateDoubleBuffered(Control: TWinControl);
  96.  
  97. function ControlIsDoubleBuffered: Boolean;
  98. const
  99. DoubleBufferedClasses: array [0..2] of TControlClass = (
  100. TMyCustomGrid,//flickers when updating
  101. TCustomListView,//flickers when updating
  102. TCustomStatusBar//drawing infidelities,e.g. my main form status bar during file loading
  103. );
  104. var
  105. i: Integer;
  106. begin
  107. if not InRemoteSession then begin
  108. //see The Old New Thing,Taxes: Remote Desktop Connection and painting
  109. for i := low(DoubleBufferedClasses) to high(DoubleBufferedClasses) do begin
  110. if Control is DoubleBufferedClasses[i] then begin
  111. Result := True;
  112. exit;
  113. end;
  114. end;
  115. end;
  116. Result := False;
  117. end;
  118.  
  119. var
  120. DoubleBuffered: Boolean;
  121.  
  122. begin
  123. if ControlSupportsDoubleBuffered(Control) then begin
  124. DoubleBuffered := ControlIsDoubleBuffered;
  125. end else begin
  126. DoubleBuffered := False;
  127. end;
  128. Control.DoubleBuffered := DoubleBuffered;
  129. end;
  130.  
  131. procedure TMyForm.UpdateDoubleBuffered;
  132. var
  133. Control: TControl;
  134. begin
  135. for Control in ControlEnumerator(TWinControl) do begin
  136. UpdateDoubleBuffered(TWinControl(Control));
  137. end;
  138. end;

这不会为你编译,但它应该包含一些有用的想法。 ControlEnumerator是我的实用工具,用于将子控件的递归步调转换为平面循环。请注意,我还使用一个自定义分割器,当它处于活动状态时调用BeginSizing / EndSizing。

另一个有用的技巧是使用TStaticText而不是TLabel,当您拥有深度嵌页的页面控件和面板时,您偶尔需要执行此操作。

我使用这个代码使我的应用程序100%闪烁免费,但它花了我的年龄和年龄的实验,以获得它所有到位。希望别人能在这里找到有用的东西。

猜你在找的Delphi相关文章