2

For the fist time I have some problems creating a "complex" UI with delphi. I use a 4K monitor for development & testing and I have some scaling issues.

My app use a 2 column design, think of a diff view under a source control where you have a left pane and a right pane that mirror themselves component wise but the content (text) of these components are different.

To give you an idea I do this on the form resize:

edtFixExifLeftFile.Width := Floor((pnlFixExifTop.ClientWidth - (bbpFixExifBrowseLeft.Width * 2 + 42)) / 2);
bbpFixExifBrowseLeft.Left := edtFixExifLeftFile.Left + edtFixExifLeftFile.Width + 5;

edtFixExifRightFile.Left := bbpFixExifBrowseLeft.Left + bbpFixExifBrowseLeft.Width + 16;
edtFixExifRightFile.Width := edtFixExifLeftFile.Width;
bbpFixExifBrowseRight.Left := edtFixExifRightFile.Left + edtFixExifRightFile.Width + 5;

This way both columns take 50% of the space. This is pixel perfect when used in a HD environment (1080p) but in a 4K environment the scaling (my TForm.Scaled = True) completely "eats" one of the margins (I use 8px margins and the scaling take about 9px more than expected). This make the look wrong in 4K (the right TEdit overflow the TForm a bit).

How can I create a pixel perfect UI in HD and 4K environments? What is the right way to code my component resize?

I use the latest version of Delphi (10.3) and I don't use fancy components (only "stock" VCL).

AlexV
  • 22,658
  • 18
  • 85
  • 122
  • 2
    You have to account for the DPI in your coordinates and your code doesn't. – David Heffernan Nov 08 '19 at 21:04
  • 2
    You can use a TGridPanel with two columns set to 50% width. – Uwe Raabe Nov 09 '19 at 08:57
  • 1
    VCL provides two events for Dpi Changes - OnBeforeMonitorDpiChanged, OnAfterMonitorDpiChanged. Even though VCL will scale most things fairly well, I find that I usually need to apply a little extra in the OnAfterMonitorDpiChanged event. To take Dpi into account, I use the MulDiv function also, for example MuldDiv(5, Monitor.PixelsPerInch, 96) instead of just 5. Get to know these functions. You can also sync height, say between a TButton and TEdit in OnAfterMonitorDpiChange. – Greg Dawson Nov 15 '19 at 23:34

1 Answers1

1

After reading a good tutorial by Žarko Gajić I ended doing this:

Pad := MulDiv(8, Monitor.PixelsPerInch, 96);
grdpnlCover.Left := pnlCoverImage.Left + pnlCoverImage.Width + Pad;

Where 8 is the unscaled value and 96 is the DPI the form was designed under.

AlexV
  • 22,658
  • 18
  • 85
  • 122