在1000个表单中将多个标签设置为透明?

14

我使用了DevExpress来美化我的软件,但是发现标签不透明,导致它们有灰色背景。

因为表单很多,所以我想知道是否有自动将标签设置为透明的方法。

我之前做过类似的事情,在表单上的DevExpress控件中设置了LookAndFeel.NativeStyle = True属性,然后我使用Grep搜索来将所有dfm表单中的该属性替换为False。然而,在标签的情况下,透明属性不存在。

谢谢。


你是否承诺在IDE中完成这个任务,或者你是否可以接受在运行时完成它? - RobertFrank
罗伯特,那太棒了 - 我是指在运行时。我该怎么做才能实现这个结果? - Rosenberg
与其在设计时做这件事,您可以在运行时更容易地完成。 - David Heffernan
遍历表单中的所有控件,每当找到一个标签时,根据需要更改属性。 - David Heffernan
2
一个问题能够激发出多个聪明的解决方案,这是非常棒的。 - Rob Kennedy
显示剩余3条评论
6个回答

15
全局 Screen 变量跟踪所有表单:
procedure MakeLabelsTransparent(AParent: TWinControl);
var
  I: Integer;
begin
  with AParent do
    for I := 0 to ControlCount - 1 do
      if Controls[I] is TLabel then
        TLabel(Controls[I]).Transparent := True
      else if Controls[I] is TWinControl then
        MakeLabelsTransparent(TWinControl(Controls[I]));
end;

procedure TMainForm.ActiveFormChange(Sender: TObject);
begin
  with Screen do
    if (ActiveCustomForm <> nil) and (ActiveCustomForm.Tag = 0) then
    begin
      MakeLabelsTransparent(ActiveCustomForm);
      ActiveCustomForm.Tag := 1;
    end;
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  Screen.OnActiveFormChange := ActiveFormChange;
end;

如果你必须要对特定表单使用Tag属性,那么省略这个检查也不会使程序变得太慢。


+1 真是太聪明了,NGLN。我之前不知道如何使用 OnActiveFormChange。 - RobertFrank
完美,同时在所有 MDI 窗体上工作,简直完美...谢谢。 - Rosenberg
2
标签不必由它们所在的窗体拥有。通过递归遍历控件的索引属性会更加健壮。 - David Heffernan

9
对于这种任务,GExperts包含“设置组件属性”工具:
该工具在后台等待,直到您编译项目。然后,它会扫描当前项目的表单以检查具有某些属性的组件,并将这些属性更改为定义的值。此工具可用于在编译应用程序之前停用数据集或数据库连接,但也可以用于任何类似情况。要激活扫描,请在GExperts配置屏幕中启用此专家旁边的复选框。
它还可用于设置尚未出现在DFM中的属性,仅需要一个额外的GExpert配置条目和重新编译即可。
我刚刚测试过,效果符合预期。

我建议这样做,因为有可能某一天你想要一个非透明的标签,并且你可以进行不同的设置。 - Warren P
绝对是第二好的解决方案。我之前不知道这个。非常感谢。 - Rosenberg

5

在设计时,您可以解析所有的 .dfm 文件,然后添加

  Transparent = True

在任何一行后面添加

  object MyLabel : TLabel

行。

在运行时,您可以重写 TCustomForm.DoCreateTCustomFrame.Create 方法,如下所示:

type
  THookedForm = class(TCustomForm)
    procedure HookedDoCreate;
  end;

  THookedFrame = class(TCustomFrame)
    constructor Create(AOwner: TComponent); override;
  end;

var
  PatchForm, OriginalForm: TPatchEvent;
  PatchPositionForm: PPatchEvent = nil;
  PatchFrame, OriginalFrame: TPatchEvent;
  PatchPositionFrame: PPatchEvent = nil;

procedure PatchCreate;
var ov: cardinal;
begin
  // hook TForm:
  PatchPositionForm := PPatchEvent(@THookedForm.DoCreate);
  OriginalForm := PatchPositionForm^;
  PatchForm.Jump := $E9; // Jmp opcode
  PatchForm.Offset := PtrInt(@THookedForm.HookedDoCreate)-PtrInt(PatchPositionForm)-5;
  if not VirtualProtect(PatchPositionForm, 5, PAGE_EXECUTE_READWRITE, @ov) then
    RaiseLastOSError;
  PatchPositionForm^ := PatchForm; // enable Hook
  // hook TFrame:
  PatchPositionFrame := PPatchEvent(@TCustomFrame.Create);
  OriginalFrame := PatchPositionFrame^;
  PatchFrame.Jump := $E9; // Jmp opcode
  PatchFrame.Offset := PtrInt(@THookedFrame.Create)-PtrInt(PatchPositionFrame)-5;
  if not VirtualProtect(PatchPositionFrame, 5, PAGE_EXECUTE_READWRITE, @ov) then
    RaiseLastOSError;
  PatchPositionFrame^ := PatchFrame; // enable Hook
end;

{ THookedForm }

procedure THookedForm.HookedDoCreate;
var i: integer;
begin
  // enumerate all labels, then set Transparent := true
  for i := 0 to Components.Count-1 do
    if Components[i] is TLabel then
      TLabel(Components[i]).Transparent := true;
  DoCreate; // call initial code
end;

{ THookedFrame }

constructor THookedFrame.Create(AOwner: TComponent);
var i: integer;
begin
  // enumerate all labels, then set Transparent := true
  for i := 0 to Components.Count-1 do
    if Components[i] is TLabel then
      TLabel(Components[i]).Transparent := true;
  inherited Create(AOwner); // call normal constructor
end;

....

initialization
  PatchCreate;

@Warren 这是我的第一个解决方案。由于 OP 要求运行时解决方案,因此我提供了一个符合此要求的通用解决方案。 - Arnaud Bouchez
这是一个很好的解决方案! :-) 读了我的评论,我发现自己说的话毫无意义。 - Warren P

5

一条相关的提示(我总是忘记使用这个方便的功能):

  1. 按照您想要的方式配置标签;
  2. 在表单上选择它;
  3. 转到组件/创建组件模板;
  4. 然后可以为模板命名:

enter image description here

从此以后,该模板将作为新的组件类型出现在您的工具面板中,并带有您喜欢的设置。

(是的,我知道这不会改变当前标签)


不错,我会在一个默认设置已经固定的自定义组件上尝试这个。 - David Heffernan
1
虽然这并没有提供问题的解决方案,但它确实非常有用。我从来没有想过点击菜单“创建组件模板”。谢谢! - Rosenberg

1

您可以将BackColor属性设置为Color.Transparent


4
我会尽力进行翻译,以下是需要翻译的内容:好的,我认为OP想要设置Label.Transparent:=True,但真正的问题在于如何自动化这个变化。 - David Heffernan

1
以下应该可以工作:transparent-property 仅在值不是默认值时才出现在 DFM 文件中。因此,您可以使用 Grep 搜索,在 "=TLabel" 后面的下一行中插入 "Transparent=TRUE"。我自己没有尝试过这个方法,但这很容易尝试...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接