Устранение неполадок в приложениях DPI Virtualization и DPI-совместимых приложений в Windows Vista и Windows 7 - PullRequest
18 голосов
/ 22 февраля 2011

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

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

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

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

Что меня больше всего беспокоит в моем приложении, так это то, что у меня есть элемент управления, который ведет себя только неправильнов моем большом реальном приложении, но которое не ведет себя неправильно в автономном приложении, где я пытаюсь отладить только элемент управления.Чтобы понять поведение управления в отдельном приложении, я был вынужден создать демонстрационное приложение, в котором я включаю осведомленность о 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 имеется покрытие для пятнистых тестов и плохо определенные требования к осведомленности о DPI.Некоторые элементы управления VCL основаны на общих элементах управления MS, и хотя справедливо сказать, что базовые общие элементы управления, вероятно, прекрасно работают в ситуациях с высоким разрешением, не все гарантии могут гарантировать правильную работу всех оболочек элементов управления VCL.Итак, проверка приложения на предмет высокой осведомленности о DPI во всех его элементах управления, а также правильное поведение во всех доступных темах Windows 7:

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

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

Ответы [ 4 ]

10 голосов
/ 22 февраля 2011

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

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

9 голосов
/ 24 июня 2011

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

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

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

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

enter image description here

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

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

enter image description here

Это означает, что если вы спроектировали свою форму с Tahoma 8pt (высота 13px), вам нужно масштабировать форму и все дочерние элементы управления на 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;

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

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

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

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

protected
   procedure ChangeScale(M, D: Integer); override;
7 голосов
/ 22 февраля 2011

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

6 голосов
/ 24 февраля 2011

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

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

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

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

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

...