Wszystkie elementy ContainerControls muszą być ustawione na to samo AutoScaleMode = Font
. (Czcionka będzie obsługiwać zarówno zmiany DPI, jak i zmiany w ustawieniu rozmiaru czcionki systemowej; DPI będzie obsługiwać tylko zmiany DPI, a nie zmiany w ustawieniu rozmiaru czcionki systemowej).
Wszystkie elementy ContainerControl muszą być również ustawione na to samo AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
, zakładając 96 dpi (patrz następny punkt) i domyślną czcionkę MS Sans Serif (patrz punkt drugi poniżej). Jest to automatycznie dodawane przez projektanta na podstawie DPI, w którym otworzyłeś projektanta ... ale brakowało go w wielu naszych najstarszych plikach projektanta. Być może program Visual Studio .NET (wersja przed VS 2005) nie dodawał go poprawnie.
Wykonuj wszystkie prace projektanta w 96 dpi (być może uda nam się przełączyć na 120 dpi; ale mądrość w Internecie mówi, aby trzymać się 96 dpi; eksperymentowanie jest w porządku; z założenia nie powinno to mieć znaczenia, ponieważ zmienia tylko AutoScaleDimensions
linię, która projektant wkładki). Aby ustawić program Visual Studio tak, aby działał w wirtualnym 96 dpi na wyświetlaczu o wysokiej rozdzielczości, znajdź jego plik .exe, kliknij prawym przyciskiem myszy, aby edytować właściwości, i w obszarze Zgodność wybierz opcję „Zastąp zachowanie skalowania w wysokiej rozdzielczości DPI. Skalowanie wykonywane przez: System”.
Upewnij się, że nigdy nie ustawiłeś Czcionki na poziomie kontenera ... tylko na kontrolkach liści LUB w konstruktorze najbardziej podstawowego formularza, jeśli chcesz mieć domyślną czcionkę dla całej aplikacji inną niż MS Sans Serif. (Ustawienie czcionki w kontenerze wydaje się wyłączać automatyczne skalowanie tego kontenera, ponieważ następuje to alfabetycznie po ustawieniu ustawień AutoScaleMode i AutoScaleDimensions). UWAGA, jeśli zmienisz czcionkę w konstruktorze najbardziej podstawowego formularza, spowoduje to Twoje AutoScaleDimensions do obliczania inaczej niż 6x13; w szczególności, jeśli zmienisz na Segoe UI (domyślna czcionka Win 10), to będzie to 7x15 ... będziesz musiał dotknąć każdego formularza w Projektancie, aby mógł ponownie obliczyć wszystkie wymiary w tym pliku .designer, w tym the AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
.
NIE używaj zakotwiczenia Right
lub Bottom
zakotwiczenia w UserControl ... jego położenie nie będzie automatycznie skalowane; zamiast tego upuść Panel lub inny kontener do Kontroli Użytkownika i zakotwicz inne Kontrolki do tego Panelu; mają obsłudze panel Dock Right
, Bottom
lub Fill
w swoim UserControl.
Tylko elementy sterujące na listach elementów sterujących, gdy wywoływana jest ResumeLayout
funkcja na końcu, InitializeComponent
będą skalowane automatycznie ... jeśli dodasz elementy sterujące dynamicznie, SuspendLayout();
AutoScaleDimensions = new SizeF(6F, 13F);
AutoScaleMode = AutoScaleMode.Font;
ResumeLayout();
musisz je włączyć, zanim je dodasz. Pozycjonowanie również będzie wymagało dostosowania jeśli nie używasz trybów Docka ani Menedżera układu, takiego jak FlowLayoutPanel
lub TableLayoutPanel
.
Klasy bazowe, z których pochodzą, ContainerControl
należy pozostawić AutoScaleMode
ustawione na Inherit
(wartość domyślna ustawiona w klasie ContainerControl
; ale NIE domyślna ustawiona przez projektanta). Jeśli ustawisz ją na cokolwiek innego, a następnie twoja klasa pochodna spróbuje ustawić ją na Font (tak, jak powinna), wtedy ustawienie tego na Font
wyczyści ustawienie projektanta AutoScaleDimensions
, co w rzeczywistości spowoduje wyłączenie automatycznego skalowania! (Ta wytyczna w połączeniu z poprzednią oznacza, że nigdy nie można utworzyć wystąpienia klas bazowych w projektancie ... wszystkie klasy muszą być zaprojektowane jako klasy bazowe lub jako klasy liści!)
Unikaj używania Form.MaxSize
statycznego / w Projektancie. MinSize
a MaxSize
na Formie nie skaluj się tak bardzo, jak wszystko inne. Tak więc, jeśli wykonasz całą swoją pracę w 96dpi, to przy wyższej DPI MinSize
nie spowoduje to problemów, ale może nie być tak restrykcyjne, jak się spodziewałeś, ale MaxSize
możesz ograniczyć skalowanie rozmiaru, co może powodować problemy. Jeśli chcesz MinSize == Size == MaxSize
, nie rób tego w Projektancie ... rób to w swoim konstruktorze lub OnLoad
nadpisuj ... ustaw oba MinSize
i MaxSize
odpowiednio wyskalowany rozmiar.
Wszystkie Kontrolki na konkretnym Panel
lub Container
powinny używać Kotwiczenia lub Dokowania. Jeśli je pomieszasz, automatyczne skalowanie wykonane przez to Panel
często będzie źle działać w subtelny dziwaczny sposób.
Kiedy wykona swoje automatyczne skalowanie, będzie próbować skalować ogólną formę ... jednak jeśli w tym procesie osiągnie górną granicę rozmiaru ekranu, jest to sztywny limit, który może następnie zepsuć (klip) skalowanie. Dlatego należy upewnić się, że wszystkie formularze w Projektancie przy 100% / 96 dpi mają rozmiar nie większy niż 1024x720 (co odpowiada 150% na ekranie 1080p lub 300%, co jest wartością zalecaną przez system Windows na ekranie 4K). Ale musisz odjąć gigantyczny pasek tytułu / podpisu Win10 ... a więc bardziej jak maksymalny rozmiar 1000x680 ... który w projektancie będzie taki jak 994x642 ClientSize. (Możesz więc wykonać funkcję FindAll References w ClientSize, aby znaleźć osoby naruszające.)
NumericUpDown
też nie skaluje sięMargin
prawidłowo. Wygląda na to, że margines jest dwukrotnie przeskalowany. Jeśli raz go przeskaluję, wygląda dobrze.AutoScaleMode = Font
nie działa dobrze dla użytkowników, którzy używają bardzo dużej czcionki w systemie Ubuntu. WolimyAutoScaleMode = DPI
Moje doświadczenie różni się od odpowiedzi, która jest obecnie najczęściej wybierana. Przechodząc przez kod platformy .NET i przeglądając kod źródłowy odniesienia, doszedłem do wniosku, że wszystko jest na miejscu, aby automatyczne skalowanie działało, i istnieje tylko subtelny problem, który go zepsuł. Okazało się, że to prawda.
Jeśli utworzysz układ z możliwością poprawiania / automatycznego określania rozmiaru, prawie wszystko działa dokładnie tak, jak powinno, automatycznie, z domyślnymi ustawieniami używanymi przez program Visual Studio (a mianowicie AutoSizeMode = Font w formularzu nadrzędnym i Inherit we wszystkich pozostałych).
Jedynym problemem jest ustawienie właściwości Font w formularzu w projektancie. Wygenerowany kod posortuje zadania alfabetycznie, co oznacza, że
AutoScaleDimensions
zostaną przypisane wcześniejFont
. Niestety, to całkowicie łamie logikę automatycznego skalowania WinForms.Poprawka jest jednak prosta. Albo w ogóle nie ustawiaj
Font
właściwości w projektancie (ustaw ją w konstruktorze formularza), albo ręcznie zmień kolejność tych przypisań (ale musisz to robić za każdym razem, gdy edytujesz formularz w projektancie). Voila, prawie idealne iw pełni automatyczne skalowanie przy minimalnym wysiłku. Nawet rozmiary formularzy są poprawnie skalowane.Wymienię tutaj znane problemy, które napotkam:
TableLayoutPanel
niepoprawnie oblicza marginesy kontrolne . Nie ma znanego obejścia poza całkowitym unikaniem marginesów i dopełnień - lub unikaniem zagnieżdżonych paneli układu tabeli.źródło
Font
w projektancie: przychodzi mi do głowy myśl: śmiało ustaw czcionkę w projektancie, abyś mógł zaprojektować z żądaną czcionką. WTEDY w konstruktorze, po układzie, odczytać właściwość czcionki i ponownie ustawić tę samą wartość? A może po prostu poproś o ponowne wykonanie układu? [Uwaga: nie miałem powodu, aby testować to podejście.] Lub zgodnie z odpowiedzią Knowleech , w projektancie określ w pikselach (aby projektant Visual Studio nie przeskalował na monitorze o wysokiej rozdzielczości DPI), a w kodzie odczytaj tę wartość, przekonwertuj z pikseli do punktów (aby uzyskać prawidłowe skalowanie).AutoScaleDimensions
nie został ustawionynew SizeF(6F, 13F)
zgodnie z zaleceniami w górnej odpowiedzi. Okazało się, że w każdym przypadku właściwość Font formularza została ustawiona (nie domyślna). Wydaje się, że kiedyAutoScaleMode = Font
, toAutoScaleDimensions
jest obliczane na podstawie właściwości czcionki formularza. Wydaje się również, że ustawienie skalowania w Panelu sterowania systemu Windows ma wpływ naAutoScaleDimensions
.Skieruj swoją aplikację na .Net Framework 4.7 i uruchom ją pod Windows 10 v1703 (Creators Update Build 15063). Dzięki .Net 4.7 pod Windows 10 (v1703) firma MS wprowadziła wiele ulepszeń DPI .
Aby to obsługiwać, dodaj manifest aplikacji do aplikacji i zasygnalizuj, że Twoja aplikacja obsługuje system Windows 10:
Następnie dodaj
app.config
i zadeklaruj aplikację Per Monitor Aware. Jest to TERAZ zrobione w app.config, a NIE w manifeście, jak wcześniej!Ten PerMonitorV2 jest nowy od aktualizacji Windows 10 Creators Update:
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
Teraz możesz zasubskrybować 3 nowe wydarzenia, aby otrzymywać powiadomienia o zmianach DPI:
Masz również 3 pomocnicze metody obsługi / skalowania DPI:
Control.LogicalToDeviceUnits , która konwertuje wartość z pikseli logicznych na piksele urządzenia.
Control.ScaleBitmapLogicalToDevice , która skaluje obraz bitmapowy do logicznego DPI urządzenia.
Control.DeviceDpi , która zwraca wartość DPI dla bieżącego urządzenia.
Jeśli nadal widzisz problemy, możesz zrezygnować z ulepszeń DPI za pośrednictwem wpisów app.config .
Jeśli nie masz dostępu do kodu źródłowego, możesz przejść do właściwości aplikacji w Eksploratorze Windows, przejść do zgodności i wybrać
System (Enhanced)
który aktywuje skalowanie GDI, aby również poprawić obsługę DPI:
Wykonaj wszystkie te kroki, a powinieneś uzyskać lepsze wrażenia z DPI dla aplikacji WinForms. Pamiętaj jednak, że musisz kierować swoją aplikację na .net 4.7 i potrzebujesz co najmniej Windows 10 Build 15063 (Creators Update). W następnej aktualizacji Windows 10 1709 możemy uzyskać więcej ulepszeń.
źródło
Poradnik, który napisałem w pracy:
źródło
Okazało się, że bardzo trudno jest sprawić, by WinForms grało dobrze z wysoką rozdzielczością. Dlatego napisałem metodę VB.NET, aby zastąpić zachowanie formularza:
źródło
Niedawno natknąłem się na ten problem, szczególnie w połączeniu z przeskalowaniem programu Visual Studio, gdy edytor jest otwarty w systemie o wysokiej rozdzielczości. Uważam, że najlepiej jest zachować
AutoScaleMode = Font
, ale ustawić czcionkę formularzy na czcionkę domyślną, ale określając rozmiar w pikselach , a nie w punktach, tjFont = MS Sans; 11px
. : . W kodzie, I następnie zresetować czcionkę domyślną:Font = SystemFonts.DefaultFont
i wszystko jest w porządku.Tylko moje dwa centy. Myślałem, że się tym podzielę, ponieważ „zachowanie AutoScaleMode = Font” i „Ustaw rozmiar czcionki w pikselach dla Projektanta” było czymś, czego nie znalazłem w Internecie.
Więcej szczegółów znajduje się na moim blogu: http://www.sgrottel.de/?p=1581&lang=en
źródło
Oprócz tego, że kotwice nie działają zbyt dobrze: poszedłbym o krok dalej i powiedział, że dokładne pozycjonowanie (czyli użycie właściwości Location) nie działa zbyt dobrze ze skalowaniem czcionki. Musiałem rozwiązać ten problem w dwóch różnych projektach. W obu z nich musieliśmy przekonwertować pozycjonowanie wszystkich kontrolek WinForms na używanie TableLayoutPanel i FlowLayoutPanel. Używanie właściwości Dock (zwykle ustawionej na Fill) wewnątrz TableLayoutPanel działa bardzo dobrze i dobrze skaluje się z DPI czcionki systemowej.
źródło