Я только что создал новое приложение в Delphi, и хотя другие приложения написаны таким же образом, это новое приложение не масштабируется Windows автоматически. Все приложения имеют одинаковые настройки (например, Scaled = false). И Windows обычно масштабирует их правильно (иначе они будут слишком маленькими, если масштабирование установлено на 150 % или выше).
Я обнаружил, что использование меню свойств файла .exe, вкладок «Совместимость», «Изменить настройки HIGH-DPI» и установки «Масштабирование по системе» внизу решает проблему, и приложение масштабируется правильно.
Но как мне активировать эту опцию по умолчанию (Реестр?) или как это сделать программно?
Возможно, уже существует манифест, утверждающий, что приложение поддерживает dpi?
Нет, проблема была в другой DLL, которая загружается при запуске программы. Он деактивирует масштабирование, поскольку для правильной работы требуется немасштабированное приложение. Мне потребовалось пол ночи, чтобы это выяснить...
Вы можете предоставить своему приложению манифест приложения, в котором указаны <dpiAwareness>unaware</dpiAwareness>
(Windows 10 v1607 и более поздние версии), <gdiScaling>false</gdiScaling>
(Windows 10 v1703 и более поздние версии) и <dpiAware>false</dpiAware>
(более ранние версии), например:
<?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>
В качестве альтернативы, прежде чем создавать какие-либо окна графического интерфейса во время выполнения, вы можете вызвать либо SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE)
(Windows 10 v1607 и более поздние версии), либо SetProcessDpiAwareness(PROCESS_DPI_UNAWARE)
(более ранние версии), например:
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.
Дополнительные сведения см. в разделе Настройка определения DPI по умолчанию для процесса на сайте MSDN.
Вы действительно используете XE (с 2010 года)? Приложения IIRC и XE изначально не поддерживали DPI. Вам нужно было написать собственный манифест приложения или явно выполнить вызовы API, чтобы включить поддержку DPI. Только за последние несколько лет в Delphi появилась встроенная функция правильной обработки DPI.