2010-04-08 12 views
6

Mam aplikację C#, która renderuje tekst, coś na równi z prostym edytorem tekstu WYSIWYG.TextRenderer.DrawText renderuje Arial inaczej na XP vs Vista

Używam TextRenderer.DrawText do renderowania tekstu na ekranie i GetTextExtentPoint32 do pomiaru tekstu, dzięki czemu mogę ustawić różne style/rozmiary czcionek w tej samej linii.

W systemie Vista wszystko działa poprawnie. W XP jednak Arial renderuje się inaczej, niektóre znaki takie jak "o" i "b" zajmują więcej szerokości niż w Vista. Wydaje się, że GetTextExtentPoint32 mierzy ciąg znaków w taki sposób, jak w Vista, o mniejszych szerokościach. Końcowym rezultatem jest to, że co jakiś czas bieg tekstu pokrywa się z tekstem poprzedzającym go, ponieważ poprzedni tekst jest mierzony jako mniejszy niż faktycznie znajduje się na ekranie.

Ponadto, mój kod renderujący tekst jest dokładnie taki, jak np. Renderowanie tekstu (tylko dla prostego formatowania i języka angielskiego), a więc renderowanie tekstu wydaje się być spójne między vistem i xp - tak zauważyłem zmianę rozmiaru różnych znaków.

Ktoś ma jakieś pomysły na temat tego, co się dzieje?

Krótko mówiąc, TextRenderer.DrawText i GetTextExtentPoint32 nie pasują do Xp dla Arial. DrawText wydaje się rysować pewne znaki większe i/lub mniejsze niż w Vista, ale GetTextExtentPoint32 wydaje się mierzyć tekst tak, jak w systemie Vista (co wydaje się pasować do renderowania tekstu w np. Na XP i Vista). Mam nadzieję, że ma to sens.

Uwaga: niestety TextRenderer.MeasureString nie jest wystarczająco szybki i dokładny, aby spełnić moje wymagania. Próbowałem go użyć i musiałem go zgrać.

+0

+1 Ponieważ wiem, z czym masz do czynienia! A miałem tylko do czynienia z czcionkami o stałej szerokości. – leppie

+0

Jesteś pewien, że nie jest to problem typu DPI lub Cleartype? –

Odpowiedz

0

Nie jestem facetem C#, ale wierzę, że renderowanie .NET jest oparte na GDI +. Jestem również całkiem pewien, że GDI + wykonuje własne renderowanie czcionek, które wykorzystuje nieodmienione skalowanie.

GetTextExtentPoint32, z drugiej strony, jest częścią GDI. GDI używa wskazówek dotyczących zmiany rozmiaru, które mogą wpływać na szerokość znaków w zależności od rozmiaru czcionki. Ogólnie tekst GDI o małych rozmiarach będzie wyglądał na nieco pochłaniający, ale nie będzie skalowany liniowo.

Musisz konsekwentnie używać jednego lub drugiego modelu, aby uzyskać doskonałe wyniki w pikselach.

W grze mogą występować inne czynniki, które mogą sprawić, że stanie się to bardziej oczywiste niż w systemie Windows Vista, ale podstawowy problem występuje w obu systemach. Te inne czynniki mogą obejmować ustawienia DPI, skalowanie DPI, ustawienia ClearType lub antyaliasingu, łączenie czcionek (w przypadku miksowania skryptów z innych alfabetów), zastępowanie czcionek (zwłaszcza w druku) i ewentualnie różne wersje Arial. Nie jestem nawet pewien, czy GDI + używa tego samego domyślnego trybu mapowania, co GDI.

Zobacz także my answer on print preview.

2

Dzięki za poświęcenie czasu na odpowiedź Adriana.

Rozumiem, że TextRenderer.DrawText faktycznie opakowuje wywołanie do GDI, całkowicie ominąwszy renderowanie tekstu GDI +. Właśnie dlatego byłem zdezorientowany, ponieważ GetTextExtentPoint32 nie jiving z wyjściem.

Myślę, że znalazłem problem. Okazuje się, że jeśli ustawisz Graphics.TextRenderingHint na System.Drawing.Text.TextRenderingHint.ClearTypeGridFit lub ewentualnie inne wartości, spowoduje to, że niektóre znaki w niektórych czcionkach zwiększą lub zmniejszą rozmiar. Wydaje się to być prawdą bardziej w XP niż w Vista. W Vista nie widziałem tego w ogóle.W każdym razie wygląda na to, że GetTextExtentPoint32 nie jest w stanie rozpoznać różnicy lub nie ustawiam flagi podczas wykonywania połączenia.

Moim rozwiązaniem jest użycie domyślnych ustawień textrenderinghint.

+0

Wygląda dobrze. Znalazłem tu dobre informacje (ale on również podaje wątpliwe twierdzenia, więc uważaj). http://blogs.msdn.com/cjacks/archive/2006/05/11/595525.aspx –

0

Właściwie zarówno DrawText TextRenderer i MeasureString na podstawie DrawTextEx (a to jest User32, a nie funkcja Gdi). Możesz więc rozważyć użycie natywnych wywołań marshalled do tej funkcji zamiast MeauseString, ponieważ wykonuje on dodatkowe obliczenia (szczególnie jeśli używasz zastąpienia funkcji bez HDC).

Być może ta post będzie również pomocna.

Powiązane problemy