Предотвратить масштабирование элементов пользовательского интерфейса моего приложения Win32, когда установлено высокое значение DPI.

Когда для окон установлено значение «изменить размер текста на «125%», мое приложение Win32 имеет увеличенный пользовательский интерфейс (но не размер окна). Это приводит к обрезанию текстовых строк и исчезновению элементов пользовательского интерфейса с края окна.

Я хотел бы предотвратить это, чтобы текст не масштабировался, а приложение отображалось правильно. Поскольку затраты времени на то, чтобы это старое устаревшее приложение должным образом учитывало DPI, слишком велико, и я просто хочу сделать приложение пригодным для использования, не позволяя Windows нарушать пользовательский интерфейс путем изменения размера элементов пользовательского интерфейса.

Я попытался вызвать SetProcessDPIAware() во время запуска, и когда это не сработало, сигнализируя, что приложение поддерживает DPI в своем манифесте. Однако ни одна из этих мер не имеет никакого эффекта.

Фрагмент манифеста, который я использую для указания осведомленности о 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>
</assembly>

person mackenir    schedule 17.04.2013    source источник
comment
манифест и сборка не похожи на стандартный C++. Вы используете C++/CLI или C#? Вы должны правильно переименовать свой вопрос.   -  person Arne Mertz    schedule 17.04.2013
comment
@ArneMertz, к сожалению, Microsoft сделала манифесты необходимыми и для обычного C++. Например, это способ получить повышение UAC.   -  person Mark Ransom    schedule 17.04.2013
comment
@ArneMertz Манифест сборки является стандартным для Win32 и используется со времен Windows XP, когда он разрешал создание тем (среди прочего), а затем с Vista/7, где он указывал необходимые разрешения и привилегии.   -  person Deanna    schedule 17.04.2013
comment
mackenir, это вид или диалог?   -  person Mark Ransom    schedule 17.04.2013
comment
Вы где-нибудь форсируете какой-либо конкретный размер окна? Скорее всего, это приведет к незнанию DPI, что приведет к обрезанию текста, когда Windows пытается соответствующим образом настроить.   -  person Deanna    schedule 17.04.2013
comment
@Deanna, хотя размер окна является одной из проблем (не знаю, откуда он взялся), текст также усекается (теряется, например, последнее слово предложения), потому что размер текстового элемента управления недостаточно увеличен, чтобы поместиться весь его текст использование более крупного шрифта.   -  person mackenir    schedule 17.04.2013
comment
@Deanna Итак, у меня есть один текстовый элемент управления, бла-бла-бла-бла, выровненный в конце этого «предложения». У меня есть еще один фрагмент текста, который я программно преобразую в интерактивную ссылку. Конечным результатом является текстовое предложение с последним словом «linkified». Однако при увеличении последнее слово «blah» теряется, а текст ссылки неуклюже перемещается, так что между ним и остальным текстом остается большой разрыв. Так что размер окна — не единственная проблема.   -  person mackenir    schedule 17.04.2013
comment
@MarkRansom Я использую WTL, поэтому приложение представляет собой CFrameWindowImpl, содержащее CTabView, внутри которого есть три вкладки. Одним из них является CDialogImpl, определенный в диалоговом ресурсе. В этом диалоговом окне масштабирование создает беспорядок.   -  person mackenir    schedule 17.04.2013
comment
Хорошо, я нашел, где задается размер окна, и сделал некоторые арифметические действия с DPI, чтобы масштабировать его. Другая проблема, которую я, вероятно, смогу обойти, просто... избавившись от этой ссылки. Я уже потратил слишком много времени на это ужасное старое архаичное приложение. Фу.   -  person mackenir    schedule 17.04.2013
comment
@MarkRansom спасибо, что разъяснили мне это, я этого не знал. До сих пор мои приложения для Windows были простыми консольными приложениями и фреймворками, которые не нуждались (или не использовали) в таких вещах.   -  person Arne Mertz    schedule 17.04.2013
comment
@mackenir Позиционирование метки нужно будет рассчитать, а не просто разместить. Ваша текущая схема будет одинаково ломаться в системах с разными стандартными шрифтами, открытым типом и т. Д. Либо используйте элемент управления с учетом ссылок, либо вычислите размер каждого бита текста и расположите следующий по размеру.   -  person Deanna    schedule 17.04.2013
comment
Позиционирование ярлыка @Deanna необходимо будет рассчитать. Действительно - и учитывая усилия, необходимые для достижения таких простых вещей в WTL, я не буду беспокоиться :). Жаль, что нельзя просто сказать Windows, пожалуйста, не ломайте мой пользовательский интерфейс, неумело пытаясь масштабировать его...   -  person mackenir    schedule 18.04.2013
comment
Это не неуместно, оно делает все возможное, вам нужно внести свой вклад и платить налоги. Что бы вы сделали со слабовидящими пользователями, которым нужен крупный шрифт, чтобы видеть экран?   -  person Deanna    schedule 18.04.2013
comment
Что бы вы сделали со слабовидящими пользователями, которым нужны большие шрифты? Рекомендуйте им установить размер шрифта на 150%, чтобы окна масштабировали непрерывный пользовательский интерфейс;)   -  person mackenir    schedule 18.04.2013


Ответы (3)


Для масштабирования шрифта 125% параметр DPI не имеет значения. Что происходит, так это то, что текст будет на 25% больше, и тогда на вас лежит ответственность за масштабирование вашего пользовательского интерфейса, чтобы соответствовать. Ваши диалоги обычно должны быть на 25% больше, чтобы вместить более крупный текст. Вам нужно не только масштабировать размеры, но и масштабировать позиции. Это зависит от вас, чтобы закодировать все это. Или используйте UI-фреймворк, который сделает это за вас.

Для масштабирования шрифта более 125% вступает в действие настройка с учетом DPI. Что происходит:

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

Эта статья MSDN содержит все кровавые подробности.

Вернемся к вашему конкретному вопросу. Ты сказал:

Я хотел бы предотвратить это, чтобы текст не масштабировался, а приложение отображалось правильно.

Другими словами, вы говорите, что хотели бы игнорировать настройку масштабирования шрифта пользователя и отображать его с разрешением 100% DPI независимо от его желания. Вы можете сделать это, уменьшив размер всего текста на 25%. Я действительно не рекомендую вам это делать.

person David Heffernan    schedule 17.04.2013
comment
Разве диалоги обычно не измеряются в диалоговых единицах, которые уже основаны на размере шрифта? - person Mark Ransom; 17.04.2013
comment
Хороший вопрос @Mark - это должно быть в ответе, чтобы сделать его более правильным. - person mackenir; 18.04.2013
comment
@David отменил мою версию, если хотите, чтобы она была в истории. - person mackenir; 19.04.2013

Это всего лишь предупреждение о ошибочном подозрении MFC/Windows 7 в этом вопросе.

У меня было то, что оказалось той же проблемой. Наше (старое) приложение MFC при запуске в Windows 7 с размером шрифта 125% отображало диалоговые окна неправильного размера. Элементы управления были масштабированы, но каждое диалоговое окно было примерно на 25% меньше.

Сначала я искал в коде диалога все, что могло бы установить его размер/положение. Затем я увидел, что у многих людей в сети возникают проблемы с размерами диалогов при перемещении приложений MFC в Windows 7, что ложно усилило мое подозрение в отношении MFC/Windows 7.

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

person Philip Beck    schedule 12.02.2014

У меня были похожие проблемы с SDL OpenGL. Масштабирование Windows DPI в неосведомленных приложениях очень плохо реализовано, например, масштабирование в полноэкранном окне просмотра и обрезка по бокам.

Мне не повезло с манифестом.

Я смог решить эту проблему, вызвав SetProcessDPIAware();, но это должно было произойти до выполнения SDLmain. Возможно, ваше «во время запуска» было недостаточно ранним. Я использую его как инициализатор глобальной переменной перед функцией main:

BOOL dpi_result = SetProcessDPIAware();

int main( int argc, char **argv )
{
    //...
person Raptor007    schedule 19.01.2020