Z Order of Controls in Delphi FireMonkey

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.
Download here

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 # 0 that is used to paint the background or border.  Dont worry, I have coded around to ensure that these elements remain at the bottom of the list.

Close enough

In VCL – some controls such as TLabel are always positioned at the back 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 they will survive.  If you pass in something that does not have a Z-Order position, it wont do anything and it also wont crash, show an error or raise an error.   The GET function will return -1.  The SET function will return FALSE.  I could have raised an error, but for the purposes that I built this it was more convenient to suppress all errors.

This works for …

  • Tested for Delphi 10.1 Berlin and should work in many prior releases of Delphi
  • 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

Feedback

I’m interested in your feedback.  Let me know if you have an idea for improvement, find a bug or are interested in a scenario that the unit does not support.

Download

Download the demo project with full source code

+1 this post

If you like this post, please +1 vote here to get it listed on Delphi Feeds and also here on BeginEnd.  Thank You

About Me

scott_hollows_201611

  • Oracle & Delphi software developer based in Perth, Western Australia
  • Australian Delphi User Group – WA Chief Cat Herder
  • Australian Delphi User Group – President
blog email linkedinlogo

Author: Scott Hollows

Enterprise software developer based in Perth, Western Australia. Focused on Oracle, Delphi, Data Warehouse design and ETL, Data Architect, Business Intelligence, Oracle performance tuning. President of the Australian Delphi User Group (ADUG) LinkedIn www.linkedin.com/in/scotthollows

3 thoughts on “Z Order of Controls in Delphi FireMonkey”

  1. Very nice!

    I added this code

    function zzGetControlMaxZOrderObject(aControl : TObject): TObject;
    var
    vControl : TControl;
    vParent : TFmxObject;
    begin
    result := nil;
    try
    vControl := aControl as TControl;
    vParent := vControl.Parent as TFmxObject;
    result := vParent.Children[vParent.ChildrenCount – 1];
    except

    end;
    end;

    when I want that some object is moved to Foreground.

    procedure TForm2.Image1Click(Sender: TObject);
    begin
    zzSetControlZOrder(
    Sender,
    zzGetControlZOrder(zzGetControlMaxZOrderObject(Sender)) + 1
    )
    end;

    it is very useful for me!!

    thank you.

  2. Hi Tetsuji

    You are welcome

    It looks like your code is bringing the image to the front and if that is correct, I have a short cut for you. This should achieve the same result

    procedure TForm2.Image1Click(Sender: TObject);
    begin
    Image1.BringToFront;
    end;

    Scott

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s