Windows DPI Form Scaling - delphi

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.

Related

How do you modify a Delphi Panel so Alignment := taRightJustify renders Caption with slight right margin?

I am converting an old legacy program from 2005. It uses many Panel.Caption fields to store output. All of panels are set to taRightJustify. The caption is very tight up against the right edge.
As a quick fix I tried making border=4 and at first I thought this would be the solution. It gave the visual appearance of a inside right margin. However, characters with a descender such as "g, y, and comma.
So I'm looking for a way to modify the Panel.Caption property so when the panel is set to taRightJustify there is a little bit of margin between the right edge of the caption text and the inside right edge of the panel.
I thought about just adding a space to the end of the caption text but there are so many places where the caption text is actually numeric values and adding the extra space would cause for code changes than it's worth.
You can modify how the TPanel displays its caption by changing the code that draws the text of the caption ... but you probably don't want to actually change that code.
Realistically what you can do is create a simple custom control which is a TPanel with another protected TPanel inside it. The properties of the inner panel should use ParentColor := true no bevels, Aligned to client (so it fills the outer panel) and set the right Margin and AlignWithMargins as advised by #Uwe Raabe.
override the declaration of the Caption property so that when this is accessed it is accessing the Caption of the inner panel.
override the declaration of the ShowCaption Property so that the outer panel ShowCaption is always False and setting the property changes the ShowCaption property on the inner panel.
With Search and Replace change all of your TPanels to your new derived class (which you would have given your own name to - perhaps TPaddedPanel).
To use your new TPanel in the form designer of the IDE you will have to register the component.
There are lots of tutorials for creating custom components. Ray Konopka is very experienced and has a useful tutorial on VCL components at: https://edn.embarcadero.com/es/article/20569
I have Konopka Signature VCL Controls 6.2.3 installed. I've decided to switch out all the panels using the taRightJustify setting for RzPanels. The RzPanel has a TextMargin property that does exactly what I need. Thank you Ray Kanopka for incorporating this feature into your panel component.
https://delphibydesign.com/
https://raize.com/

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

Anchoring GUI components in FireMonkey

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).

Resources