【问题标题】:How to prevent black background under control before it is repainted?如何在重绘之前防止黑色背景受到控制?
【发布时间】:2020-05-12 12:45:47
【问题描述】:

屏幕截图是在窗口激活期间拍摄的。可以看出,一些控件首先被绘制为黑色背景。这些是 TCheckBox、TButton、TStringGrid。我希望控件下的黑色区域具有 clBtnFace 形式的颜色。我该如何解决这个问题?

编辑: 它发生在 VCL、Delphi 10.3.3、Windows 10 中。 通过窗口激活,我的意思是应用程序已经在运行并被最小化到任务栏。只有很多控件放在表单上。可以看到有 7 个 TPanel,大约 60 个 TEdits,在它们旁边有大约 60 个 TLabels 尚未绘制,其余的黑色背景是几个 TCheckBoxes,TButtons 和一个空的 TStringGrid。

用空表格进行测试,放置一个 TPanel 并在其上放置 300 个 TEdit,行为相同。因此,某些控件首先用黑色背景绘制是设计使然。那么如何将默认背景颜色更改为其他颜色呢?

编辑2: 使用 400 个 TPanel 进行测试。这些按预期绘制,没有将 TPanel 下的 Rect 设置为黑色。

编辑3: 不幸的是,1000 TPanel 的表单重绘速度足够慢,所以我能够观察到黑色背景。

这是我用来测试控件的代码:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Grids, Vcl.ExtCtrls, Vcl.StdCtrls;

const
  ControlsNum=800;
  Columns=40;

type
  TControlTestList=array of TButton;
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    var CList:TControlTestList;
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  i:integer;
  W,H:integer;
begin
  Self.Width:=1400;
  Self.Height:=800;
  W:=Self.ClientWidth div Columns;
  H:=Self.ClientHeight div (ControlsNum div Columns);
  SetLength(CList,ControlsNum);
  for i:=0 to ControlsNum-1 do
  begin
    CList[i]:=TButton.Create(Self);
    with (CList[i] as TButton) do
    begin
      Parent:=Self;
      Top:=H*(i div Columns);
      Left:=W*(i mod Columns);
      Width:=W;
      Height:=H;
      Caption:=IntToStr(i);
    end;
  end;

end;

procedure TForm1.FormDestroy(Sender: TObject);
var
  i:integer;
begin
  for i:=0 to Length(CList)-1 do FreeAndNil(CList[i]);
  SetLength(CList,0);
end;

end.

编辑4: 在 Windows 10 上:在任何类型的表单调整大小期间,控件下的黑色背景都不会出现。只有当窗口的极简化并把它带回来时。 在 Windows 8.1 上:调整窗体大小时也会出现黑色背景。

【问题讨论】:

  • VCL 还是 Firemonkey?哪个德尔福版本?哪个 Windows 版本?
  • 无论如何,这种外观不应该超过一秒的一小部分。当我不小心用完 RAM 并且整个系统变得非常缓慢时,我只会看到这种行为。如果您在系统正常时在应用程序中看到此行为,则说明您在应用程序中做错了,例如在激活表单时在 GUI 线程中做了大量工作。你真的不应该这样做。在单独的线程中工作,或者改为在FormCreate 中工作(或FormShow,如果这更适合您的情况)。
  • 您确定上述控件是先涂成黑色,然后再涂上实际内容吗?由于您的桌面背景为黑色,因此黑色区域可能只是您的应用程序窗口的一部分未绘制,因此在那里可以看到桌面背景。据我所知,Windows Vista 引入了不同的窗口组合系统方式,它能够仅渲染窗口的可见部分,这与在 Windows XP 和 odler 上不同,后者必须渲染整个窗口,然后渲染所有子窗口。
  • 是的,我确定控件首先被涂成黑色。
  • 请注意,您可以完全跳过 OnDestroy 处理程序。由于表单拥有按钮 (TButton.Create(Self)),因此当表单被销毁时,所有按钮都会被释放。动态数组由编译器管理,所以你也不需要SetLength(CList, 0)。另外,你尝试释放CList[Length(CList)],这是一个错误——最后一个按钮是CList[Length(CList) - 1] = CList[High(CList)]

标签: user-interface delphi background


【解决方案1】:

试试这个:

interface

  TForm1 = class(TForm)
  ....
  protected
    procedure CreateParams(var Params: TCreateParams); override;
  public
  ....
  end;


implementation

procedure TForm1.CreateParams(var Params: TCreateParams);
begin
    inherited;
    Params.WindowClass.hbrBackground := COLOR_BTNFACE + 1;
end;

【讨论】:

  • 您能否添加有关如何修改此代码的信息,以便获得自定义重绘颜色,即红色?
  • 用 CreateSolidBrush(clRed) 替换 COLOR_BTNFACE + 1
猜你喜欢
  • 2016-10-04
  • 2012-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-29
  • 2012-03-25
  • 2023-03-06
  • 2011-01-06
相关资源
最近更新 更多