Устранение неполадок виртуализации DPI и приложений с поддержкой DPI в Windows Vista и Windows 7

У меня проблема, когда приложение (написанное на Delphi) ведет себя правильно при настройках по умолчанию 96 DPI во всех системах, но ведет себя непоследовательно при настройке "150% размер текста" (внутренне 144 dpi) в разных системах. Кажется, что в некоторых системах некоторые части текста/шрифта моего приложения растягиваются, а в других системах-нет. Я бы подумал, что мое приложение на определенной версии Windows (Win7), при определенном DPI, должно вести себя одинаково путь.

либо мое приложение сообщит Windows, что ему не нужна функция виртуализации DPI, либо нет. Это я понимаю. Я не понимаю, как изменения DPI могут вызывать различный внешний вид на двух машинах, работающих под управлением Windows 7, как на 144 dpi, отображая одни и те же шрифты и формы с одинаковыми фиксированными размерами.

есть ли некоторые зависящие от конфигурации элементы, участвующие в виртуализации DPI, которые мне нужно проверить в windows (реестр и т. д.)? В противном случае, как устранить неполадки и узнать, выполняется ли виртуализация DPI в окне клиента?

в Delphi необходимо установить TForm.Масштабируемое свойство имеет значение false, если масштабирование не требуется. Но чего я не понимаю, так это того, что когда масштабируемое свойство основной формы истинно, я не всегда могу предсказать результат.

что меня больше всего озадачивает в моем приложении, так это то, что у меня есть контроль, который только плохо себя ведет в моем большом реальном приложении, но который не ведет себя плохо в автономном приложении, где я пытаюсь отладить только элемент управления. Чтобы понять поведение управления в автономном приложении, я был вынужден сделать демонстрационное приложение, где я заставляю осведомленность DPI через файл манифеста. Затем я могу воспроизвести контрольный рисунок Глюка, хотя и в другой форме.

вот файл манифеста, который я использую в своем демо-приложении, который раскрывает проблемы, которые мои элементы управления имеют с настройками с высоким разрешением в windows. Однако, один странный вещь я нашел, что это возможно для приложения

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
 <asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    <asmv3:windowsSettings
         xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
  <assemblyIdentity version="14.0.3615.26342" processorArchitecture="*"            
   name="TestProject" type="win32"></assemblyIdentity>
  <description>High DPI Controls Test App</description>
</assembly>

вот пример одного из примерно 30 мест, где элементы управления в моем приложении перепутались, когда я отключаю виртуализацию DPI в своем приложении. Этот конкретный глюк был решен путем отключения масштабируемого свойства в моей форме. Но в других местах, имея TForm.Scaled=false вызывает проблему, тогда как в некоторых формах она исправляет ее:

DPI Glitch Example with a non-DPI-virtualized app manifest, but main form is Scaled

Update: оказывается, некоторые из моих элементы управления используют GDI+ и что поведение шрифта в контекстах GDI+ отличается от поведения шрифта в обычных контекстах GDI, по крайней мере для некоторых сторонних элементов управления, которые используют GDI+. Это главный источник головной боли. Во-вторых, в VCL есть пятнистый охват тестирования и плохо определенные требования для осведомленности DPI. Некоторые элементы управления VCL основаны на общих элементах управления MS, и хотя справедливо сказать, что основные общие элементы управления, вероятно, работают нормально в ситуациях с высоким разрешением, не все VCL можно гарантировать, что оболочки управления будут работать правильно. Итак, обзор приложения для высокой DPI-осведомленности во всех его элементах управления, а также правильное поведение во всех доступных темах windows 7:

  1. aero glass on, at 96dpi (внешний вид Win7 по умолчанию на большинстве современных аппаратных средств)
  2. основная тема (aero glass off), но темы xp включены
  3. классический win2000 посмотрите, где стекло выключено, а также темы уровня xp,
  4. контрастный белый
  5. высокая контрастность черный
  6. различные настройки, отличные от-96-DPI

..и список продолжается., и у вас есть довольно тяжелое бремя, как разработчик приложений. Являетесь ли вы пользователем delphi и используете VCL, или вы разработчик MFC/ATL C++, мне кажется, что поддержка всех различных причудливых режимов windows-это бремя, почти слишком тяжелое, чтобы нести. Поэтому большинство людей не беспокоятся. Я прав?

4 ответов


вам нужно показать, что ваше приложение знает DPI с разделом, как это:

<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
  <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
    <dpiAware>true</dpiAware>
  </asmv3:windowsSettings>
</asmv3:application>

Если вы это сделаете, вы не получите виртуализацию DPI.

вы не должны использовать виртуализацию DPI, поэтому я думаю, что нет смысла пытаться понять, как это работает. Это может легко зависеть от драйверов видеокарты. Нам почти невозможно объяснить, почему виртуализация ведет себя таким образом: вы даже не дали никаких скриншотов, деталей оборудования и т. д. Однако, вы просто не должны пытаться диагностировать это. Манифестируйте как dpiaware, и это не проблема.

для справки предлагаю вам:


enter image description hereОкно " настройка пользовательского DPI "имеет"использовать масштабирование DPI в стиле Windows XP". Это может объяснить другое поведение.


на самом деле это другой вопрос.

ваши формы не должны становиться больше с DPI, они должны стать больше с размер шрифта.

шрифт формы по умолчанию Delphi и 8пт Tahoma размером.
The в среднем 8pt Тахома характер:6.08px * 13px.

начиная с Windows Vista, шрифт по умолчанию 9 кегль, шрифт Segoe UI.
The в среднем 9pt Segoe UI символ:6.81px * 15px.

enter image description here

ваши приложения Windows должны уважать предпочтение шрифта пользователя (т. е. IconTitleFont).

мой предпочтение шрифта Windows -12pt Segoe UI, которого в среднем размер символов: 8.98px * 21px:

enter image description here

это означает, что если вы спроектировали код форму Тахома 8pt (13px high), вам нужно масштабировать форму и все дочерние элементы управления на 162%:

scaleFactor = (userFontSize / designedFontSize)
            = 21px / 13px
            = 1.615

если вы будете осторожны, вы заметите, что изменение DPI - это просто особый случай изменения размера шрифта. Ваш 8pt шрифт все еще 8pt, но 8pt переводится в больше пикселей. Если вы запустите 131dpi (136% масштабирование в Windows 7) затем:

9pt Segoe UI,  96dpi = 6.81px x 15px
9pt Segoe UI, 131dpi = 8.98px x 21px

enter image description here

Примечание: это не совпадение, что я выбрала 131dpi и 12pt в моих примерах. На работе я запускаю 96dpi, но 12pt. Дома я запускаю 9pt, но 131dpi. Оба имеют одинаковую высоту шрифта пикселя, 21px.


в конце концов вам нужно позвонить ScaleControl по разнице размеров:

procedure StandardizeFormFont(Form: TForm);    
var
   iconTitleFontName: string;
   iconTitleFontSizePixels: Integer;
   currentFontSizePixels: Integer;
begin
   GetIconTitleFont(iconTitleFontName, iconTitleFontSizePixels);

   //Change font face first
   //Some fonts are inheriently taller than others
   //(even at the same point size)
   Form.Font.Name := iconTitleFontName;     

   //Get the form's current font height (in pixels)
   currentFontSizePixels := Form.Font.Height; //negative number, but so is iconTitleFontSizePixels

   Form.ScaleBy(iconTitleFontSizePixels, currentFontSizePixels);
end;

на самом деле этот код очень упрощен. Необходимо обновить многие дочерние элементы управления вручную:

  • столбцы listview должны быть шире
  • управления ParentFont = false нужно настроить их шрифт
  • управление TImage нужно растянуть их изображения на новый размер
  • панель инструментов должна использовать большие изображения

на самом деле мы используем супер-причудливую версию StandardizeFormFont это рекурсивно проходит через все элементы управления в форме и лучше всего настроить каждый элемент управления на основе того, что он есть.

каждый элемент управления Delphi должен переопределить его ScaleControl метод и внести необходимые корректировки:

protected
   procedure ChangeScale(M, D: Integer); override;

оказывается, что причуды в моем приложении, когда системный DPI изменился от значения по умолчанию 96 dpi, находятся в трех общих лагерях:

  1. некоторые элементы управления приложения используют GDI, а некоторые элементы управления используют GDI+. Есть некоторые различия в том, как шрифт GDI и GDI+ отображается на разных DPI, по крайней мере, в элементах управления, которые я использую.

  2. Я использую фреймворк под названием VCL в delphi. В этой Delphi VCL framework некоторые формы имеют TForm.Scaled=true, а некоторые имеют TForm.Масштабируется=ложь. Поскольку это требует, чтобы вы думали о каждом элементе управления в масштабированной форме, очень часто происходит то, что вы, как дизайнер пользовательского интерфейса, найдете "уродливым" или неприемлемым в масштабированной форме. Выключив масштабирование, вы остаетесь с формами, которые либо растягиваются самой Windows 7, в высоких настройках DPI (режим виртуализации DPI) или которые кажутся маленькими и поэтому игнорируют "запрос" пользователя, если хотите, для версии 144 dpi вашего 96 dpi ПОЛЬЗОВАТЕЛЬСКИЙ ИНТЕРФЕЙС. Другие люди могут использовать другие фреймворки на других языках или даже использовать что-то действительно старомодное, например редактор диалоговых окон для Visual C++, где вы разрабатываете диалоговые окна в "диалоговых единицах", что является еще одним способом попытаться отделить общий макет диалога от соответствия 1:1 пикселям. Элементы управления масштабированием, растяжением и компоновкой-это общая часть дизайна пользовательского интерфейса, которая должна быть решена в соответствии с требованиями платформы. В моем случае VCL делает большую работу позвольте мне разработать приложение aero с поддержкой стекла 96 DPI и отлично работает в других рейтингах DPI, но большинство моих пользовательских элементов управления этого не делают. Так что это еще одна причина придерживаться элементов управления, которые поставляются с VCL: если вы заботитесь о высокой поддержке DPI, ваша работа становится сложнее, когда вы пытаетесь сделать работу с высокой поддержкой DPI.

  3. виртуализация DPI, в свою очередь, управляется параметром манифеста, который необходимо явно включить в приложение. Так как у моего приложения уже был обычай манифест (не тот, который включен в ваше приложение Delphi, когда вы нажимаете флажок Включить-windows-темы в настройках проекта), я смог включить и выключить эту виртуализацию DPI и протестировать мое приложение в обоих случаях. Я обнаружил, что мое приложение не готово к работе без виртуализации DPI, и поэтому я оставил Windows для ее поведения по умолчанию. Приложения других людей могут легко работать с отключенной виртуализацией DPI, если они используют 100% элементы управления vcl, с формами, которые либо используйте масштабирование формы или какой-либо другой метод для соответствующего размера (например, элемент управления VCL ExpressLayout от DevExpress) при различных размерах шрифта и шагах DPI.). Мне кажется, что в конце концов VCL достаточно функциональен, но для действительно промышленных решений требуется более продвинутая структура, чем VCL, чтобы всесторонне решать такие проблемы, как" среды с высоким DPI", и что сторонние элементы управления, как правило, не предназначены для работы даже так хорошо как работает текущий VCL, в этих случаях. Такие проблемы с фреймворком очень хорошо видны в рамках WPF (Microsoft) и Java (wing), но не являются частью классической "общей структуры управления Win16/Win32" VCL.

в целом, эти изменения не так уж отличаются (сложные) сейчас, чем в старые времена, когда Windows XP и другие версии Windows предложили вам выбор "размеров шрифта", в то время как теперь Windows 7 UI experience пытается похоронить шрифт параметры размера точки довольно глубоко, и вместо этого предлагает вам" размер текста " изменение пользовательского интерфейса, который изменяет систему DPI под поверхностью. Оба этих способа изменения пользовательского опыта приводят к тому, что почти у каждого пользователя возникают проблемы по крайней мере с одним крупным коммерческим приложением, которое не выглядит или корректно работает с полученными изменениями. Поскольку ультравысокие точечные дисплеи становятся все более распространенными в потребительском ландшафте ПК, эта проблема, вероятно, будет становиться все хуже и хуже, и дизайн пользовательского интерфейса вокруг более подходящих рамок потребуется.