Подтвердить что ты не робот

Устранение неполадок приложений для виртуализации 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.Scaled значение false, если вы не хотите масштабирования. Но я не понимаю, что, когда свойство основной формы Scaled истинно, я не всегда могу предсказать результат.

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

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

<?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 в своем приложении. Этот конкретный глюк был разрешен путем отключения свойства Scaled в моей форме. Но в других местах, когда TForm.Scaled = false вызывает проблему, тогда как в некоторых формах она исправляет ее:

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

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

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

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

4b9b3361

Ответ 1

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

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

  • Я использую фреймворк VCL в delphi. В этой структуре Delphi VCL некоторые формы имеют TForm.Scaled = true, а некоторые имеют TForm.Scaled = false. Поскольку это требует, чтобы вы думали о каждом элементе управления в масштабированной форме, очень часто случается, что вы, как разработчик пользовательского интерфейса, найдете "уродливым" или неприемлемым в масштабированной форме. При повороте Scaled off вы остаетесь с формами, которые либо растягиваются самой Windows 7, либо с высокими настройками DPI (режим виртуализации DPI), либо кажутся маленькими и, следовательно, игнорируют пользовательский "запрос", если хотите, для версии с разрешением 144 dpi ваш пользовательский интерфейс с разрешением 96 точек на дюйм. Другие люди могут использовать другие фреймворки на других языках или даже могут использовать что-то действительно старомодное, например, редактор диалогового окна для Visual С++, где вы создаете диалоги в "Dialog Units", что является еще одним способом отделить общий диалог макет, от соответствия 1:1 пикселям. Масштабирование, растяжка и компоновка являются общей частью дизайна пользовательского интерфейса, которая должна быть решена таким образом, чтобы соответствовать требованиям платформы. В моем случае VCL отлично справляется с тем, что я могу создать приложение для аэродинамического стекла с разрешением 96 точек на дюйм и отлично работает в других рейтингах DPI, но большинство моих пользовательских элементов управления не работают. Так что это еще одна причина придерживаться элементов управления, которые поставляются с VCL: если вы заботитесь о высокой поддержке DPI, ваша работа усложняется, когда вы пытаетесь сделать работу с поддержкой DPI.

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

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

Ответ 2

Вам нужно продемонстрировать, что ваше приложение поддерживает 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, и это не проблема.

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

Ответ 3

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

Ответ 4

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

Ваши формы не должны увеличиваться с помощью пользователя DPI, они должны увеличиваться с размером шрифта.

Размер шрифта по умолчанию Delphi 8pt Tahoma.
средний 8pt Характер Tahoma: 6.08px * 13px.

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

enter image description here

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

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

enter image description here

Это означает, что если вы создали свою форму в Tahoma 8pt (максимум 13 пикселей), вам необходимо масштабировать форму и все дочерние элементы управления на 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 current font height (in pixels)
   currentFontSizePixels := Form.Font.Height; //negative number, but so is iconTitleFontSizePixels

   Form.ScaleBy(iconTitleFontSizePixels, currentFontSizePixels);
end;

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

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

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

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

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