norgepaul / TChromeTabs

Comprehensive Delphi implementation of Chrome's tab system
Other
215 stars 78 forks source link

High DPI support for TChromeTabs #83

Closed wpostma closed 3 years ago

wpostma commented 3 years ago

I have a high DPI laptop, and frankly, 90% of VCL controls don't work on DPI other than 96 dpi, in fact, most VCL controls, especially ones that are built around Win32 Common Controls, don't support high DPI well. Of course, neither do most of the built in VCL owner drawn controls.

TChromeTabs is very modern and uses GDI+ and seems to work great on 96 dpi systems. On my system, High DPI is enabled, in the manifest, and the demo looks good except for a few extra things. The new-tab gadget does not look right. Collapsed (pinned) tabs do not look right, in fact they are rendered very strangely.

I am not sure if I am able to provide fixes for this but wanted to log this issue to start with in case anyone else stumbles into this. Perhaps if there are 2 or 3 reasonably senior devs with some GDI+ coding experience we can get a scaled version of this to work.

Looking at the code I can see considerable effort has ALREADY been made to make the polygon logic work:

function TAddButtonControl.GetPolygons: IChromeTabPolygons; var LeftOffset, TopOffset: Integer; begin Result := InternalGetPolygons(itAddButton, GetButtonBrush, GetButtonPen);

if Result = nil then begin Result := TChromeTabPolygons.Create;

Result.AddPolygon(BidiPolygon(
                  NewPolygon(BidiControlRect, [Point(MulDiv(7,Screen.PixelsPerInch,96), RectHeight(BidiControlRect)),
                             Point(MulDiv(4,Screen.PixelsPerInch,96), RectHeight(BidiControlRect) - MulDiv(2,Screen.PixelsPerInch,96)),
                             Point(0, MulDiv(2,Screen.PixelsPerInch,96)),
                             Point(MulDiv(1,Screen.PixelsPerInch,96), 0),
                             Point(RectWidth(BidiControlRect) - MulDiv(7,Screen.PixelsPerInch,96), 0),
                             Point(RectWidth(BidiControlRect) - MulDiv(4,Screen.PixelsPerInch,96), MulDiv(2,Screen.PixelsPerInch,96)),
                             Point(RectWidth(BidiControlRect), RectHeight(BidiControlRect) - MulDiv(2,Screen.PixelsPerInch,96)),
                             Point(RectWidth(BidiControlRect), RectHeight(BidiControlRect))],
                  ChromeTabs.GetOptions.Display.Tabs.Orientation)),
                  GetButtonBrush,
                  GetButtonPen);

if ChromeTabs.GetOptions.Display.AddButton.ShowPlusSign then
begin
  LeftOffset := (ChromeTabs.GetOptions.Display.AddButton.Width div 2) - MulDiv(4,Screen.PixelsPerInch,96);
  TopOffset := (ChromeTabs.GetOptions.Display.AddButton.Height div 2) - MulDiv(4,Screen.PixelsPerInch,96);

  Result.AddPolygon(BidiPolygon(
                    NewPolygon(Rect(BidiControlRect.Left + LeftOffset,
                               BidiControlRect.Top + TopOffset,
                               BidiControlRect.Right - LeftOffset,
                               BidiControlRect.Bottom - TopOffset),
                              [Point(0, MulDiv(3,Screen.PixelsPerInch,96)),
                               Point(MulDiv(3,Screen.PixelsPerInch,96), MulDiv(3,Screen.PixelsPerInch,96)),
                               Point(MulDiv(3,Screen.PixelsPerInch,96), 0),
                               Point(MulDiv(6,Screen.PixelsPerInch,96), 0),
                               Point(MulDiv(6,Screen.PixelsPerInch,96), MulDiv(3,Screen.PixelsPerInch,96)),
                               Point(MulDiv(9,Screen.PixelsPerInch,96), MulDiv(3,Screen.PixelsPerInch,96)),
                               Point(MulDiv(9,Screen.PixelsPerInch,96), MulDiv(6,Screen.PixelsPerInch,96)),
                               Point(MulDiv(6,Screen.PixelsPerInch,96), MulDiv(6,Screen.PixelsPerInch,96)),
                               Point(MulDiv(6,Screen.PixelsPerInch,96), MulDiv(9,Screen.PixelsPerInch,96)),
                               Point(MulDiv(3,Screen.PixelsPerInch,96), MulDiv(9,Screen.PixelsPerInch,96)),
                               Point(MulDiv(3,Screen.PixelsPerInch,96), MulDiv(6,Screen.PixelsPerInch,96)),
                               Point(0, MulDiv(6,Screen.PixelsPerInch,96)),
                               Point(0, MulDiv(3,Screen.PixelsPerInch,96))],
                           ChromeTabs.GetOptions.Display.Tabs.Orientation)),
                           GetSymbolBrush,
                           GetSymbolPen);
end;

end; end;

The above code, seems from my basic testing to work fantastically well.

I think the control actually needs to have its own internal PixelsPerInch value, for starters, and that it should be adjustable.

Secondly, after the main rendering/painting and logical glitches are fixed, I believe some per monitor DPI work will be needed, if the VCL is up to the task.

wpostma commented 3 years ago

This control also is not useable as it stands, within an application where there is DPI virtualization being used in the application. For example, Screen.PixelsPerInch should not be invoked when the app is running virtualized. You can't even inspect the manifest to know this, you actually need to detect DPI virtualization being active and get the virtual dpi of your application.

Someone may have forced System DPI Scaling with ntfs attributes on your exe on the client system, for instance.

landrix commented 3 years ago

take a first look

https://github.com/norgepaul/TChromeTabs/tree/monitorv2support

currently only the star on left top corner isn't correct painted under High-DPI

image