【发布时间】: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