Z Order of Controls in Delphi FireMonkey by Scott Hollows

emailx45

Местный
Регистрация
5 Май 2008
Сообщения
3,571
Реакции
2,438
Credits
573
Z Order of Controls in Delphi FireMonkey
Scott Hollows - 27/Dec/2016
[SHOWTOGROUPS=4,20]
Get and set the Z Order of controls at runtime in Delphi FireMonkey.

z_order_of_controls_fmx_intro




This is a follow on to my earlier post where I provided a VCL solution.
Now Ive created a free FireMonkey unit that has the same get and set routines as the VCL solution. The full source code is available for download

Source and Demo Project
z_order_of_controls_fmx-png


Full source code provided.
Для просмотра ссылки Войди или Зарегистрируйся

The demo lets you get and set the Z Order of controls and also get a list of all controls in Z Order.

The list on the right hand side shows the Z order of all controls on the form.
You can change the Z order and watch the “B” TEdit move up and down through the Z Order.

What does Delphi Provide ?
Delphi provides a limited API to set the Z order of controls.
You can bring a control to the front or send it to the back … that is all.
Код:
begin
  Edit1.BringToFront;
  Edit2.SendToBack;
end;

But we need to reposition a control anywhere in the Z order !

Don’t panic – we can do that using code that I provide in this post.

How does my code work ?
The code uses a brute force approach, repeatedly bringing controls to the front until they are in the requested order. It’s a primitive approach but it works well enough.

Get Z Order of a control
This is the code that you write. Pretty easy
Код:
var
  vZorder : integer;
begin
  vZorder:= zzGetControlZOrder (MyEdit);
end;

Modify the Z Order of a control
Another one liner. The brute force happens behind the scenes
Код:
begin
 zzSetControlZOrder (MyEdit, 10);
end;

Reposition a control on top of another control
Код:
// reposition Edit1 to be on top of Edit2
begin
 zzSetControlZOrder (
          Edit1
         ,zzGetControlZOrder (Edit2) + 1
          );
end;

Reposition a control below another control
Код:
   // reposition Edit1 to be on top of Edit2
begin
 zzSetControlZOrder (
          Edit1
         ,zzGetControlZOrder (Edit2) - 1
          );
end;

FireMonkey dummy elements
Some FireMonkey objects such as TForm and TPanel always include a child element #0 that is used to paint the background or border. My code takes these into account and ensures that these elements remain at the bottom of the Z order.

Close enough
In VCL – some controls such as TLabel are always positioned at the rear and their Z Order can not be changed.

This is less of an issue for FireMoneky as TLabels can be brought to the front. However, I expect it will still be an issue for some controls

With this in mind, the zzSetControlZOrder function will reorder the control to as close as possible to the Z position that you specify.

Zero Based Z-Order
The Z Order is zero based, so the first control is #0, the second control is #1.

Try to break it
You can throw any object that you like at the routines and it will elegantly and silently survive the attempt. If you pass in something that does not have a Z-Order position, it wont do anything and it wont crash, it wont raise an error or show an error message.

If this occurs, the GET function will return -1 and the SET function will return FALSE.

I could have raised an error, but for the purposes that I wrote the code it was more convenient to suppress all errors.

Tested Environments
  • Tested for Delphi 10.1 Berlin and it should work in many prior and future releases of Delphi as well
  • This supports FMX controls on Forms, Panels and Frames and their descendents.
    Let me know if you are interested in others that dont work and Ill see what I can do.
What About VCL ?
This post is about FireMonkey.
See this post for my solution for VCL

There are minor differences between VCL and FireMonkey

1) FireMonkey creates a child TRectangle as element #0, placed at the bottom of the Z order in Forms and Panels.

2) You can not change the Z-Order for TLabel in VCL, but you can in FireMonkey

Limitations
Some controls such as TWebBrowser will always display on top of other controls.
This might be fixed in recent versions of Delphi but I havent tested that. Please post a comment if you have any information about that. Recent Delphi versions included improvements to support Z order such as Delphi 10.3 having support for Z-order of controls in Android


[/SHOWTOGROUPS]