Dela via


Självstudie: Komma igång med DirectWrite

Det här dokumentet visar hur du använder DirectWrite och Direct2D- för att skapa enkel text som innehåller ett enda format och sedan text som innehåller flera format.

Den här självstudien innehåller följande delar:

Källkod

Källkoden som visas i den här översikten är hämtad från DirectWrite Hello World-exempel. Varje del implementeras i en separat klass (SimpleText och MultiformattedText) och visas i ett separat underordnat fönster. Varje klass representerar ett Microsoft Win32-fönster. Förutom metoden WndProc innehåller varje klass följande metoder:

Funktion Beskrivning
SkapaEnhetsOberoendeResurser Skapar resurser som är enhetsoberoende, så att de kan återanvändas var som helst.
KasseraResurserOberoendeAvEnhet Släpper de enhetsoberoende resurserna när de inte längre behövs.
SkapaEnhetsResurser Skapar resurser, till exempel penslar och återgivningsmål, som är knutna till en viss enhet.
DiscardDeviceResources Frigör de enhetsberoende resurserna när de inte längre behövs.
DrawD2DContent Använder Direct2D- för att rendera till skärmen.
DrawText Ritar textsträngen med hjälp av Direct2D-.
OnResize Ändrar storlek på Direct2D- återgivningsmål när fönsterstorleken ändras.

 

Du kan använda exemplet eller använda anvisningarna nedan för att lägga till DirectWrite- och Direct2D- i ditt eget Win32-program. Mer information om exemplet och de associerade projektfilerna finns i DirectWrite HelloWorld-.

Skapa enkel text

Det här avsnittet visar hur du använder DirectWrite- och Direct2D- för att återge enkel text som har ett enda format, enligt följande skärmbild.

skärmdump av

För att kunna rita enkel text på skärmen krävs fyra komponenter:

  • En teckensträng som ska återges.
  • En instans av IDWriteTextFormat.
  • Dimensionerna för det område som ska innehålla texten.
  • Ett objekt som kan återge texten. I den här handledningen. du använder ett Direct2D- återgivningsmål.

Gränssnittet IDWriteTextFormat beskriver teckensnittsfamiljens namn, storlek, vikt, stil och stretch som används för att formatera text och beskriver språkinformation. IDWriteTextFormat definierar även metoder för att ange och hämta följande egenskaper:

  • Radavståndet.
  • Textjusteringen i förhållande till layoutrutans vänstra och högra kanter.
  • Styckejusteringen i förhållande till layoutrutans över- och nederkant.
  • Läsriktningen.
  • Granularitet för textbeskärning för text som inte får plats i layoutrutan.
  • Den inkrementella fliken stoppas.
  • Styckeflödesriktningen.

Gränssnittet IDWriteTextFormat krävs för att rita text som använder båda processerna som beskrivs i det här dokumentet .

Innan du kan skapa ett IDWriteTextFormat--objekt eller något annat DirectWrite--objekt behöver du en IDWriteFactory--instans. Du använder en IDWriteFactory för att skapa IDWriteTextFormat-instanser och andra DirectWrite-objekt. Om du vill hämta en fabriksinstans använder du funktionen DWriteCreateFactory.

Del 1: Deklarera DirectWrite- och Direct2D-resurser.

I den här delen deklarerar du de objekt som du kommer att använda senare för att skapa och visa text som privata datamedlemmar i klassen. Alla gränssnitt, funktioner och datatyper för DirectWrite deklareras i dwrite.h-huvudfilen och de för Direct2D- deklareras i d2d1.h; Om du inte redan har gjort det kan du inkludera dessa rubriker i projektet.

  1. I klasshuvudfilen (SimpleText.h) deklarerar du pekare till IDWriteFactory- och IDWriteTextFormat gränssnitt som privata medlemmar.

    IDWriteFactory* pDWriteFactory_;
    IDWriteTextFormat* pTextFormat_;
    
    
  2. Deklarera medlemmar som ska innehålla textsträngen som ska visas och längden på strängen.

    const wchar_t* wszText_;
    UINT32 cTextLength_;
    
    
  3. Deklarera pekare till ID2D1Factory, ID2D1HwndRenderTargetoch ID2D1SolidColorBrush-gränssnitt för att återge texten med Direct2D-.

    ID2D1Factory* pD2DFactory_;
    ID2D1HwndRenderTarget* pRT_;
    ID2D1SolidColorBrush* pBlackBrush_;
    
    

Del 2: Skapa enhetsoberoende resurser.

Direct2D- innehåller två typer av resurser: enhetsberoende resurser och enhetsoberoende resurser. Enhetsberoende resurser är associerade med en återgivningsenhet och fungerar inte längre om enheten tas bort. Enhetsoberoende resurser kan å andra sidan vara inom ramen för ditt program.

DirectWrite- resurser är enhetsoberoende.

I det här avsnittet skapar du de enhetsoberoende resurser som används av ditt program. Dessa resurser måste frigöras med ett anrop till metoden Release i gränssnittet.

Vissa av de resurser som används måste bara skapas en gång och är inte knutna till en enhet. Initieringen för dessa resurser placeras i metoden SimpleText::CreateDeviceIndependentResources, som anropas när klassen initieras.

  1. I metoden SimpleText::CreateDeviceIndependentResources i klassimplementeringsfilen (SimpleText.cpp) anropar du funktionen D2D1CreateFactory för att skapa ett ID2D1Factory--gränssnitt, som är rotfabriksgränssnittet för alla Direct2D- objekt. Du använder samma fabrik för att instansiera andra Direct2D-resurser.

    hr = D2D1CreateFactory(
        D2D1_FACTORY_TYPE_SINGLE_THREADED,
        &pD2DFactory_
        );
    
    
  2. Anropa funktionen DWriteCreateFactory för att skapa ett IDWriteFactory--gränssnitt, som är rotfabriksgränssnittet för alla DirectWrite- objekt. Du använder samma fabrik för att instansiera andra DirectWrite-resurser.

    if (SUCCEEDED(hr))
    {
        hr = DWriteCreateFactory(
            DWRITE_FACTORY_TYPE_SHARED,
            __uuidof(IDWriteFactory),
            reinterpret_cast<IUnknown**>(&pDWriteFactory_)
            );
    }
    
    
  3. Initiera textsträngen och lagra dess längd.

    wszText_ = L"Hello World using  DirectWrite!";
    cTextLength_ = (UINT32) wcslen(wszText_);
    
    
  4. Skapa ett IDWriteTextFormat- gränssnittsobjekt med hjälp av metoden IDWriteFactory::CreateTextFormat. IDWriteTextFormat anger teckensnitt, vikt, stretch, format och språk som ska användas för att återge textsträngen.

    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. Centrera texten vågrätt och lodrätt genom att anropa IDWriteTextFormat::SetTextAlignment och IDWriteTextFormat::SetParagraphAlignment metoder.

    // 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);
    }
    
    

I den här delen initierade du de enhetsoberoende resurser som används av ditt program. I nästa del initierar du de enhetsberoende resurserna.

Del 3: Skapa Device-Dependent resurser.

I den här delen skapar du en ID2D1HwndRenderTarget- och en ID2D1SolidColorBrush- för att återge texten.

Ett återgivningsmål är ett Direct2D-objekt som skapar ritningsresurser och återger ritkommandon till en renderingsenhet. En ID2D1HwndRenderTarget är ett återgivningsmål som renderas till en HWND-.

En av de ritningsresurser som ett återgivningsmål kan skapa är en pensel för att måla konturer, fyllningar och text. En ID2D1SolidColorBrush målar med en heldragen färg.

Både ID2D1HwndRenderTarget och ID2D1SolidColorBrush gränssnitt är bundna till en renderingsenhet när de skapas och måste släppas och återskapas om enheten blir ogiltig.

  1. I metoden SimpleText::CreateDeviceResources kontrollerar du om målpekaren för återgivning är NULL-. I så fall hämtar du storleken på återgivningsområdet och skapar en ID2D1HwndRenderTarget av den storleken. Använd ID2D1HwndRenderTarget för att skapa en ID2D1SolidColorBrush.

    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. I metoden SimpleText::DiscardDeviceResources släpps både penseln och återgivningsmålet.

    SafeRelease(&pRT_);
    SafeRelease(&pBlackBrush_);
    
    

Nu när du har skapat ett återgivningsmål och en pensel kan du använda dem för att återge texten.

Del 4: Rita text med hjälp av Direct2D DrawText-metoden.

  1. I metoden SimpleText::DrawText i din klass definierar du området för textlayouten genom att få dimensionerna för renderingsområdet och skapa en Direct2D--rectangle som har samma dimensioner.

    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. Använd metoden ID2D1RenderTarget::DrawText och IDWriteTextFormat-objektet för att återge text på skärmen. Metoden ID2D1RenderTarget::DrawText tar följande parametrar:

    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.
        );
    
    

Del 5: Rendera fönstrets innehåll med Direct2D

Om du vill återge innehållet i fönstret med hjälp av Direct2D- när ett färgmeddelande tas emot gör du följande:

  1. Skapa de enhetsberoende resurserna genom att anropa metoden SimpleText::CreateDeviceResources som implementerades i del 3.
  2. Anropa metoden ID2D1HwndRenderTarget::BeginDraw för återgivningsmålet.
  3. Rensa återgivningsmålet genom att anropa metoden ID2D1HwndRenderTarget::Clear.
  4. Anropa metoden SimpleText::DrawText, implementerad i del 4.
  5. Anropa metoden ID2D1HwndRenderTarget::EndDraw för återgivningsmålet.
  6. Om det är nödvändigt tar du bort de enhetsberoende resurserna så att de kan återskapas när fönstret ritas om.
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();
}

Klassen SimpleText implementeras i SimpleText.h och SimpleText.cpp.

Rita text med flera format.

Det här avsnittet visar hur du använder DirectWrite och Direct2D- för att återge text med flera format, enligt följande skärmbild.

skärmbild av

Koden för det här avsnittet implementeras som klassen MultiformattedText i DirectWrite HelloWorld. Den baseras på stegen från föregående avsnitt.

Om du vill skapa flerformaterad text använder du gränssnittet IDWriteTextLayout utöver gränssnittet IDWriteTextFormat som introducerades i föregående avsnitt. Gränssnittet IDWriteTextLayout beskriver formatering och layout för ett textblock. Förutom standardformatering som anges av ett IDWriteTextFormat- objekt kan formateringen för specifika textintervall ändras med hjälp av IDWriteTextLayout. Detta inkluderar teckensnittsfamiljenamn, storlek, vikt, stil, stretch, genomstrykning och understrykning.

IDWriteTextLayout innehåller även metoder för träfftestning. De träfftestningsmått som returneras av dessa metoder är relativa till layoutrutan som angavs när IDWriteTextLayout gränssnittsobjekt skapas med hjälp av CreateTextLayout--metoden för IDWriteFactory--gränssnittet.

Gränssnittet IDWriteTypography används för att lägga till valfria OpenType typografiska funktioner i en textlayout, till exempel swashes och alternativa stilistiska textuppsättningar. Typografiska funktioner kan läggas till i ett visst textintervall i en textlayout genom att anropa AddFontFeature-metoden för IDWriteTypography-gränssnittet. Den här metoden tar emot en DWRITE_FONT_FEATURE struktur som en parameter som innehåller en DWRITE_FONT_FEATURE_TAG uppräkningskonstant och en UINT32 körningsparameter. En lista över registrerade OpenType-funktioner finns i OpenType Layout Tag Registry på microsoft.com. Motsvarande DirectWrite-uppräkningskonstanter finns i DWRITE_FONT_FEATURE_TAG.

Del 1: Skapa ett IDWriteTextLayout-gränssnitt.

  1. Deklarera en pekare till ett IDWriteTextLayout- gränssnitt som medlem i klassen MultiformattedText.

    IDWriteTextLayout* pTextLayout_;
    
    
  2. I slutet av metoden MultiformattedText::CreateDeviceIndependentResources skapar du ett IDWriteTextLayout- gränssnittsobjekt genom att anropa metoden CreateTextLayout. Gränssnittet IDWriteTextLayout innehåller ytterligare formateringsfunktioner, till exempel möjligheten att använda olika format för valda delar av texten.

    // 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.
            );
    }
    
    

Del 2: Tillämpa formatering med IDWriteTextLayout.

Formatering, till exempel teckenstorlek, vikt och understrykning, kan tillämpas på delsträngar av texten som ska visas med hjälp av gränssnittet IDWriteTextLayout.

  1. Ange teckenstorleken för understrängen "Di" för "DirectWrite" till 100 genom att deklarera en DWRITE_TEXT_RANGE och anropa metoden IDWriteTextLayout::SetFontSize.

    // 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. Understryk understrängen "DirectWrite" genom att anropa metoden IDWriteTextLayout::SetUnderline.

    // 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. Ange teckenvikten till fetstil för understrängen "DirectWrite" genom att anropa metoden IDWriteTextLayout::SetFontWeight.

    if (SUCCEEDED(hr))
    {
        // Format the word "DWrite" to be bold.
        DWRITE_TEXT_RANGE textRange = {20,
                                       11 };
        hr = pTextLayout_->SetFontWeight(DWRITE_FONT_WEIGHT_BOLD, textRange);
    }
    

Del 3: Lägga till typografiska funktioner med IDWriteTypography.

  1. Deklarera och skapa ett IDWriteTypography gränssnittsobjekt genom att anropa metoden IDWriteFactory::CreateTypography.

    // Declare a typography pointer.
    IDWriteTypography* pTypography = NULL;
    
    // Create a typography interface object.
    if (SUCCEEDED(hr))
    {
        hr = pDWriteFactory_->CreateTypography(&pTypography);
    }
    
    
  2. Lägg till en teckensnittsfunktion genom att deklarera ett DWRITE_FONT_FEATURE objekt som har den stilistiska uppsättningen 7 angiven och anropa metoden IDWriteTypography::AddFontFeature.

    // Set the stylistic set.
    DWRITE_FONT_FEATURE fontFeature = {DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_7,
                                       1};
    if (SUCCEEDED(hr))
    {
        hr = pTypography->AddFontFeature(fontFeature);
    }
    
    
  3. Ange textlayouten så att den använder typografin över hela strängen genom att deklarera en DWRITE_TEXT_RANGE variabel och anropa IDWriteTextLayout::SetTypography-metoden och skicka in textområdet.

    if (SUCCEEDED(hr))
    {
        // Set the typography for the entire string.
        DWRITE_TEXT_RANGE textRange = {0,
                                       cTextLength_};
        hr = pTextLayout_->SetTypography(pTypography, textRange);
    }
    
    
  4. Ange den nya bredden och höjden för textlayoutobjektet i metoden MultiformattedText::OnResize.

    if (pTextLayout_)
    {
        pTextLayout_->SetMaxWidth(static_cast<FLOAT>(width / dpiScaleX_));
        pTextLayout_->SetMaxHeight(static_cast<FLOAT>(height / dpiScaleY_));
    }
    

Del 4: Rita text med hjälp av Metoden Direct2D DrawTextLayout.

Om du vill rita texten med de textlayoutinställningar som anges av objektet IDWriteTextLayout, ändra koden i metoden MultiformattedText::DrawText så att den använder IDWriteTextLayout::DrawTextLayout.

  1. Deklarera en D2D1_POINT_2F variabel och ange den till fönstrets övre vänstra punkt.

    D2D1_POINT_2F origin = D2D1::Point2F(
        static_cast<FLOAT>(rc.left / dpiScaleX_),
        static_cast<FLOAT>(rc.top / dpiScaleY_)
        );
    
    
  2. Rita texten till skärmen genom att anropa ID2D1RenderTarget::DrawTextLayoutDirect2D renderytan och överlämna IDWriteTextLayout pekaren.

    pRT_->DrawTextLayout(
        origin,
        pTextLayout_,
        pBlackBrush_
        );
    
    

Klassen MultiformattedText implementeras i MultiformattedText.h och MultiformattedText.cpp.