(0) exportieren Drucken
Alle erweitern

Lernprogramm: Erste Schritte mit DirectWrite

In diesem Dokument erfahren Sie, wie Sie DirectWrite und Direct2D zum Erstellen von einfachem Text mit einer einzigen Formatierung und anschließend von Text mit mehreren Formatierungen verwenden.

Dieses Lernprogramm umfasst die folgenden Abschnitte:

Quellcode

Der in dieser Übersicht aufgeführte Quellcode ist dem DirectWrite-Beispiel "Hello World" entnommen. Jedes Teil wird in einer separaten Klasse implementiert (SimpleText und MultiformattedText) und in einem separaten untergeordneten Fenster angezeigt. Jede Klasse stellt ein Microsoft Win32-Fenster dar. Außer der WndProc-Methode enthält jede Klasse die folgenden Methoden:

FunktionBeschreibung
CreateDeviceIndependentResourcesErstellt geräteunabhängige Ressourcen, die überall wiederverwendet werden können.
DiscardDeviceIndependentResourcesGibt die geräteunabhängige Ressourcen frei, wenn sie nicht mehr benötigt werden.
CreateDeviceResourcesErstellt Ressourcen, wie z. B. Pinsel und Renderziele, die an ein bestimmtes Gerät gebunden sind.
DiscardDeviceResourcesGibt die geräteunabhängigen Ressourcen frei, wenn sie nicht mehr benötigt werden.
DrawD2DContentVerwendet Direct2D zum Rendern auf dem Bildschirm.
DrawTextZeichnet die Textzeichenfolge mit Direct2D.
OnResizeÄndert die Größe des Direct2D-Renderziels, wenn sich die Fenstergröße ändert.

 

Sie können anhand des bereitgestellten Beispiels oder der folgenden Anweisungen DirectWrite und Direct2D Ihrer eigenen Win32-Anwendung hinzufügen. Weitere Informationen zum Beispiel und den zugehörigen Projektdateien finden Sie unter dem DirectWriteHelloWorld-Beispiel.

Zeichnen von einfachem Text

In diesem Abschnitt wird erläutert, wie Sie DirectWrite und Direct2D zum Rendern eines einfachen Text mit nur einer Formatierung verwenden (siehe die nachfolgende Bildschirmabbildung).

Bildschirmabbildung von "Hello World using DirectWrite!" in einem einzelnen Format

Zum Zeichnen von einfachem Text auf dem Bildschirm sind vier Komponenten erforderlich:

  • Eine Zeichenfolge, die gerendert werden kann.
  • Eine Instanz von IDWriteTextFormat.
  • Die Abmessungen des Bereichs für den Text.
  • Ein Objekt, das den Text rendern kann. In diesem Lernprogramm wird ein Direct2D-Renderziel verwendet.

Die IDWriteTextFormat-Schnittstelle beschreibt den Schriftfamiliennamen, die Größe, den Schnitt, das Format und die Ausdehnung zum Formatieren von Text sowie Gebietsschema-Informationen. IDWriteTextFormat definiert darüber hinaus Methoden zum Festlegen und Abrufen der folgenden Eigenschaften:

  • Zeilenabstand
  • Textausrichtung relativ zum linken und rechten Rand des Layoutfelds
  • Absatzausrichtung relativ zum oberen und unteren Rand des Layoutfelds
  • Leserichtung
  • Zuschneidegranularität für Text, der über das Layoutfeld hinausragt
  • Inkrementeller Tabstopp
  • Absatzflussrichtung

Die IDWriteTextFormat-Schnittstelle ist zum Zeichnen von Text erforderlich, der die beiden in diesem Dokument beschriebenen Prozesse verwendet.

Bevor Sie ein IDWriteTextFormat-Objekt oder ein anderes DirectWrite-Objekt erstellen können, benötigen Sie eine IDWriteFactory-Instanz. Sie verwenden eine IDWriteFactory zum Erstellen von IDWriteTextFormat-Instanzen und anderen DirectWrite-Objekten. Um eine Factoryinstanz zu erhalten, verwenden Sie die DWriteCreateFactory-Funktion.

Abschnitt 1: Deklarieren von DirectWrite- und Direct2D-Ressourcen

In diesem Teil deklarieren Sie die Objekte, die Sie später zum Erstellen und Anzeigen von Text als private Datenmember der Klasse verwenden. Alle Schnittstellen, Funktionen und Datentypen für DirectWrite werden in der Headerdatei dwrite.h deklariert, und die für Direct2D werden in d2d1.h deklariert; wenn noch nicht geschehen, schließen Sie diese Header in das Projekt ein.

  1. Deklarieren Sie in der Klassenheaderdatei (SimpleText.h) die Zeiger auf die IDWriteFactory-Schnittstelle und IDWriteTextFormat-Schnittstelle als private Member.
    
    
    IDWriteFactory* pDWriteFactory_;
    IDWriteTextFormat* pTextFormat_;
    
    
    
    
  2. Deklarieren Sie Member, die die zu rendernde Textzeichenfolge und die Länge der Zeichenfolge beinhalten.
    
    
    const wchar_t* wszText_;
    UINT32 cTextLength_;
    
    
    
    
  3. Deklarieren Sie Zeiger auf die Schnittstellen ID2D1Factory, ID2D1HwndRenderTarget und ID2D1SolidColorBrush, um den Text mit Direct2D zu rendern.
    
    
    ID2D1Factory* pD2DFactory_;
    ID2D1HwndRenderTarget* pRT_;
    ID2D1SolidColorBrush* pBlackBrush_;
    
    
    
    

Abschnitt 2: Erstellen von geräteunabhängige Ressourcen

Direct2D stellt zwei Ressourcentypen zur Verfügung: geräteabhängige und geräteunabhängige Ressourcen. Geräteabhängige Ressourcen sind einem Renderinggerät zugeordnet und funktionieren nicht mehr, wenn dieses Gerät entfernt wird. Geräteunabhängige Ressourcen können dagegen können für Umfang der gesamten Anwendung bestehen bleiben.

DirectWrite-Ressourcen sind geräteunabhängig.

In diesem Abschnitt erstellen Sie die geräteunabhängigen Ressourcen, die von der Anwendung verwendet werden. Diese Ressourcen müssen mit einem Aufruf der Release-Methode der Schnittstelle freigegeben werden.

Einige der verwendeten Ressourcen müssen nur einmal erstellt werden und sind nicht an ein Gerät gebunden. Die Initialisierung dieser Ressourcen ist in der SimpleText::CreateDeviceIndependentResources-Methode enthalten, die beim Initialisieren der Klasse aufgerufen wird.

  1. Rufen Sie in der SimpleText::CreateDeviceIndependentResources-Methode in der Klassenimplementierungsdatei (SimpleText.cpp) die D2D1CreateFactory-Funktion auf, um eine ID2D1Factory-Schnittstelle zu erstellen, bei der es sich um die Stammfactoryschnittstelle für alle Direct2D-Objekte handelt. Sie verwenden die gleiche Factory zum Instanziieren anderer Direct2D-Ressourcen.
    
    
    hr = D2D1CreateFactory(
        D2D1_FACTORY_TYPE_SINGLE_THREADED,
        &pD2DFactory_
        );
    
    
    
    
  2. Rufen Sie die DWriteCreateFactory-Funktion auf, um eine IDWriteFactory-Schnittstelle zu erstellen, die die Stammfactoryschnittstelle für alle DirectWrite-Objekte ist. Sie verwenden die gleiche Factory zum Instanziieren anderer DirectWrite-Ressourcen.
    
    
    if (SUCCEEDED(hr))
    {
        hr = DWriteCreateFactory(
            DWRITE_FACTORY_TYPE_SHARED,
            __uuidof(IDWriteFactory),
            reinterpret_cast<IUnknown**>(&pDWriteFactory_)
            );
    }
    
    
    
    
  3. Initialisieren Sie die Textzeichenfolge, und speichern Sie ihre Länge.

    
    
    wszText_ = L"Hello World using  DirectWrite!";
    cTextLength_ = (UINT32) wcslen(wszText_);
    
    
    
    
  4. Erstellen Sie ein IDWriteTextFormat-Schnittstellenobjekt mit der IDWriteFactory::CreateTextFormat-Methode. Das IDWriteTextFormat gibt die Schriftart, den Schnitt, die Streckung, das Format und das Gebietsschema an, die zum Render der Textzeichenfolge verwendet werden.
    
    
    if (SUCCEEDED(hr))
    {
        hr = pDWriteFactory_->CreateTextFormat(
            L"Gabriola",                // Font family name.
            NULL,                       // Font collection (NULL sets it to use the system font collection).
            DWRITE_FONT_WEIGHT_REGULAR,
            DWRITE_FONT_STYLE_NORMAL,
            DWRITE_FONT_STRETCH_NORMAL,
            72.0f,
            L"en-us",
            &pTextFormat_
            );
    }
    
    
    
    
  5. Zentrieren Sie den Text horizontal und vertikal, indem Sie die IDWriteTextFormat::SetTextAlignment-Methode und IDWriteTextFormat::SetParagraphAlignment-Methode aufrufen.
    
    
    // Center align (horizontally) the text.
    if (SUCCEEDED(hr))
    {
        hr = pTextFormat_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
    }
    
    if (SUCCEEDED(hr))
    {
        hr = pTextFormat_->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
    }
    
    
    
    

In diesem Abschnitt initialisieren Sie die geräteunabhängigen Ressourcen, die von der Anwendung verwendet werden. Im nächsten Abschnitt initialisieren Sie die geräteabhängigen Ressourcen.

Abschnitt 3: Erstellen von geräteabhängige Ressourcen

In diesem Abschnitt erstellen Sie ein ID2D1HwndRenderTarget und einen ID2D1SolidColorBrush zum Rendern des Texts.

Ein Renderziel ist ein Direct2D-Objekt, mit dem Zeichnungsressourcen erstellt und Zeichenbefehle an ein Renderinggerät gerendert werden. Ein ID2D1HwndRenderTarget ist ein Renderziel, das auf einem HWND rendert.

Eine der Zeichnungsressourcen, die von einem Renderziel erstellt werden kann, ist ein Pinsel zum Zeichnen von Konturen, Füllungen und Text. Mit einem ID2D1SolidColorBrush wird mit einer Volltonfarbe gezeichnet.

Sowohl die ID2D1HwndRenderTarget-Schnittstelle als auch die ID2D1SolidColorBrush-Schnittstelle werden beim Erstellen an ein Renderinggerät gebunden und müssen freigegeben und neu erstellt werden, wenn das Gerät ungültig wird.

  1. Überprüfen Sie in der SimpleText::CreateDeviceResources-Methode, ob der Renderzielzeiger NULL ist. Wenn dies der Fall ist, rufen Sie die Größe des Renderingbereichs, und erstellen Sie ein ID2D1HwndRenderTarget dieser Größe. Verwenden Sie das ID2D1HwndRenderTarget, um einen ID2D1SolidColorBrush zu erstellen.
    
    
    RECT rc;
    GetClientRect(hwnd_, &rc);
    
    D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
    
    if (!pRT_)
    {
        // Create a Direct2D render target.
        hr = pD2DFactory_->CreateHwndRenderTarget(
                D2D1::RenderTargetProperties(),
                D2D1::HwndRenderTargetProperties(
                    hwnd_,
                    size
                    ),
                &pRT_
                );
    
        // Create a black brush.
        if (SUCCEEDED(hr))
        {
            hr = pRT_->CreateSolidColorBrush(
                D2D1::ColorF(D2D1::ColorF::Black),
                &pBlackBrush_
                );
        }
    }
    
    
    
    
  2. Geben Sie in der SimpleText::DiscardDeviceResources-Methode sowohl den Pinsel als auch das Renderziel frei.
    
    
    SafeRelease(&pRT_);
    SafeRelease(&pBlackBrush_);
    
    
    
    

Sie haben jetzt ein Renderziel und einen Pinsel erstellt und können diese zum Rendern des Texts verwenden.

Abschnitt 4: Zeichnen von Text mit der DrawText-Methode in Direct2D.

  1. Definieren Sie in der SimpleText::DrawText-Methode der Klasse den Bereich für das Textlayout, indem Sie die Abmessungen des Renderingbereichs abrufen, und erstellen Sie ein Direct2D-Rechteck mit den gleichen Abmessungen.
    
    
    D2D1_RECT_F layoutRect = D2D1::RectF(
        static_cast<FLOAT>(rc.left) / dpiScaleX_,
        static_cast<FLOAT>(rc.top) / dpiScaleY_,
        static_cast<FLOAT>(rc.right - rc.left) / dpiScaleX_,
        static_cast<FLOAT>(rc.bottom - rc.top) / dpiScaleY_
        );
    
    
    
    
  2. Verwenden Sie die ID2D1HwndRenderTarget::DrawText-Methode und das IDWriteTextFormat-Objekt, um Text auf dem Bildschirm zu rendern. Für die ID2D1HwndRenderTarget::DrawText-Methode werden folgende Parameter verwendet:
    • Eine Zeichenfolge, die gerendert werden soll.
    • Ein Zeiger auf eine IDWriteTextFormat-Schnittstelle.
    • Ein Direct2D-Layoutrechteck.
    • Ein Zeiger auf eine Schnittstelle, die ID2D1Brush verfügbar macht.
    
    
    pRT_->DrawText(
        wszText_,        // The string to render.
        cTextLength_,    // The string's length.
        pTextFormat_,    // The text format.
        layoutRect,       // The region of the window where the text will be rendered.
        pBlackBrush_     // The brush used to draw the text.
        );
    
    
    
    

Abschnitt 5: Rendern des Fensterinhalts mit Direct2D

Um den Fensterinhalt mit Direct2D zu rendern, wenn eine Meldung zum Zeichnen empfangen wird, gehen Sie wie folgt vor:

  1. Erstellen Sie die geräteabhängigen Ressourcen, indem Sie die in Abschnitt 3 implementierte SimpleText::CreateDeviceResources-Methode aufrufen.
  2. Rufen Sie die ID2D1HwndRenderTarget::BeginDraw-Methode des Renderingziels auf.
  3. Löschen Sie das Renderingziel, indem Sie die ID2D1HwndRenderTarget::Clear-Methode aufrufen.
  4. Rufen Sie die in Abschnitt 4 implementierte SimpleText::DrawText-Methode auf.
  5. Rufen Sie die ID2D1HwndRenderTarget::EndDraw-Methode des Renderziels auf.
  6. Falls notwendig, verwerfen Sie die geräteabhängigen Ressourcen, damit sie neu erstellt werden können, wenn das Fenster neu gezeichnet wird.


hr = CreateDeviceResources();

if (SUCCEEDED(hr))
{
    pRT_->BeginDraw();

    pRT_->SetTransform(D2D1::IdentityMatrix());

    pRT_->Clear(D2D1::ColorF(D2D1::ColorF::White));

    // Call the DrawText method of this class.
    hr = DrawText();

    if (SUCCEEDED(hr))
    {
        hr = pRT_->EndDraw(
            );
    }
}

if (FAILED(hr))
{
    DiscardDeviceResources();
}



Die SimpleText-Klasse wird in SimpleText.h und SimpleText.cpp implementiert.

Zeichnen von Text mit mehreren Formatierungen

In diesem Abschnitt wird erläutert, wie Sie DirectWrite und Direct2D zum Rendern von Text mit mehreren Formatierungen verwenden (siehe die nachfolgende Bildschirmabbildung).

Bildschirmabbildung von "Hello World using DirectWrite!" mit verschiedenen Formaten, Größen und Formatierungen

Der Code für diesen Abschnitt ist als MultiformattedText-Klasse im DWriteHelloWorld-Beispiel implementiert. Er basiert auf den Schritten im vorherigen Abschnitt.

Um Text mit mehreren Formatierungen zu erstellen, verwenden Sie die IDWriteTextLayout-Schnittstelle zusätzlich zur IDWriteTextFormat-Schnittstelle, die im vorherigen Abschnitt eingeführt wurde. Die IDWriteTextLayout-Schnittstelle beschreibt die Formatierung und das Layout eines Textblocks. Zusätzlich zur Standardformatierung, die von einem IDWriteTextFormat-Objekt angegeben wird, kann die Formatierung für bestimmte Textbereiche mit IDWriteTextLayout geändert werden. Dies schließt den Schriftfamiliennamen, die Größe, den Schnitt, das Format, die Streckung, die Durchstreichung und Unterstreichung ein.

IDWriteTextLayout stellt darüber hinaus die Treffertests-Methoden bereit. Die von diesen Methoden zurückgegebene Treffertests-Metrik ist relativ zum Layoutfeld, das angegeben wird, wenn das IDWriteTextLayout-Schnittstellenobjekt mit der CreateTextLayout-Methode der IDWriteFactory-Schnittstelle erstellt wird.

Die IDWriteTypography-Schnittstelle wird verwendet, um einem Textlayout optionale OpenType-Typographiefunktionen hinzuzufügen, z. B. Schwungbuchstaben und alternative stilistische Textsätze. Einem bestimmten Bereich des Texts können typographische Funktionen innerhalb eines Textlayouts hinzugefügt werden, indem die AddFontFeature-Methode der IDWriteTypography-Schnittstelle aufgerufen wird. Diese Methode empfängt eine DWRITE_FONT_FEATURE-Struktur als Parameter, der eine DWRITE_FONT_FEATURE_TAG-Enumerationskonstante und einen UINT32-Ausführungsparameter enthält. Eine Liste registrierter OpenType-Funktionen finden Sie auf microsoft.com unter OpenType Layout Tag Registry. Die entsprechenden DirectWrite-Enumerationskonstanten finden Sie unter DWRITE_FONT_FEATURE_TAG.

Abschnitt 1: Erstellen einer IDWriteTextLayout-Schnittstelle

  1. Deklarieren Sie einen Zeiger auf eine IDWriteTextLayout-Schnittstelle als Member der MultiformattedText-Klasse.
    
    
    IDWriteTextLayout* pTextLayout_;
    
    
    
    
  2. Erstellen Sie am Ende der MultiformattedText::CreateDeviceIndependentResources-Methode ein IDWriteTextLayout-Schnittstellenobjekt, indem Sie die CreateTextLayout-Methode aufrufen. Die IDWriteTextLayout-Schnittstelle stellt zusätzliche Formatierungsfunktionen bereit, z. B. die Fähigkeit, andere Formate für ausgewählte Teile des Texts zu übernehmen.
    
    
    // Create a text layout using the text format.
    if (SUCCEEDED(hr))
    {
        RECT rect;
        GetClientRect(hwnd_, &rect); 
        float width  = rect.right  / dpiScaleX_;
        float height = rect.bottom / dpiScaleY_;
    
        hr = pDWriteFactory_->CreateTextLayout(
            wszText_,      // The string to be laid out and formatted.
            cTextLength_,  // The length of the string.
            pTextFormat_,  // The text format to apply to the string (contains font information, etc).
            width,         // The width of the layout box.
            height,        // The height of the layout box.
            &pTextLayout_  // The IDWriteTextLayout interface pointer.
            );
    }
    
    
    
    

Abschnitt 2: Anwenden von Formatierungen mit IDWriteTextLayout.

Formatierungen, z. B. der Schriftgrad, der Schnitt und die Unterstreichung, können auf Teilzeichenfolgen des Texts angewendet werden , der mit der IDWriteTextLayout-Schnittstelle angezeigt werden soll.

  1. Set the font size for the substring "Di" of "DirectWrite" to 100 by declaring a DWRITE_TEXT_RANGE and calling the IDWriteTextLayout::SetFontSize method.
    
    // Format the "DirectWrite" substring to be of font size 100.
    if (SUCCEEDED(hr))
    {
        DWRITE_TEXT_RANGE textRange = {20,        // Start index where "DirectWrite" appears.
                                        6 };      // Length of the substring "Direct" in "DirectWrite".
        hr = pTextLayout_->SetFontSize(100.0f, textRange);
    }
    
    
    
  2. Unterstreichen Sie die Teilzeichenfolge "DirectWrite", indem Sie die IDWriteTextLayout::SetUnderline-Methode aufrufen.
    
    // Format the word "DWrite" to be underlined.
    if (SUCCEEDED(hr))
    {
        
        DWRITE_TEXT_RANGE textRange = {20,      // Start index where "DirectWrite" appears.
                                       11 };    // Length of the substring "DirectWrite".
        hr = pTextLayout_->SetUnderline(TRUE, textRange);
    }
    
    
    
  3. Legen Sie den Schriftschnitt für die Teilzeichenfolge "DirectWrite" durch das Aufrufen der IDWriteTextLayout::SetFontWeight-Methode als "Fett" fest.
    
    if (SUCCEEDED(hr))
    {
        // Format the word "DWrite" to be bold.
        DWRITE_TEXT_RANGE textRange = {20,
                                       11 };
        hr = pTextLayout_->SetFontWeight(DWRITE_FONT_WEIGHT_BOLD, textRange);
    }
    
    
    

Abschnitt 3: Hinzufügen von typographischen Funktionen mit IDWriteTypography

  1. Deklarieren und Erstellen Sie ein IDWriteTypography-Schnittstellenobjekt, indem Sie die IDWriteFactory::CreateTypography-Methode aufrufen.
    
    
    // Declare a typography pointer.
    IDWriteTypography* pTypography = NULL;
    
    // Create a typography interface object.
    if (SUCCEEDED(hr))
    {
        hr = pDWriteFactory_->CreateTypography(&pTypography);
    }
    
    
    
    
  2. Fügen Sie eine Schriftartfunktion hinzu, indem Sie ein DWRITE_FONT_FEATURE-Objekt deklarieren, für das der Stilsatz 7 festgelegt ist, und die IDWriteTypography::AddFontFeature-Methode aufrufen.
    
    
    // Set the stylistic set.
    DWRITE_FONT_FEATURE fontFeature = {DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_7,
                                       1};
    if (SUCCEEDED(hr))
    {
        hr = pTypography->AddFontFeature(fontFeature);
    }
    
    
    
    
  3. Legen Sie das Textlayout so fest, dass die Typographie für die gesamte Zeichenfolge angewendet wird, indem Sie eine DWRITE_TEXT_RANGE-Variable deklarieren und die IDWriteTextLayout::SetTypography-Methode aufrufen sowie den Textbereich übergeben.
    
    
    if (SUCCEEDED(hr))
    {
        // Set the typography for the entire string.
        DWRITE_TEXT_RANGE textRange = {0,
                                       cTextLength_};
        hr = pTextLayout_->SetTypography(pTypography, textRange);
    }
    
    
    
    
  4. Legen Sie die neue Breite und Höhe des Textlayoutobjekts in der MultiformattedText::OnResize-Methode fest.
    
    if (pTextLayout_)
    {
        pTextLayout_->SetMaxWidth(static_cast<FLOAT>(width / dpiScaleX_));
        pTextLayout_->SetMaxHeight(static_cast<FLOAT>(height / dpiScaleY_));
    }
    
    
    

Abschnitt 4: Zeichnen von Text mit der Direct2D-Methode DrawTextLayout.

Um den Text mit den vom IDWriteTextLayout-Objekt angegebenen Textlayouteinstellungen zu zeichnen, ändern Sie den Code in der MultiformattedText::DrawText-Methode, sodass IDWriteTextLayout::DrawTextLayout verwendet wird.

  1. Deklarieren Sie eine D2D1_POINT_2F-Variable, und legen Sie sie auf den linken oberen Punkt des Fensters fest.
    
    
    D2D1_POINT_2F origin = D2D1::Point2F(
        static_cast<FLOAT>(rc.left / dpiScaleX_),
        static_cast<FLOAT>(rc.top / dpiScaleY_)
        );
    
    
    
    
  2. Zeigen Sie den Text durch Aufrufen der ID2D1RenderTarget::DrawTextLayout-Methode des Direct2D-Renderingziels und Übergeben des IDWriteTextLayout-Zeigers auf dem Bildschirm an.
    
    
    pRT_->DrawTextLayout(
        origin,
        pTextLayout_,
        pBlackBrush_
        );
    
    
    
    

Die MultiformattedText-Klasse wird in MultiformattedText.h und MultiformattedText.cpp implementiert.

 

 

Anzeigen:
© 2014 Microsoft