High DPI preview form issue

Hello,

looks like preview form is not high dpi aware, can this be fixed somehow?

image

Best regards
Frank Liebig

Comments

  • Hi Frank,

    I'm testing with Delphi 10.4 and RB 20.03 and the preview toolbar is scaling correctly.





    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • edited November 2020
    Dear Nard,

    I have the same kind of problem as Frank:
    image

    I am with all versions updated: Delphi 10.4.1 and RB 20.04

    My monitor is 4K with Windows Zoom at 300%.
    If I drag the preview window to another monitor Full HD with zoom at 150%, everything is ok on this other monitor, and if I drag it back to the 4K monitor, the icons are not rescaled and I am back with the same problem.

    My manifest is using PerMonitorv2

    Gilles Boussin
  • Dear Nard,

    I am still investigating how to solve this problem of PreviewForm.
    With the debugger I see that PreviewForm has the right FCurrentPPI = 192 et FScaleFactor = 2

    FYI: Aside of this problem, I have everything ok in my application for handle drag from monitors with various DPI. So I see no other problem of configuration.

    I am looking forward to your answer.

    Regards,

    Gilles
  • Hi Gilles,

    There is a patch available for RB 20.04 which resolves an issue with toolbar/menus being double-scaled in some cases. This is perhaps what is happening in the first case above. It looks like in the screen shot either the buttons are not scaled or the font is double-scaled.

    In your screen shot the toolbar items are scaled - you can see this in the highlight-rectangle for the 2 selected buttons. The icons are not scaled. The Delphi ImageList is not DPI aware.

    The plan is to continue improving DPI support. Windows API has been evolving its DPI support, the Delphi VCL and FMX libraries are following suit. Delphi 10.4 introduces new VirtualImageList and ImageCollection classes designed to implement DPI aware icons. We're researching using these new classes for a future RB release.

    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • Dear Nard,

    Thanks for your explanation.
    The problem I have on my 4K screen is effectively that the icons are not scaled.

    FYI : if it can help you to build a patch quickly: in places where there are plenty of icons I do not want to migrate to image collections, I use in the Create function (DPI being the current DPI of the form) :

    if DPI <> 96 then ResizeBitmap(btnXXX.Glyph, MulDiv(btnXXX.Glyph.Width, DPI, 96), Muldiv(btnXXX.Glyph.Height, DPI, 96));

    procedure ResizeBitmap(Bitmap: TBitmap; NewWidth, NewHeight: integer; ForceSquare: boolean = false);
    var
    buffer: TBitmap;
    begin
    buffer := TBitmap.Create;
    try
    buffer.SetSize(NewWidth, NewHeight);
    buffer.Canvas.StretchDraw(Rect(0, 0, NewWidth, NewHeight), Bitmap);
    Bitmap.SetSize(NewWidth, NewHeight);
    Bitmap.Canvas.Draw(0, 0, buffer);
    finally
    buffer.Free;
    end;
    end;

    And furthermore, to handle DPI change between monitors, here is a simplified version of what I do:

    procedure XXX.FormAfterMonitorDpiChanged(Sender: TObject; OldDPI,
    NewDPI: Integer);
    begin
    if oldDPI <> DPI then begin
    j := MDIChildCount - 1;
    for k := j downto 0 do begin
    try
    if MDIChildren[k] <> nil then begin
    for i := MDIChildren[k].ControlCount - 1 downto 0 do
    begin
    ResizeControls(MDIChildren[k].Controls[i] as TControl, oldDPI, DPI);
    end;
    end;
    except
    //
    end;
    end;
    end;
    end;

    The function to resize the icons recusively:

    procedure XXX.ResizeControls(const AControl: TControl; oldDPI: integer; newDPI: integer);
    var
    i, j: Integer;
    begin
    if (AControl = nil) or (newDPI = oldDPI) then Exit;
    if AControl is TWinControl then begin
    for i := 0 to TWinControl(AControl).ControlCount-1 do
    ResizeControls(TWinControl(AControl).Controls[i], oldDPI, newDPI);
    end;
    if (AControl is TBitBtn) then
    DMStyle.ResizeBitmap((AControl as TBitBtn).Glyph, MulDiv((AControl as TBitBtn).Glyph.Width, newDPI, oldDPI), Muldiv((AControl as TBitBtn).Glyph.Height, newDPI, oldDPI))
    else if (AControl is TSpeedButton) then
    DMStyle.ResizeBitmap((AControl as TSpeedButton).Glyph, MulDiv((AControl as TSpeedButton).Glyph.Width, newDPI, oldDPI), Muldiv((AControl as TSpeedButton).Glyph.Height, newDPI, oldDPI))
    end;

    => you could use this approach at short term, and migrate later to proper high resolution icons, because the usability of the icons bar is really faulty with such small icons.

    Gilles
Sign In or Register to comment.