TLabel和TGroupbox Captions Flicker on Resize [英] TLabel and TGroupbox Captions Flicker on Resize

查看:249
本文介绍了TLabel和TGroupbox Captions Flicker on Resize的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


  • 所以,我有一个应用程序加载不同的插件,并在每一个TPageControl上创建一个
    的新标签。

  • 每个DLL都有一个与它相关联的TForm。

  • 表单是以其父级hWnd作为新的TTabSheet创建的。

  • 由于TTabSheets不是表单的父母就VCL而言(不想使用动态RTL,而以其他语言编写的插件)我必须手动处理大小。我这样做如下:

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


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

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.

我尝试过的东西:


  • WM_SETREDRAW后面是一个RedrawWindow

  • 设置为False的TGroupBoxes和TLabel上的ParentBackground
  • DoubleBuffer:= True

  • LockWindowUpdate(是的,即使我知道这是非常错误的

  • 透明:= False(甚至覆盖创建来编辑ControlState

  • 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)

任何想法?

推荐答案

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

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.

您应该首先执行一个快速测试,看看是否方法将通过简单地向所有窗口控件添加 WS_EX_COMPOSITED 窗口样式来帮助您。如果这样做,你可以考虑以下更先进的方法:

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:

快速入侵

procedure EnableComposited(WinControl: TWinControl);
var
  i: Integer;
  NewExStyle: DWORD;
begin
  NewExStyle := GetWindowLong(WinControl.Handle, GWL_EXSTYLE) or WS_EX_COMPOSITED;
  SetWindowLong(WinControl.Handle, GWL_EXSTYLE, NewExStyle);

  for i := 0 to WinControl.ControlCount-1 do
    if WinControl.Controls[i] is TWinControl then
      EnableComposited(TWinControl(WinControl.Controls[i]));
end;

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

Call this, for example, in the OnShow for your TForm, 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.

全部代码

procedure TMyForm.WMEnterSizeMove(var Message: TMessage);
begin
  inherited;
  BeginSizing;
end;

procedure TMyForm.WMExitSizeMove(var Message: TMessage);
begin
  EndSizing;
  inherited;
end;

procedure SetComposited(WinControl: TWinControl; Value: Boolean);
var
  ExStyle, NewExStyle: DWORD;
begin
  ExStyle := GetWindowLong(WinControl.Handle, GWL_EXSTYLE);
  if Value then begin
    NewExStyle := ExStyle or WS_EX_COMPOSITED;
  end else begin
    NewExStyle := ExStyle and not WS_EX_COMPOSITED;
  end;
  if NewExStyle<>ExStyle then begin
    SetWindowLong(WinControl.Handle, GWL_EXSTYLE, NewExStyle);
  end;
end;

function TMyForm.SizingCompositionIsPerformed: Boolean;
begin
  //see The Old New Thing, Taxes: Remote Desktop Connection and painting
  Result := not InRemoteSession;
end;
procedure TMyForm.BeginSizing;
var
  UseCompositedWindowStyleExclusively: Boolean;
  Control: TControl;
  WinControl: TWinControl;
begin
  if SizingCompositionIsPerformed then begin
    UseCompositedWindowStyleExclusively := Win32MajorVersion>=6;//XP can't handle too many windows with WS_EX_COMPOSITED
    for Control in ControlEnumerator(TWinControl) do begin
      WinControl := TWinControl(Control);
      if UseCompositedWindowStyleExclusively then begin
        SetComposited(WinControl, True);
      end else begin
        if WinControl is TPanel then begin
          TPanel(WinControl).FullRepaint := False;
        end;
        if (WinControl is TCustomGroupBox) or (WinControl is TCustomRadioGroup) or (WinControl is TCustomGrid) then begin
          //can't find another way to make these awkward customers stop flickering
          SetComposited(WinControl, True);
        end else if ControlSupportsDoubleBuffered(WinControl) then begin
          WinControl.DoubleBuffered := True;
        end;
      end;
    end;
  end;
end;

procedure TMyForm.EndSizing;
var
  Control: TControl;
  WinControl: TWinControl;
begin
  if SizingCompositionIsPerformed then begin
    for Control in ControlEnumerator(TWinControl) do begin
      WinControl := TWinControl(Control);
      if WinControl is TPanel then begin
        TPanel(WinControl).FullRepaint := True;
      end;
      UpdateDoubleBuffered(WinControl);
      SetComposited(WinControl, False);
    end;
  end;
end;

function TMyForm.ControlSupportsDoubleBuffered(Control: TWinControl): Boolean;
const
  NotSupportedClasses: array [0..1] of TControlClass = (
    TCustomForm,//general policy is not to double buffer forms
    TCustomRichEdit//simply fails to draw if double buffered
  );
var
  i: Integer;
begin
  for i := low(NotSupportedClasses) to high(NotSupportedClasses) do begin
    if Control is NotSupportedClasses[i] then begin
      Result := False;
      exit;
    end;
  end;
  Result := True;
end;

procedure TMyForm.UpdateDoubleBuffered(Control: TWinControl);

  function ControlIsDoubleBuffered: Boolean;
  const
    DoubleBufferedClasses: array [0..2] of TControlClass = (
      TMyCustomGrid,//flickers when updating
      TCustomListView,//flickers when updating
      TCustomStatusBar//drawing infidelities , e.g. my main form status bar during file loading
    );
  var
    i: Integer;
  begin
    if not InRemoteSession then begin
      //see The Old New Thing, Taxes: Remote Desktop Connection and painting
      for i := low(DoubleBufferedClasses) to high(DoubleBufferedClasses) do begin
        if Control is DoubleBufferedClasses[i] then begin
          Result := True;
          exit;
        end;
      end;
    end;
    Result := False;
  end;

var
  DoubleBuffered: Boolean;

begin
  if ControlSupportsDoubleBuffered(Control) then begin
    DoubleBuffered := ControlIsDoubleBuffered;
  end else begin
    DoubleBuffered := False;
  end;
  Control.DoubleBuffered := DoubleBuffered;
end;

procedure TMyForm.UpdateDoubleBuffered;
var
  Control: TControl;
begin
  for Control in ControlEnumerator(TWinControl) do begin
    UpdateDoubleBuffered(TWinControl(Control));
  end;
end;

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

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 flat for loop. Note that I also use a custom splitter that calls BeginSizing/EndSizing when it is active.

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

Another useful trick is to use TStaticText instead of TLabel which you occasionally need to do when you have deep nesting of page controls and panels.

我已经使用这个代码使我的应用程序100%闪烁,但它花了我的年龄和年龄的实验,以将其全部到位。希望别人可以在这里找到一些有用的东西。

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.

这篇关于TLabel和TGroupbox Captions Flicker on Resize的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆