Anchoring GUI components in FireMonkey - delphi

Just started testing FireMonkey and can't find a way to make dynamically sized/positioned components.
VCL had the Anchor property, FM does not.
Anybody see something I missed
Update:
Simple anchoring is not available in FM. You have to create TLayouts and align those, then put the controls inside the panel to have them 'stick'. If you used older version of Builder or Delphi, this will be the same as we used to have to do with TPanels.

This is the answer to your question. The anchors property in VCL has apparently been replaced by Margins and Padding (due to performance considerations) and I found some documentation at the XE2 wiki (http://docwiki.embarcadero.com/RADStudio/en/FireMonkey_Application_Design). I doubt if anchors will be put in at a later date. To anchor two buttons (Ok and Cancel) at the bottom of a form on the right side do the following.See images below for the Ok and cancel button.
Place a small panel aligned to the bottom on the form, say about 40 height. Set the 'Margins' on the bottom panel to create a smaller space in which the buttons will live, make sure you set the align the button to alRight. For example the gap between the right edge of the form and the right most button has a margin of 15. The top and bottom margins were set to 12. That anchors the right most button.
'Padding' is the opposite to a margin, the padding puts space outside the control. To the right most button I added a padding of 20 to the left side, this will be the space between the two buttons. For the second button to the left of the first all we need to do is set the align property to alRight, no need to adjust the padding or margins.

Drop multiple TLayout components on the form and configure their alignment properties as desired. Drop other components into these layouts and set their alignment properties relative to the TLayout they are contained in. Seems to be working for me...

Here's the answer you are looking for: FMX controls do not have anchors.
I imagine this will be a "next version" feature.

A quick look at the align property reveals many more choices than we had in previous Delphi versions:
Doesn't that solve your problem (at least partially).
I remember getting by OK for a long time just using nested panels and align to layout stuff.

You can use LiveBindings and expressions to set the properties of your control based on the parent control, though it's a lot of work.
Otherwise, use Margins and Padding (like HTML/CSS).

Related

Make a component appear in the middle of form no matter what screen resolution

I am using delphi
I have a program that runs in multiple shops but some people have a screen with a low resolution and some have a screen with a high resolution.
When i run the program on a screen with a lower resolution, the components are more to the right and a scroll bar appears.
I want my components to appear exactly in the middle of the form no matter what resolution.
how?
Screen resolution is no issue, unless you are talking about maximized forms, so I will assume that. That implies you having trouble with aligning components in the center of changing form sizes.
Considering a single control in that regard, then the solution is relatively easy: change its position in an OnResize event handler:
procedure TForm1.FormResize(Sender: TObject);
begin
Control.Left := (ClientWidth - Control.Width) div 2;
Control.Top := (ClientHeight - Control.Height) div 2;
end;
For a multiple control situation, the most easy solution is to place them on a single container, e.g. a panel, and use the above approach. But for small forms, this could result in the container being too large resulting in showing the form's scroll bars as you say (which can be suppressed by the AutoScroll property of the form), and for large form sizes, the container could render too small.
Another solution is the relative anchor solution: Just set the Anchors property to [] for all controls, and all controls will stay in their relative position, regardless form size. (This trick also applies to solution #1).
In both cases, the control's size and font size remain the same which could or will distort the layout. There are multiple possible solutions for that, but that's beyond the scope of your question and this answer I think.
You can use Anchors property. For example if you align TEdit, TCombobox as you need and you want them to have always same position relatively left and right side of the form, just set Anchors property accordingly (akLeft=True, akRight=True). You can do that in design time or from the code.
P.S. Descriptions of problem is no so clear actually.
Use a TGridPanel to place your components in if they have to be centered all the time. The TGridPanel will align it's child components according to the Alignment and VerticalAlignment properties within each cell.
Place the TGridPanel where you want to show your component
Set the Align to alClient.
Set the ColumnCollection to only one column.
Set the RowCollection to only one row.
Set the Alignment to taCenter
Set the VerticalAlignment to taVerticalCenter
Place your component in the TGridPanel
Note: You can put only one component in each cell of a TGridPanel, to overcome this restriction put a TPanel in a cell and then multiple components in that panel.

Delphi XE4 dynamic panel alignment order

I have a Firemonkey app. that dynamically adds a number of objects derived from a TPanel with
Align := TAlignLayout.alTop;
However, the last object ends up at the top, with all the others in the correct place.
e.g.
Panel-5
Panel-0
Panel-1
Panel-2
Panel-3
Panel-4
when I want
Panel-0
Panel-1
Panel-2
Panel-3
Panel-4
Panel-5
I've tried alBottom, alMostTop[ etc but all have a similar problem.
How can I fix thgis?
Cheers,
Martin.
OK, now as official answer:
When creating your panels assign a value for top (the height of the container, for example).
Reason:
When you create a component its top will always be 0. With two components with a top at 0 and alTop it is purely coincidental which component ends up on top in the end. See here for some code doing the trick: How to dynamically create controls aligned to the top but after other aligned controls?

How to set caption of TMS AdvSmoothLabel with proper alignment in Delphi 7?

Below is a screenshot of a TMS AdvSmoothLabel with alignment set to Bottom Right.
As can be seen in the pic, there is a small amount of space always left between the RHS of Label and RHS of Label's caption. What i wanted was something like the TLabel:-
I tried going through TMS units and i was only confused.
I am not sure if you have yet asked TMS Software or if you have been replied to but the way to do what you require is to turn Wordwrap ON
I would have though it would be the margins, but testing them I can't get them to do anything.
I have two work arounds to suggest.:
Set the Caption Location to plCustom and then set the Caption's Top and Left settings. This might be annoying for you if your form is resizeable and you want to keep the text to the left.
Hide the bit of the background you don't want under a panel, or off the form or something.

How do I keep a control at the bottom or right of a panel when the panel changes size?

There have been a few similar questions with solutions, but none answered my question, so here it is.
Making a TPanel collapse/expand with a TButton on it is ridiculously simple, or so I thought. I played around and by putting the button at the very top (for expansion/collapse of height from top to bottom) or left (for expansion/collapse of width from left to right) everything worked as planned. In fact all of the expandable/collapsible "advanced" panels work in the exact same way - the button is placed on top or left only. Soon enough I hit a wall: if you put the button at the bottom or right for expansion/collapse of height or width respectively, the buttons stay where they are on... the client area (?) - I lack the knowledge to explain this properly, but I'll presume that it is clear what is happening until otherwise pointed out. The point is that with the way I'm doing this the only solution would be to reposition the button within the panel, but that might put in on top of say some other components which should not be visible at all.
So the question is: how can I make this happen properly? as my idea of resizing the panel and then repositioning the button doesn't look like a proper approach to this problem. Alternatively, I'd gladly take some component that does this, however from the components that I have checked out, all act the same, even JEDI VCL TJvRollOut component can set Placement (of the button/caption) only to plTop or plLeft, so I'm thinking this isn't as simple to do?
Set to your button Anchors property to [akLeft, akBottom].
There are two properties for adjusting the alignment of any tool in delphi:
Align (alNone, alLeft, alRight, alTop....)
Anchors (akLeft, akRight, akTop, akBottom)
e.g.
You have a panel and drag a TEdit on the TPanel. Now, you want TEdit to occupy ONLY top-left corner of TPanel and its distance form the bottom and right corners of the panel should remain constant irrespective of changing the panel size (which means TEdit expands if you extent panel along the bottom or right corners).
Set Align-> alNone. (not alLeft or else tEdit would occupy entire left region on panel and not just top-left).
Set Anchors-> akLeft=akTop=akRight=akBottom=True.
In case you set akLeft=akTop=True and akRight=akBottom=False: then the size of TEdit remains constant on expanding panel along the bottom or right corners.

Windows DPI Form Scaling

I have previously been using VGScene (Firemonkey predecessor) to create an application and have recently switched to Delphi XE2's Firemonkey.
To scale my form in VGScene all I had to do was to scale the Root object of the VGScene object to scale all content in the form. However I am unsure how this should be done using FireMonkey.
My form consists of two TLayouts, one left aligned and one set to Client align, with a vertical splitter control between the left and client layouts. The client layout also has a list box on it set to client alignment.
I have tried having a base TLayout with all my controls on it, and scaling the base TLayout but this doesn't quite work properly, the left layout scales properly, but the client layout's listbox seem to extend past the right and bottom edge of the client layout object? i.e. when you have a full list the list items extend past the right edge of the form, (which are cut off) and the vertical scrollbar isn't shown completely either as it extends past the bottom of the form. It is as though the client layout's width and height are scaled to that larger than the form allows, but should it not still fill the form's area?
I have tried to just scale the individual object's, like just scaling the listbox, but this produces the same result, the listbox extends past the bounds of the form.
Anyone have any ideas?
One possibility is that you didn't quite follow exactly the instructions for laying out your controls and splitter, as recommended on the TSplitter documentation?
If you didn't, it is easy to get to a point where all the properties seem to be set to the right values, but somehow the controls and splitter just don't cooperate. I would recommend trying again, paying careful attention to getting the align properties with the correct values, i.e. alLeft on the left component, alLeft on the splitter, and alClient on the right component.

Resources