Setting multiple labels to transparent across 1.000 forms?
Asked Answered
R

6

14

I skinned my software with Devexpress and I found that the labels were non-transparent causing them to have grey background.

There's just endless forms, so I was wondering whether there was a way to do this task (of setting labels to transparent) automatically.

I did a similar thing earlier, the Devexpress controls on the form had LookAndFeel.NativeStyle = True, I used Grep Search to replace it to False on all dfm forms. In the label's case however, the transparent property is not present.

Thank you.

Rosel answered 25/5, 2011 at 15:2 Comment(8)
Are you committed to doing this in the IDE, or would you be okay with it being done at run-time?Barbule
Robert, that would be fantastic - at run time I mean. What can I do to achieve that result?Rosel
Rather than doing it at design time you could perhaps more easily do this at runtimeNobility
Iterate across all the controls in the form and whenever you find a label change the properties as desiredNobility
I've used GExperts for a massive search and replace. Can you use it to locate all occurences of TLabel in the dfm's and replace by TLabel<CR>Transparent=True - I dont know how to declare the <CR> bit though.Haar
In Delphi XE the default value for TLabel.Transparent is true. So if it doesn't appear in the DFM, it should already be OK. You have tagged three Delphi versions - which one has the problem?Sukin
Delphi 7, I use XE as well, since there are multiple projects but for this one only 7 will do.Rosel
+1 for a question inspiring several clever solutions.Sturrock
K
15

The global Screen variable keeps track of all forms:

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;

And if you have to use the Tag property for a particular form, then omit this check: it wouldn't really get that much slower.

Kimes answered 25/5, 2011 at 15:45 Comment(3)
+1 Ingenious, NGLN. I wasn't aware of how to use OnActiveFormChange.Barbule
Perfect, work on all MDI forms simultaneously, simply perfect... Thank you.Rosel
Labels need not be owned by the form in which they live. It would be more robust to recursively walk the Controls indexed property.Nobility
T
9

For this type of task, GExperts contains the Set Component Properties tool:

This tool waits in the background until you compile a project. It then scans the current project's forms to check for components with certain properties and changes those properties to a defined value. This tool is useful to deactivate datasets or database connections before you compile your applications, but it can be used for any similar situations as well. To activate the scanning, enable the checkbox next to this expert in the GExperts Configuration screen.

It can be used to set a property which is not yet in the DFM as well, and only requires one additional entry in the GExpert configuration, and a recompile.

I have just tested it and it works as expected.

Trestlework answered 25/5, 2011 at 15:54 Comment(2)
I recommend this as it can be possible that some day you want a non-transparent label, and you could set it differently.Segregationist
Definitely second best solution. I had no idea of this. Thanks a million.Rosel
A
5

At design time, you can just parse all .dfm then add the

  Transparent = True

line just after any

  object MyLabel : TLabel

line.

At runtime, you may override the TCustomForm.DoCreate and TCustomFrame.Create methods, as such:

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;
Alphabetical answered 25/5, 2011 at 15:38 Comment(2)
@Warren It's my first solution. And the OP asked for a run-time solution, so I gave one generic solution of this request.Alphabetical
This is a good solution! :-) Reading my comment I see I'm making NO sense.Segregationist
C
5

A related tip (I always forget to make use of this handy feature):

  1. Configure the label the way you want to have it;
  2. Select it on the form;
  3. Go to Component/Create component template;
  4. You can then a name for the template:

enter image description here

From then on, the template appears as a new component type in your tool palette, with the settings that you prefer.

(Yeah, I know this doesn't change current labels)

Cheree answered 25/5, 2011 at 21:24 Comment(2)
nice, will try this out on one of my custom components whose defaults are set in stoneNobility
Although this doesn't provide a solution to the question it's really useful. I never once thought about clicking the menu 'Create component template'. Thanks!Rosel
P
1

You can set the BackColor property to Color.Transparent.

Precaution answered 25/5, 2011 at 15:6 Comment(1)
Well, I think OP wants to set Label.Transparent := True but the real issue here is how to automate the changeNobility
A
1

The following should work: the transparent-property is present in the DFM-file only if the value is not the default. So you can us a Grep-Search to insert the "Transparent=TRUE" just in the next line after the "=TLabel". I have not tried this myself, but it is easy to try...

Acevedo answered 25/5, 2011 at 15:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.