2010-12-10 6 views
6

Dies ist eine Frage in Bezug auf eine sehr einfache Konstruktion zu machen - ich habe folgendes XAML:TextBlock- innerhalb einer Viewbox - seltsam

<Viewbox Height="100" Stretch="Uniform"> 
     <TextBlock FontFamily="Georgia">My Cool Text</TextBlock> 
    </Viewbox> 

Das ist ganz einfach zu verstehen. Aber wenn ich das Programm starte, bekomme ich seltsamen verschwommenen Text (in meinem Projekt gibt es keine Bitmap-Effekte). alt text

(linke Seite - die Designeransicht in VS2010, rechte Seite - die laufende Anwendung)

Hat jemand irgendwelche Vorschläge, warum dies geschieht ??

+0

sieht perfekt auf meiner Maschine –

+0

Sieht gut aus auf meiner Maschine, auch !! Welche Version von WPF verwenden Sie? Können Sie es in einem neuen Fenster testen, da es nur Inhalt ist? – decyclone

+0

Ja, es sieht gut aus, wenn ich eine neue App erstelle, die nur diesen Code enthält. Ich weiß das :) Das Problem ist, dass ich keine Ahnung habe, wie ich zu dieser verschwommenen Dehnung gekommen bin. Irgendwo ist etwas, und ich habe keine Ahnung, womit ich anfangen soll. Es ist auch nicht die beste Idee, den gesamten Code/die Ressourcen zu veröffentlichen - es gibt einfach zu viel. – Jefim

Antwort

27

Während Jefim seine eigene Frage richtig beantwortet hat, wollte ich erklären, warum Sie dieses Verhalten bei der Verwendung dieser speziellen Funktionen bekommen. Jefim schlägt vor, dass dies ein Fehler in WPF ist, aber es ist nicht. Das Problem entsteht dadurch, dass WPF aufgefordert wird, etwas Unmögliches zu tun. Es muss einen Kompromiss wählen, wenn Sie nach dieser unmöglichen Sache gefragt haben, und das Ergebnis ist, was Sie oben sehen.

Die Erklärung ist ein bisschen lang für einen Kommentar, weshalb ich es in eine separate Antwort setze.

In diesem Beispiel werden zwei widersprüchliche Features von WPF verwendet. Diese Merkmale sind:

  1. Die Fähigkeit, visuals konsequent in jedem Maßstab
  2. Die Fähigkeit zu machen Text in gleicher Weise GDI32 macht Text

Sie können nicht beide Funktionen gleichzeitig nutzen zu machen. GDI32 rendert Text in einer Weise, die nicht konsistent skaliert werden kann: Wenn ein bestimmter Text in einer bestimmten Schriftgröße 200 Pixel breit ist, wenn Sie die Schriftgröße mit 3 multiplizieren und denselben Text in der gleichen Schriftfamilie wiedergeben diese neue Schriftgröße, in GDI32 wird es wahrscheinlich nicht 600 Pixel sein - es wird nah sein, aber es wird in der Regel nicht ganz richtig sein.

GDI32 verwechselt die Formen und Breiten von Zeichen, um die Klarheit und Schärfe des Textes zu verbessern. Insbesondere werden Buchstaben aus der Form herausgebogen, so dass ihre Features besser mit den Pixeln auf Ihrem Bildschirm übereinstimmen. Und wo es nötig ist, passt es die Breite einzelner Zeichen an, um eine exakte Anzahl von Pixeln zu erhalten. Da dieses Buchstabenbiegen auf tatsächlichen Pixeln basiert, biegt es den Text auf verschiedene Arten in verschiedenen Schriftgrößen.

Während das Ihnen schön scharfen Text gibt, sieht es absolut schrecklich aus, wenn Sie versuchen, die Skala allmählich zu ändern. Wenn Sie versuchen, die Schriftgröße eines auf diese Weise gerenderten Textes zu animieren, wird das Ding schillern und zittern, weil die im Namen der Klarheit vorgenommenen Anpassungen bei jeder Schriftgröße leicht unterschiedlich ausfallen.Auch wenn Sie nicht animieren, kann es immer noch zu schlechten Ergebnissen führen - wenn Sie eine einzelne Schrift in mehreren Größen haben, kann sie bei jeder Größe anders aussehen; Wenn Ihre Anwendung über eine Zoomfunktion verfügt, kann sich der Charakter des Textes beim Vergrößern und Verkleinern erheblich verändern. (Und auch das Layout. Wenn Sie Microsoft Word verwenden, haben Sie vielleicht bemerkt, dass Sie manchmal merkwürdig aussehende, besonders breite Leerzeichen zwischen bestimmten Wörtern sehen. Dies ist das Ergebnis von Word, das mit GDI32 kämpft - Word versucht, das Layout auf dem Bildschirm beizubehalten so nah wie möglich an die Dinge beim Drucken, was bedeutet, dass es manchmal mit GDI32 Gitter Anpassung kollidiert.)

So WPF bietet eine andere Herangehensweise an Text-Rendering: es kann Text so treu wie möglich zu machen zum ursprünglichen Design der Schriftart. Dies verzerrt den Text weniger und es bedeutet, dass Sie beim Skalieren keine Diskontinuitäten erhalten.

Der Nachteil ist, dass der Text verschwommen aussieht, verglichen mit dem Text, der von GDI32 gerendert wird. (Die von GDI32 vorgenommenen Verzerrungen zielen alle auf eine Verbesserung der Übersichtlichkeit ab.)

So fügte Microsoft in WPF 4.0 die Fähigkeit hinzu, Text so zu rendern, wie GDI32 dies tun würde. Das macht TextOptions.TextFormattingMode="Display".

Wenn Sie diese Option aktivieren, sagen Sie: "Ich brauche keine konsistente Skalierung, und ich bevorzuge Klarheit, also erzeuge die gleichen Pixel wie in GDI32." Wenn Sie dann die Skalierung anwenden, nachdem Sie WPF gesagt haben, dass Sie keine Skalierbarkeit benötigen, erhalten Sie beschissene Ergebnisse. WPF hat sorgfältig eine Bitmap-Darstellung des Textes genau nach Ihren Vorgaben erstellt und Sie dann aufgefordert, diesen Text in einem anderen Maßstab darzustellen. Und so sieht es aus wie es ist: eine skalierte Bitmap eines Textes, der für eine andere Auflösung erzeugt wurde.

Sie könnten argumentieren, dass WPF hier etwas anderes machen könnte: Wenn Sie eine Maßstabsumwandlung in GDI32 anwenden, würden Sie ein anderes Verhalten sehen - Sie würden die Inkonsistenz auf verschiedenen Skalen sehen, die früher beschrieben wurden. Wenn Sie diesen Effekt in WPF wirklich möchten, können Sie ihn direkt durch Ändern der Schriftgröße erhalten. Aber WPF priorisiert nicht den gleichen Effekt - seine Ziele sind, dass es möglich ist, GDI32-gestochen scharfen Text zu erhalten, wenn Sie ihn wirklich brauchen, und standardmäßig konsistente Skalierung bereitzustellen.

Und was Sie hier laufen, ist die "konsistente Skalierung". Durch das Aktivieren des Text-Renderings im GDI32-Stil wird die konsistente Skalierung nicht beeinträchtigt: Durch das Anwenden eines Skalierungsfaktors (entweder direkt über oder indirekt über Viewbox) werden die Dimensionen des visuellen Objekts um genau den angegebenen Skalierungsfaktor geändert. Wenn es die Textdarstellungen durch ein Gitter neu erzeugen würde, das an die neu skalierte Größe angepasst wäre, würde der Text in einer anderen Breite erscheinen. Das würde die Viewbox Probleme tatsächlich verursachen: es wendet einen Maßstabsfaktor an, der auf der natürlichen Größe des Inhalts basiert, entworfen, um es dem verfügbaren Speicherplatz anzupassen. Aber wenn das Gitter nach der Skalierung wieder passt, würde das tatsächlich die Breite ändern. Aufgrund der Inkonsistenzen, die dem GDI32-Text-Rendering innewohnen, ist es für den ViewBox möglicherweise nicht einmal möglich, eine geeignete Skala zu finden - es ist möglich, einen Text zu erstellen, der in einer bestimmten Schriftart nicht ausgegeben wird bei 200 Pixel breit. Bei einigen Schriftgrößen kann die Rundung, die der Rasteranpassung innewohnt, die Größe beispielsweise auf 198 herabsetzen, und es bleibt möglicherweise bei kleinen Schritten der Schriftgröße bestehen, bis Sie einen Schwellenwert überschreiten, an dem es springen kann bis 202 Pixel.

Für einen Viewbox Versuch, den Text zu zwingen, in genau 200 Pixel zu passen, würde das ein Problem sein. Aber Viewbox funktioniert nicht auf diese Weise - es verwendet WPF konsistente Skalierung, nach dem Punkt, an dem Sie die Schriftgröße, mit der GDI32-style-Text-Rendering funktioniert. So wird Viewbox immer in der Lage sein, zu tun, wofür es entwickelt wurde, aber das ist eine Aufgabe, die grundsätzlich mit dem GDI32-Stil-Text-Rendering inkompatibel ist.

Kurz gesagt, WPF rendert den Text für die gewünschte Schriftgröße und skaliert das Ergebnis.

Sie müssen also nur ein Merkmal auswählen - Sie können nicht beide haben, weil das einfach unmöglich ist. Versuchen Sie nicht, Text in einem Kontext zu rendern, in dem ein beliebiger Skalierungsfaktor angewendet werden kann (z. B. Viewbox) oder schalten Sie Textdarstellung im GDI32-Stil nicht ein. Sonst bekommst du diesen seltsamen pixeligen Text, den du gesehen hast.

+0

Danke für diesen "Kommentar" - es ist sehr interessant zu lesen. Ich nenne es als Antwort, weil es sich lohnt. Was meine Formulierung eines "Bugs" angeht - Ihre Erklärung hat mir einiges klar gemacht. Jetzt werde ich nur sagen - das sollte auf MSDN-Dokumenten sein. Wirklich, denn das ist nicht so offensichtlich (zumindest für mich) und ich musste einige Stunden verbringen, bevor ich mich der Ursache des Problems zuwandte. Wie auch immer, danke nochmal für die Antwort. – Jefim

+0

@lan Griffiths thx, möchte ich wissen, ob ich das Element bekommen kann, dass in ViewBox seine tatsächliche Größe geändert hat? Die tatsächliche Größe ist das Element, das im Bildschirm nicht ActualSize angezeigt wird. Und ich poste in http://stackoverflow.com/questions/42411455/how-to-know-the-element-actual-size-have-change-by-other-control?noredirect – lindexi

8

Ok, Fehler gefunden. My Window-Stil hat den folgenden Setzer:

<Setter Property="TextOptions.TextFormattingMode" Value="Display"/> 

Wenn ich es wieder auf „Ideal“ gesetzt (das ist der Standardwert ist), dann macht es den Text innerhalb des Sichtgerätes richtig. Ich würde sagen, dass dies ein Bug in WPF ist. Grundsätzlich, wenn Sie dies versuchen:

<Viewbox Height="100" Stretch="Uniform" TextOptions.TextFormattingMode="Display"> 
    <TextBlock FontFamily="Georgia">My Cool Text</TextBlock> 
</Viewbox> 

Sie erhalten das gleiche Ergebnis wie in meinem ersten Bild.

Verwandte Themen