www.rolandk.de
- Aktuelle Themen zu .Net -
Achtung: Hier handelt es sich um meine alte Seite.
Die aktuelle ist unter folgendem Link erreichbar: www.rolandk.de/wp/
Home Tutorials Direct2D und DirectWrite Chapter 3 - Texte mit DirectWrite




















































Chapter 3 - Texte mit DirectWrite
Donnerstag, den 29. Juli 2010 um 17:53 Uhr

 

 

DirectWrite

Da wir in den letzten Kapiteln nur einfache Rechtecke gezeichnet haben, wird jetzt mal Zeit für etwas komplexeres. Text ist in System.Drawing relativ primitiv abgebildet. Es gibt irgendwo Font-Objekte und über Graphics.DrawString können damit Texte mit einer frei wählbaren Schriftart gezeichnet werden. Probleme entstehen allerdings schnell, wenn man etwa automatische Zeilenumbrüche, Darstellung als Blocksatz oder dergleichen realisieren möchte. Solche Funktionen müssen manuell vom Entwickler programmiert werden. Im Gegensatz dazu wird einem diese Arbeit in DirectWrite von vorneherein abgenommen. Direct2D und DirectWrite sind - anders als es die verschiedenen Bezeichnungen vermuten lassen - nahtlos miteinander verknüpft, somit kann man die Beiden auch als eine Einheit betrachten.

 

Initialisierung von DirectWrite

Ähnlich wie bei Direct2D gibt es auch bei DirectWrite eine Factory Klasse, von der man zuerst ein Objekt erzeugen muss. Folgender Code zeigt das kurz:

  1. m_factoryWrite = new DWrite.Factory(DWrite.FactoryType.Shared);

Über den FactoryType kann man festlegen, ob die von dieser Factory erzeugten Objekte auch von Objekten verwendet werden können, welche von einer anderen Factory stammen. Standardwert ist hier ganz einfach Shared.

 

Mithilfe der Factory können wir jetzt ein TextFormat Objekt erzeugen. Die Klasse TextFormat kann man vergleichen mit Font aus System.Drawing, da hierin unter anderem die Schriftart festgelegt wird. Man kann aber noch mehr angeben, wie beispielsweise die Ausrichtung des Textes oder die Schreibrichtung. Folgender Codeausschnitt erzeugt das TextFormat Objekt, welches für den Text "Hello World using DirectWrite!" oben im Screenshot zuständig ist:

  1. //Create DirectWrite resources
  2. m_textFormatCentered = m_factoryWrite.CreateTextFormat(
  3. "Gabriola",
  4. DWrite.FontWeight.Normal, DWrite.FontStyle.Normal, DWrite.FontStretch.Normal,
  5. 72f, "de-de");
  6. m_textFormatCentered.TextAlignment = DWrite.TextAlignment.Center;
  7. m_textFormatCentered.ParagraphAlignment = DWrite.ParagraphAlignment.Center;

Nichts Besonderes, wie man sieht. Hier wird ein TextFormat mit der Schriftart "Gabriola" und der Schriftgröße 72 erstellt. Zusätzlich stellen wir TextAlignment und ParagraphAlignment auf Center, damit der Text zentriert dargestellt wird.

 

Text zeichnen

Da wir jetzt ein TextFormat Objekt haben, stellt sich die Frage, wie wir damit Text auf das Direct2D RenderTarget bekommen. Die Antwort ist sehr einfach, denn das RenderTarget bietet uns die Methode DrawText:

  1. //Draw simple text
  2. m_renderTarget.DrawText(
  3. "Hello World using DirectWrite!", m_textFormatCentered,
  4. new Rectangle(new Point(), this.Size), m_blackBrush);

Grundsätzlich funktioniert das sehr ähnlich der Graphics.DrawString Methode von System.Drawing. Ein großer Unterschied ist aber der 3. Übergabeparameter. Und zwar wird ein Rechteck übergeben, in dem der Text gezeichnet werden soll. In diesem Textblock wird der Text dann je nach Einstellung im TextFormat Objekt zentriert, linksbündig oder rechtsbündig dargestellt. Auch Zeilenumbrüche und andere ähnliche Funktionen sind problemlos möglich.

 

Textlayouts vorberechnen

Das eben beschriebene Vorgehen ist ein großer Vorteil gegenüber der Funktionen von System.Drawing. Eine Sache ist aber eher etwas ungünstig: Die genaue Position des Textes und aller enthaltender Wörter wird jedes Mal beim Zeichnen neu berechnet, weil das übergebene Rechteck theoretisch immer eine andere Größe haben kann. Um das endgültige Layout von DirectWrite vorberechnen zu lassen, gibt es die Klasse TextLayout:

  1. m_textFormatFlow = m_factoryWrite.CreateTextFormat(
  2. "Arial",
  3. DWrite.FontWeight.Normal, DWrite.FontStyle.Normal, DWrite.FontStretch.Normal,
  4. 20f, "de-de");
  5. m_textFormatFlow.TextAlignment = DWrite.TextAlignment.Leading;
  6. m_textFormatFlow.ParagraphAlignment = DWrite.ParagraphAlignment.Near;
  7.  
  8. m_textLayoutFlow = m_factoryWrite.CreateTextLayout(
  9. TEXT_TOP_RIGHT, m_textFormatFlow,
  10. 400f, 100f);

Hier erzeugen wir ein neues TextLayout mit der Schriftart Arial. Danach wird ein TextLayout erzeugt, dem wir bereits den darzustellenden Text (steht in der Konstante TEXT_TOP_RIGHT) und die Größe des Layoutrechtecks mitgeben. Somit kann Direct3D alle Berechnungen, die für die Darstellung notwendig sind, bereits durchführen. Folgender Programmcode zeigt beide Varianten, das Zeichnen mit einem TextFormat und das Zeichnen mit einem TextLayout (Das Ergebnis ist oben im Screenshot sichtbar):

  1. //Render top left rectangle
  2. {
  3. Rectangle textRect = new Rectangle(
  4. 10, 10,
  5. this.Width / 2 - 20, this.Height / 3 - 20);
  6.  
  7. m_renderTarget.DrawText(
  8. TEXT_TOP_LEFT,
  9. m_textFormatFlow,
  10. textRect, m_blackBrush,
  11. D2D.DrawTextOptions.Clip, DWrite.MeasuringMethod.Natural);
  12. }
  13.  
  14. //Render top right rectangle
  15. {
  16. Point topRight = new Point(this.Width / 2 + 10, 10);
  17. m_renderTarget.DrawTextLayout(topRight, m_textLayoutFlow, m_blackBrush, D2D.DrawTextOptions.Clip);
  18. }

Wie man sieht, braucht der DrawTextLayout Methode kein Rechteck und kein String mehr übergeben werden, sondern nur noch eine Startkoordinate und eben der verwendete Brush. Mit dem DrawTextOptions.Clip Wert sagen wir Direct2D übrigens, dass nicht über die Grenzen des Layoutrechtecks hinaus gezeichnet werden darf. Standardmäßig würde Direct2D das nämlich tun.

 

Weiter geht's

In diesem Kapitel haben wir einige Grundsätzliche Features von DirectWrite behandelt und gezeigt, dass es hier Gegenüber System.Drawing auch sehr nützliche Fortschritte gibt. Im nächsten Kapitel werde ich schließlich noch beschreiben, wie Bitmaps in Direct2D geladen und gezeichnet werden können.

 

Quellen

  • DirectX SDK
    Die Beispiele und die Dokumentation im DirectX SDK sind zwar auf C++ ausgelegt, da sich SlimDX stark an der originalen API orientiert, ist das SDK aber dennoch sehr hilfreich.
  • Msdn
    Auf Msdn findet man eine sehr umfangreiche Hilfe zu Direct2D und DirectWrite.
  • SlimDX
    Hauptseite des SlimDX-Projekts.

 

Siehe auch...

 

Kommentar hinzufügen

Ihr Name:
Kommentar: