Uwaga: zapoznaj się z innymi odpowiedziami, ponieważ zawierają one bardzo cenne techniki. Moja odpowiedź tutaj zawiera tylko zastrzeżenia i przestrogi przed założeniem, że świadomość DPI jest łatwa.
Generalnie unikam skalowania z uwzględnieniem DPI z TForm.Scaled = True
. Świadomość DPI jest dla mnie ważna tylko wtedy, gdy staje się ważna dla klientów, którzy do mnie dzwonią i są gotowi za to zapłacić. Technicznym powodem tego punktu widzenia jest to, że świadomość DPI lub nie, otwierasz okno na świat bólu. Wiele standardowych i zewnętrznych formantów VCL nie działa dobrze w trybie High DPI. Godnym uwagi wyjątkiem jest to, że części VCL, które zawijają wspólne kontrolki systemu Windows, działają wyjątkowo dobrze przy wysokiej rozdzielczości DPI. Ogromna liczba zewnętrznych i wbudowanych niestandardowych elementów sterujących Delphi VCL nie działa dobrze lub w ogóle nie działa przy wysokim DPI. Jeśli planujesz włączyć TForm.Scaled, pamiętaj, aby przetestować przy 96, 125 i 150 DPI dla każdego formularza w projekcie oraz dla każdej strony trzeciej i wbudowanej kontroli, której używasz.
Samo Delphi jest napisane w Delphi. Ma włączoną flagę świadomości High DPI dla większości formularzy, chociaż nawet tak niedawno, jak w Delphi XE2, autorzy IDE sami zdecydowali NIE włączać tej flagi manifestu świadomości High DPI. Zauważ, że w Delphi XE4 i nowszych, flaga świadomości HIGH DPI jest włączona i IDE wygląda dobrze.
Sugeruję, abyś nie używał TForm.Scaled = true (co jest wartością domyślną w Delphi, więc większość twoich formularzy ma Scaled = true) z flagami High DPI Aware (jak pokazano w odpowiedziach Davida) z Aplikacje VCL, które są tworzone przy użyciu wbudowanego projektanta formularzy Delphi.
W przeszłości próbowałem zrobić minimalną próbkę tego rodzaju złamania, jakiego można się spodziewać, gdy TForm.Scaled jest prawdą i gdy skalowanie formularzy Delphi ma usterkę. Te usterki nie zawsze są wyzwalane tylko przez wartość DPI inną niż 96. Nie byłem w stanie określić pełnej listy innych rzeczy, w tym zmian rozmiaru czcionki w systemie Windows XP. Ale ponieważ większość tych usterek pojawia się tylko w moich własnych aplikacjach, w dość skomplikowanych sytuacjach, zdecydowałem się pokazać wam pewne dowody, które możecie sami zweryfikować.
Delphi XE wygląda tak, gdy ustawisz skalowanie DPI na „Fonts @ 200%” w Windows 7, a Delphi XE2 jest podobnie uszkodzony w Windows 7 i 8, ale te usterki wydają się być naprawione jak w Delphi XE4:
Są to głównie standardowe kontrolki VCL, które działają nieprawidłowo przy wysokiej rozdzielczości DPI. Zauważ, że większość rzeczy nie została w ogóle skalowana, więc programiści Delphi IDE zdecydowali się zignorować świadomość DPI, a także wyłączyć wirtualizację DPI. Taki ciekawy wybór.
Wyłącz wirtualizację DPI tylko wtedy, gdy chcesz tego nowego dodatkowego źródła bólu i trudnych wyborów. Proponuję zostawić to w spokoju. Zwróć uwagę, że wspólne elementy sterujące systemu Windows w większości wydają się działać dobrze. Należy zauważyć, że formant eksploratora danych Delphi jest opakowaniem C # WinForms wokół standardowej wspólnej kontrolki drzewa systemu Windows. To czysta usterka Microsoft, a naprawienie jej może wymagać przepisania przez Embarcadero czystej natywnej kontroli drzewa .Net dla ich eksploratora danych lub napisania kodu właściwości DPI-Check-and-Modify w celu zmiany wysokości elementów w kontrolce. Nawet Microsoft WinForms nie radzi sobie w sposób czysty z wysoką rozdzielczością DPI, automatycznie i bez niestandardowego kodu kludge.
Aktualizacja: Interesujący fakt: chociaż środowisko delphi IDE wydaje się nie być „zwirtualizowane”, nie wykorzystuje ono manifestu treści pokazanego przez Davida do osiągnięcia „wirtualizacji innej niż DPI”. Być może używa jakiejś funkcji API w czasie wykonywania.
Aktualizacja 2: W odpowiedzi na to, jak obsługiwałbym 100% / 125% DPI, wymyśliłbym plan dwufazowy. Faza 1 polega na inwentaryzacji mojego kodu pod kątem niestandardowych formantów, które należy naprawić w celu uzyskania wysokiej rozdzielczości DPI, a następnie zaplanowaniu ich naprawienia lub wycofania. Faza 2 polegałaby na przejęciu niektórych obszarów mojego kodu, które są zaprojektowane jako formularze bez zarządzania układem i zamianie ich na formularze, które używają pewnego rodzaju zarządzania układem, aby zmiany DPI lub wysokości czcionki mogły działać bez przycinania. Podejrzewam, że ta praca nad układem „między kontrolą” byłaby znacznie bardziej złożona w większości aplikacji niż praca „wewnątrz kontroli”.
Aktualizacja: W 2016 roku najnowsza wersja Delphi 10.1 Berlin działa dobrze na mojej stacji roboczej 150 dpi.
SetProcessDPIAware
.Twoje ustawienia w pliku .dfm zostaną poprawnie przeskalowane, o ile tak
Scaled
jestTrue
.Jeśli ustawiasz wymiary w kodzie, musisz skalować je przez
Screen.PixelsPerInch
podzielenie przezForm.PixelsPerInch
. Użyj,MulDiv
aby to zrobić.To właśnie robi platforma utrwalania formularzy, kiedy
Scaled
jestTrue
.W rzeczywistości można przedstawić przekonywujący argument za zastąpieniem tej funkcji wersją, która na stałe koduje wartość 96 jako mianownik. Pozwala to na użycie bezwzględnych wartości wymiarów i nie martwi się o zmianę znaczenia, jeśli zdarzy się zmienić skalowanie czcionki na komputerze deweloperskim i ponownie zapiszesz plik .dfm. Powodem, który ma znaczenie, jest to, że
PixelsPerInch
właściwość przechowywana w pliku .dfm to wartość komputera, na którym ostatnio zapisano plik .dfm.Kontynuując temat, kolejną rzeczą, na którą należy uważać, jest to, że jeśli projekt jest tworzony na wielu komputerach z różnymi wartościami DPI, zauważysz, że skalowanie używane przez Delphi podczas zapisywania plików .dfm powoduje, że kontrolki wędrują po serii zmian. . Aby tego uniknąć, w moim miejscu pracy stosujemy ścisłą zasadę, zgodnie z którą formularze są zawsze edytowane tylko w rozdzielczości 96 dpi (100% skalowanie).
W rzeczywistości moja wersja
ScaleFromSmallFontsDimension
pozwala również na uwzględnienie możliwości czcionki różniącej się w czasie wykonywania od czcionki ustawionej w czasie projektowania. Na komputerach XP formularze mojej aplikacji używają 8pt Tahoma. W systemie Vista i nowszych używany jest interfejs użytkownika 9pt Segoe. Zapewnia to jeszcze jeden stopień swobody. Skalowanie musi to uwzględniać, ponieważ zakłada się, że wartości wymiarów bezwzględnych użyte w kodzie źródłowym są odniesione do linii bazowej 8 punktów Tahomy przy 96 dpi.Jeśli używasz obrazów lub glifów w swoim interfejsie użytkownika, one również muszą zostać przeskalowane. Typowym przykładem mogą być glify używane na paskach narzędzi i menu. Będziesz chciał dostarczyć te glify jako zasoby ikon połączone z twoim plikiem wykonywalnym. Każda ikona powinna zawierać zakres rozmiarów, a następnie w czasie wykonywania należy wybrać najbardziej odpowiedni rozmiar i załadować go do listy obrazów. Kilka szczegółów na ten temat można znaleźć tutaj: Jak ładować ikony z zasobu bez aliasów?
Inną przydatną sztuczką jest zdefiniowanie wymiarów w jednostkach względnych względem
TextWidth
lubTextHeight
. Tak więc, jeśli chcesz, aby coś miało rozmiar około 10 pionowych linii, możesz użyć10*Canvas.TextHeight('Ag')
. To bardzo przybliżone i gotowe dane, ponieważ nie pozwalają na odstępy między wierszami i tak dalej. Jednak często wszystko, co musisz zrobić, to ustawić prawidłowe skalowanie GUIPixelsPerInch
.Powinieneś także oznaczyć swoją aplikację jako obsługującą wysokie DPI . Najlepszym sposobem na to jest skorzystanie z manifestu aplikacji. Ponieważ narzędzia do budowania Delphi nie pozwalają na dostosowywanie używanego manifestu, zmusza to do połączenia własnego zasobu manifestu.
Skrypt zasobów wygląda następująco:
gdzie
Manifest.txt
zawiera rzeczywisty manifest. Musisz również dołączyć sekcję comctl32 v6 i ustawićrequestedExecutionLevel
naasInvoker
. Następnie połącz ten skompilowany zasób ze swoją aplikacją i upewnij się, że Delphi nie próbuje zrobić tego samego z manifestem. W nowoczesnych Delphi można to osiągnąć, ustawiając opcję projektu Runtime Themes na None.Manifest to właściwy sposób na zadeklarowanie aplikacji, która obsługuje wysoką rozdzielczość DPI. Jeśli chcesz po prostu szybko to wypróbować, nie zmieniając manifestu, zadzwoń
SetProcessDPIAware
. Zrób to jako pierwszą czynność, którą robisz po uruchomieniu aplikacji. Najlepiej w jednej z wczesnych sekcji inicjalizacji jednostki lub jako pierwsza rzecz w pliku .dpr.Jeśli nie zadeklarujesz, że Twoja aplikacja obsługuje wysokie DPI, Vista i nowsze wyrenderują ją w starszym trybie dla dowolnego skalowania czcionki powyżej 125%. To wygląda dość okropnie. Staraj się nie wpaść w tę pułapkę.
Aktualizacja DPI dla Windows 8.1 na monitor
W systemie Windows 8.1 dostępna jest teraz obsługa ustawień DPI dla poszczególnych monitorów ( http://msdn.microsoft.com/en-ca/magazine/dn574798.aspx ). Jest to duży problem w przypadku nowoczesnych urządzeń, które mogą mieć różne wyświetlacze o bardzo różnych możliwościach. Możesz mieć ekran laptopa o bardzo wysokiej rozdzielczości i zewnętrzny projektor o niskiej rozdzielczości. Wsparcie takiego scenariusza wymaga jeszcze więcej pracy niż opisano powyżej.
źródło
Należy również pamiętać, że honorowanie DPI użytkownika to tylko część Twojej prawdziwej pracy:
Od dziesięcioleci system Windows rozwiązuje ten problem, stosując koncepcję wykonywania układu przy użyciu jednostek dialogowych , a nie pikseli. „Jednostka dialogowe” jest zdefiniowane tak, że fontu średni charakter jest
Delphi dostarcza (błędne) pojęcie
Scaled
, w którym formularz próbuje automatycznie dostosować się na podstawieTo nie rozwiązuje problemu, gdy użytkownik używa innej czcionki niż ta, z którą zaprojektowałeś formularz, np .:
6.21px x 13.00px
96dpi)użytkownik korzystający z Tahoma 8pt (gdzie przeciętny znak to
5.94px x 13.00px
96 dpi)Tak jak w przypadku każdego, kto tworzy aplikację dla systemu Windows 2000 lub Windows XP.
lub
5.94px x 13.00px
96dpi)6.67px x 15px
)Jako dobry programista będziesz szanować preferencje czcionek użytkownika. Oznacza to, że musisz również przeskalować wszystkie kontrolki w formularzu, aby dopasować je do nowego rozmiaru czcionki:
Scaled
nie zrobię tego za Ciebie.Gorzej, gdy:
10.52px x 25px
Teraz musisz wszystko skalować
Scaled
nie zrobię tego za Ciebie.Jeśli jesteś sprytny, możesz zobaczyć, jak honorowanie DPI jest nieodparte:
Nie powinieneś patrzeć na ustawienie DPI użytkownika, powinieneś patrzeć na jego rozmiar czcionki . Dwóch użytkowników działa
używają tej samej czcionki . DPI to tylko jedna rzecz, która wpływa na rozmiar czcionki; preferencje użytkownika są inne.
StandardizeFormFont
Clovis zauważył, że odwołuję się do funkcji,
StandardizeFormFont
która naprawia czcionkę w formularzu i skaluje ją do nowego rozmiaru czcionki. Nie jest to standardowa funkcja, ale cały zestaw funkcji wykonujących proste zadanie, którego firma Borland nigdy nie wykonywała.Windows ma 6 różnych czcionek; w systemie Windows nie ma jednego „ustawienia czcionki”.
Ale z doświadczenia wiemy, że nasze formularze powinny być zgodne z ustawieniem Czcionka tytułu ikony
Kiedy znamy rozmiaru czcionki będziemy skalowania formularz do otrzymujemy aktualną wysokość czcionki w formie ( w pikselach ), a skalowanie w górę przez ten czynnik.
Na przykład, jeśli ustawiam formularz na
-16
, a formularz jest obecnie na-11
, musimy przeskalować cały formularz przez:Standaryzacja przebiega w dwóch fazach. Najpierw przeskaluj formularz według stosunku nowych: starych rozmiarów czcionek. Następnie faktycznie zmień kontrolki (rekurencyjnie), aby użyć nowej czcionki.
Oto zadanie rzeczywistego skalowania formularza. Działa wokół błędów w
Form.ScaleBy
metodzie własnej firmy Borland . Najpierw musi wyłączyć wszystkie zakotwiczenia w formularzu, następnie wykonać skalowanie, a następnie ponownie włączyć kotwice:a następnie musimy rekurencyjnie użyć nowej czcionki:
Gdy kotwice są rekursywnie wyłączone:
A kotwice są ponownie włączane rekurencyjnie:
Dzięki pracy nad faktyczną zmianą czcionki kontrolek pozostawiono:
To o wiele więcej kodu, niż się spodziewałeś; wiem. Smutne jest to, że nie ma na świecie programisty Delphi, poza mną, który faktycznie poprawia ich aplikacje.
źródło
Oto mój prezent. Funkcja, która może pomóc w poziomym pozycjonowaniu elementów w układach GUI. Darmowy dla wszystkich.
źródło