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

Когато windows е настроен да "преоразмерява текста на "125%", моето Win32 приложение има своя UI (но не и неговия размер на прозореца) увеличен. Това кара текстовите низове да бъдат отрязани и UI елементите да изчезнат от ръба на прозореца.

Бих искал да предотвратя това да се случи, така че текстът да не се мащабира и приложението да се показва правилно. Тъй като инвестицията във времето, за да се получи това старо наследено приложение правилно с DPI, е твърде висока и аз просто искам да направя приложението използваемо, като попреча на Windows да наруши потребителския интерфейс чрез преоразмеряване на елементи на потребителския интерфейс.

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

Фрагментът на манифеста, който използвам, за да посоча осведомеността за 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 UNaware, причинявайки изрязания текст, когато 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%, така че Windows да мащабира неразрушения потребителски интерфейс;)   -  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. Мащабирането на DPI на Windows в непознати приложения е много лошо внедрено, като например увеличаване на прозореца за изглед на цял екран и изрязване отстрани.

Нямах късмет с манифеста.

Успях да го разреша, като извиках SetProcessDPIAware();, но трябваше да се случи преди да се изпълни SDLmain. Може би вашето „по време на стартиране“ не е било достатъчно рано. Използвам го като инициализатор на глобална променлива преди функцията main:

BOOL dpi_result = SetProcessDPIAware();

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