I just created a new application in Delphi and even though other applications written the same way, this new application does not get automatically scaled by Windows. All applications have exactly the same settings (e.g., scaled = false). And Windows usually scales them properly (otherwise they would be too small if scaling is set to 150% or higher).
I found out that using properties menu of the .exe file, tab "Compatibility", "Change HIGH-DPI settings" and set "Scaling by system" on bottom solves the issue and the application gets scaled properly.
But how can I either activate this option by default (Registry?) or how can I do it programmatically?
You can provide your app with an app manifest that specifies <dpiAwareness>unaware</dpiAwareness>
(Windows 10 v1607 and later), <gdiScaling>false</gdiScaling>
(Windows 10 v1703 and later), and <dpiAware>false</dpiAware>
(earlier versions), eg:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">unaware</dpiAwareness>
<gdiScaling xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">false</gdiScaling>
</windowsSettings>
</application>
</assembly>
Alternatively, before creating any GUI windows at runtime, you can call either SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE)
(Windows 10 v1607 and later) or SetProcessDpiAwareness(PROCESS_DPI_UNAWARE)
(earlier versions), eg:
program MyProject;
uses
Vcl.Forms, Winapi.Windows,
MyMainForm in 'MainForm.pas' {MyMainForm};
{$R *.res}
{$IF NOT DECLARED(DPI_AWARENESS)}
type
DPI_AWARENESS = (
DPI_AWARENESS_INVALID = -1,
DPI_AWARENESS_UNAWARE = 0,
DPI_AWARENESS_SYSTEM_AWARE = 1,
DPI_AWARENESS_PER_MONITOR_AWARE = 2
);
{$IFEND}
{$IF NOT DECLARED(DPI_AWARENESS_CONTEXT)}
type
DPI_AWARENESS_CONTEXT__ = record
var
unused: Integer;
end;
DPI_AWARENESS_CONTEXT = ^DPI_AWARENESS_CONTEXT__;
const
DPI_AWARENESS_CONTEXT_UNAWARE: DPI_AWARENESS_CONTEXT = DPI_AWARENESS_CONTEXT(-1);
{$IFEND}
type
LPFN_SetProcessDpiAwarenessContext = function(value: DPI_AWARENESS_CONTEXT): BOOL; stdcall;
LPFN_SetProcessDpiAwareness = function(value: PROCESS_DPI_AWARENESS): HRESULT; stdcall;
var
lpSetProcessDpiAwarenessContext: LPFN_SetProcessDpiAwarenessContext;
lpSetProcessDpiAwareness: LPFN_SetProcessDpiAwareness;
begin
@lpSetProcessDpiAwarenessContext := GetProcAddress(LoadLibrary('User32.dll'), 'SetProcessDpiAwarenessContext');
if Assigned(lpSetProcessDpiAwarenessContext) then begin
lpSetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE);
end else begin
@lpSetProcessDpiAwareness := GetProcAddress(LoadLibrary('Shcore.dll'), 'SetProcessDpiAwareness');
if Assigned(lpSetProcessDpiAwareness) then
lpSetProcessDpiAwareness(PROCESS_DPI_UNAWARE);
end;
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TMyMainForm, MyMainForm);
Application.Run;
end.
See Setting the default DPI awareness for a process on MSDN for more details.