Problem z rozmazanymi czcionkami WPF - rozwiązania

153

Problem jest opisany i zademonstrowany pod następującymi linkami:

Objaśnienie: przejrzystość tekstu w WPF . Ten link zawiera porównanie czcionek.

Chciałbym zebrać wszystkie możliwe rozwiązania tego problemu. Microsoft Expression Blend używa WPF, ale czcionki wyglądają na czytelne.

  • Ciemne tło jak w Microsoft Expression Blend
  • Zwiększanie rozmiaru czcionki i zmiana czcionki (Calibri ...) [link]
  • Osadź formularze systemu Windows [link]
  • Użyj klasy TextRenderer GDI + i / lub Windows Forms, aby renderować tekst do mapy bitowej, a następnie renderuj tę mapę bitową jako kontrolkę WPF. [połączyć]

Czy jest więcej rozwiązań?

Zostanie to naprawione w VS2010 (i WPF4) beta 2

WYGLĄDA JAK TO W KOŃCU ROZWIĄZANE!

ComputerZen.com Scotta Hanselmana: WPF i rozmycie tekstu, teraz z pełną przejrzystością

Robert Vuković
źródło
VS2010RC jest dla mnie całkowicie bezużyteczne mpdreamz.nl/vs2010RC-blur.png
Martijn Laarman
VS2010RC na moim komputerze wygląda znacznie lepiej niż na Twoim zdjęciu, właściwie na białym tle jest bardzo dobry, ale nadal jest do bani na ciemnym tle.
Robert Vuković
Czy znalazłeś jakieś rozwiązanie tego problemu, w rzeczywistości mam ten sam problem tutaj w mojej aplikacji i używam WPF 3.5 z VS2010
SharpUrBrain
Ostatnie 3 linki nie działają.
SHIN JaeGuk

Odpowiedzi:

107

Zaplecze techniczne

Istnieje szczegółowy artykuł na temat renderowania tekstu WPF z jednego z menedżerów programu tekstowego WPF w witrynie windowsclient.net: klarowność tekstu w WPF .

Problem sprowadza się do tego, że WPF wymaga liniowego skalowania renderowania czcionek w celu płynnych animacji. Z drugiej strony Pure ClearType wymaga sporej swobody dzięki czcionce, która przesuwa pionowe łodygi do następnego piksela.

Różnica jest oczywista, jeśli porównamy klasyczny wzór „kaskadowy”. WinForms w lewym dolnym rogu, WPF w prawym górnym rogu:

Chociaż nie jestem fanem idiosynkrazji związanych z renderowaniem czcionek WPF, mogę sobie wyobrazić wrzawę, gdyby animacje skakały tak, jak robią to w kaskadzie WinForm.

Zabawa z rejestrem

Szczególnie interesujące było dla mnie łącze do artykułu MSDN „ Ustawienia rejestru ClearType ”, w którym wyjaśniono możliwe korekty rejestru po stronie użytkownika:

  • Poziom ClearType: ilość podpowiedzi subpikseli
  • Poziom gamma
  • Struktura pikseli: sposób ułożenia kolorowych pasków w pikselu wyświetlacza
  • Poziom kontrastu tekstu: dostosowuje szerokość lasek glifów w celu zwiększenia ciężaru czcionki

Zabawa z tymi ustawieniami tak naprawdę nie poprawiła podstawowego problemu, ale może pomóc, zmniejszając efekt krwawienia kolorów dla wrażliwych użytkowników.

Inne podejście

Najlepszą radą zawartą w artykule Text Clarity było zwiększenie rozmiaru i zmiana czcionki. Calibri działa dla mnie lepiej niż standardowy interfejs Segoe. Ze względu na jej popularność jako czcionki internetowej wypróbowałem również Verdana, ale ma ona nieprzyjemny skok wagi między 14 a 15 punktami, co jest bardzo widoczne podczas animowania rozmiaru czcionki.

WPF 4.0

WPF 4 będzie miał ulepszoną obsługę wpływania na renderowanie czcionek. W blogu tekstowym WPF znajduje się artykuł wyjaśniający zmiany. Co najważniejsze, obecnie istnieją (co najmniej) trzy różne rodzaje renderowania tekstu:

porównanie renderowania tekstu

<grumble> To powinno wystarczyć dla każdego projektanta. </grumble>

David Schmitt
źródło
11
doskonałe wyjaśnienie, +1. Prawdopodobnie wyjaśnia, dlaczego Flash ma również tak okropne renderowanie czcionek.
Jeff Atwood
1
Tak. To dobre wyjaśnienie, ale nadal żałuję, że nie ma sposobu na włączenie podpowiedzi czcionek, aby uzyskać ładny wygląd, gdy wiesz, że nie będziesz animować. Przypuszczam, że oznaczałoby to daną skalę, dla której optymalizujesz podpowiedź. Ten rodzaj rzeczy sprawia, że ​​WPF wydaje mi się nadal wersją beta.
PeterAllenWebb,
To nie jest tak, że wariant „skalowalny” nie używa podpowiedzi czcionek, po prostu WPF nie optymalizuje pod kątem trafiania w siatkę pikseli, tak jak robi to ClearType. Prawdopodobnie SnapToDevicePixels powinno działać w przypadku tekstu, ale zawsze musiałoby to być dziedziczone, ponieważ formant nie może wiedzieć, czy może zostać przyciągnięty, czy nie.
David Schmitt,
2
Szczególnie istotna jest dołączona właściwość TextOptions.TextFormattingMode ( msdn.microsoft.com/en-us/library/ee169597.aspx ). WPF4 i Silverlight mają również właściwości UseLayoutRounding ( msdn.microsoft.com/en-us/library/dd783605.aspx ) i SnapsToDevicePixels ( msdn.microsoft.com/en-us/library/… ).
Pat
@Wszystko: nie mogę znaleźć sposobu na wyłączenie wygładzania tekstu w WPF3.5 i w rezultacie etykieta lub tekst przycisku wygląda naprawdę źle. Najlepiej byłoby, gdybyśmy globalnie wyłączali antyaliasing dla czcionek. Jak mogę to osiągnąć?
SharpUrBrain
128

NET 4 wreszcie ma rozwiązanie problemu słabej jakości renderowania tekstu WPF, ale jest dobrze ukryte. Ustaw następujące parametry dla każdego okna:

TextOptions.TextFormattingMode="Display"

Wartość domyślna to „Ideal”, co wcale nie jest tym, co sugeruje nazwa.

Istnieją dwie inne opcje w TextOptions, a mianowicie TextHintingMode i TextRenderingMode, ale obie mają rozsądne wartości domyślne.

Helge Klein
źródło
Wszystko. Dzięki. To pomaga mi rozwiązać problem, ale musisz to zdefiniować tylko raz w kontenerze, takim jak <grid>
Peter Du
Tak, a jeśli ustawisz go w oknie, będzie obowiązywał dla wszystkiego, co zawiera to okno.
Helge Klein
Spędziłem dużo czasu na szukaniu tego, na wielu witrynach i blogach, które nieustannie opowiadają o tym, o ile lepsze jest formatowanie tekstu w VS2010 RTM / .Net 4 (zgadzam się, tak!). Ale żaden z nich nie chciał wspomnieć o tym, jak można sprawić, by aplikacje WPF, które za ich pomocą tworzyłeś, też wyglądały tak dobrze. Dlaczego ta własność jest tak dobrze ukryta? Dziękuję Ci bardzo.
M-Peror
5
Chcę tylko tego! Naprawdę nie obchodzi mnie, jak wyrafinowane jest renderowanie WPF, czcionki są po prostu nie do zaakceptowania przez nikogo.
Jerry Liang
1
U mnie działa „Idealny” zamiast „Wyświetlacz”. Projekt jest na platformie .NET 4.6.2. Może naprawili zdezorientowaną nazwę.
joe
40

Napotkałem problem pewnego dnia, kiedy użyłem obramowania, do którego zastosowano DropShadowEffect . W rezultacie cały tekst wewnątrz tej ramki był bardzo rozmyty. Nie ma znaczenia, czy tekst znajdował się wewnątrz innych paneli, czy bezpośrednio pod obramowaniem - każdy blok tekstu będący dzieckiem rodzica, który ma Efekt wydaje się, .

Rozwiązaniem tego konkretnego przypadku było nie umieszczanie rzeczy wewnątrz obramowania, które mają efekty, ale zamiast tego użyj siatki (lub czegokolwiek innego, co obsługuje umieszczanie treści jedna na drugiej) i umieść prostokąt w tej samej komórce co tekst (tj. jako rodzeństwo w drzewie wizualnym) i umieść na tym efekty.

Tak jak to:

<!-- don't do this --->
<Border>
     <Border.Effect>
          <DropShadowEffect BlurRadius="25" ShadowDepth="0" Opacity="1"/>
     </Border.Effect>
     <TextBlock Text="This Text Will Be Blurry" />
</Border>

<!-- Do this instead -->
<Grid>
  <Rectangle>
     <Rectangle.Effect>
          <DropShadowEffect BlurRadius="25" ShadowDepth="0" Opacity="1"/>
     </Rectangle.Effect>
  </Rectangle>
  <TextBlock Text="This Text Will Be Crisp and Clear" />
</Grid>
Isak Savo
źródło
To ładnie załatwiło sprawę. Trochę hack, ale lepsze niż majstrowanie przy ustawieniach itp. Niezłe. dzięki. Jedyną rzeczą, którą musiałem zrobić, było ustawienie wypełnienia prostokąta na coś. Może to jednak tylko moja konfiguracja.
HAdes
Tak, masz rację ... prostokąt jest domyślnie przezroczysty, co sprawia, że ​​cień wygląda dziwnie.
Isak Savo,
to się nie dzieje w mojej przykładowej aplikacji, używam WPF 3.5
SharpUrBrain
@SharpUrBrain: co się nie dzieje? Czy jest nadal rozmyty, nawet po użyciu mojego drugiego przykładu?
Isak Savo
Tak,
obraz
10

To zostanie naprawione w VS2010 (i WPF4) beta 2:

Pavel Minaev
źródło
1
+1 do testów. Ciekawe, o ile szerszy jest ten tekst.
David Schmitt,
6

SnapToDevicePixels dotyczy tylko kształtów WPF (linii itp.), A nie renderowania tekstu.

Nie jest znane obejście tego problemu. Według firmy Microsoft zachowanie jest zgodne z projektem.

Zobacz również ten wątek na forach Microsoft omawiający problemy - otrzymał kilka odpowiedzi od facetów z MS, które wyjaśniają ich stanowisko w tej sprawie.


źródło
Naprawiono w WPF 4 przy użyciu dołączonej właściwości TextOptions.TextFormattingMode ( msdn.microsoft.com/en-us/library/ee169597.aspx ).
Pat
1
Nazwa właściwości to „SnapsToDevicePixels”, a nie „SnapToDevicePixels”, jak napisano.
Nir Kornfeld
6

Z punktu widzenia programisty jedynym znanym dotychczas „obejściem” jest użycie klasy TextRenderer GDI + i / lub Windows Forms do renderowania tekstu na bitmapie, a następnie renderowanie tej mapy bitowej jako kontrolki WPF. Pomijając oczywiste konsekwencje dla wydajności, nie zmniejsza to problemu dla istniejących aplikacji.

Utworzyłem teraz bilet Microsoft Connect dla tego problemu (ku mojemu zaskoczeniu, pomimo wszystkich negatywnych opinii, w wyznaczonym trackerze nie było rzeczywistego raportu o błędzie).

Ponieważ jest to jeden z oficjalnych kanałów przekazywania zapytań i zapytań do firmy Microsoft, radziłbym również przejść przez to, aby uzyskać szybszą odpowiedź. Przynajmniej, jeśli chcesz, aby problem został rozwiązany w taki czy inny sposób, głosowanie na ten bilet i / lub zatwierdzenie problemu pomoże zwrócić uwagę kierowników projektów firmy Microsoft i inżynierów na ten problem i prawdopodobnie podniesie jego postrzegany priorytet.

David Schmitt
źródło
6

Nie uważam tego za błąd, ale domyślna konfiguracja jest rzeczywiście bardzo irytująca. Oto porównanie wszystkich kombinacji

TextOptions.TextRenderingMode
TextOptions.TextFormattingMode
RenderOptions.ClearTypeHint

SnapToDevicePixels nie powoduje żadnej różnicy w renderowaniu tekstu.

http://i.stack.imgur.com/cS3S2.png

Wolę:

TextOptions.TextRenderingMode="Auto"
TextOptions.TextFormattingMode="Ideal"
RenderOptions.ClearTypeHint="Auto"

gdzie pionowe linie nigdy nie są rozmyte.

Użyta czcionka to Open Sans Light, która może być naprawdę piękna, jeśli jest dobrze używana, jak w najnowszym TeamViewerze.

Dla osób używających Mahapps.Metro problemem jest TransitioningContentControl https://github.com/MahApps/MahApps.Metro/issues/889

Gabriel
źródło
4

Właśnie wypróbowałem wersję beta VS2010, która jest wykonywana w WPF, i BADANIE cierpi z powodu problemu z rozmytą czcionką. Szczególnie w podpowiedziach.

Wydaje się to świadczyć o tym, że WPF4 w rzeczywistości nie rozwiąże problemu (jeśli już, to wygląda gorzej)

Orion Edwards
źródło
3
Zgłaszam błędy dotyczące VS2010B1 dla każdego miejsca w interfejsie użytkownika tekst jest niewyraźny. Zgadzam się, podpowiedzi są prawie komicznie złe. Biorąc pod uwagę, jak wyraźnie powiedziano, że ma to zostać naprawione w WPF4, mogę tylko mieć nadzieję, że po prostu nie udało się to w tej wersji beta.
Will Dean
4

Wow, nie mogę uwierzyć, że w końcu moje czcionki WPF są czytelne. Nie mogę też uwierzyć, że nie ma okna dialogowego z opcjami, które ułatwiłoby te zmiany, podczas gdy domyślne wartości są okropne na moim ekranie.

Te ustawienia rejestru (w systemie dziesiętnym) działały dla mnie i są najbliższe mojej zwykłej czcionce zwykłej:

  • ClearTypeLevel: 10 (głównie aliasing w skali szarości)
  • GammaLevel: 1300 (wyższa gamma sprawiła, że ​​czcionka była zbyt cienka i widziałem kolory w aliasingu)
VVS
źródło
3

Mówią, że „SnapToDevicePixels = true” działa, ale nigdy nie widziałem żadnych dobrych wyników.

Z rozmytym tekstem walczę, przełączając się na inną czcionkę.

Oczywiście nie jest to rozwiązanie problemu, ale tak to obejrzałem.

Inisheer
źródło
Właśnie porównałem TextBlock z SnapToDevicePixels = "true" z jednym bez i nie było żadnej różnicy z czcionką Segoe UI w 12duis. Czy mogę zapytać, jakich czcionek używasz?
David Schmitt
Poprawiliśmy również sytuację, zmieniając naszą czcionkę. Czcionka, którą wybraliśmy, to Avenir (nie sądzę, że jest instalowana domyślnie, przynajmniej nie w systemie Windows XP).
cplotts
0

Jeśli wolisz używać klasy bazowej C # do dostosowywania okien dla swojej aplikacji (lub teraz masz ku temu powód), oto jak ustawić formatowanie tekstu, aby używał atrakcyjnego trybu wyświetlania:

public class SnappyWindow : Window
{
    public SnappyWindow()
    {
        SetValue(TextOptions.TextFormattingModeProperty, TextFormattingMode.Display);
    }
}
Edward Brey
źródło