Sdílet prostřednictvím


Průvodce: Začínáme s DirectWrite

Tento dokument ukazuje, jak pomocí DirectWrite a Direct2D vytvořit jednoduchý text, který obsahuje jeden formát, a text, který obsahuje více formátů.

Tento kurz obsahuje následující části:

Zdrojový kód

Zdrojový kód zobrazený v tomto přehledu pochází z ukázky DirectWrite Hello World. Každá část je implementována v samostatné třídě (SimpleText a MultiformattedText) a je zobrazena v samostatném podřízené okně. Každá třída představuje okno Microsoft Win32. Kromě metody WndProc obsahuje každá třída následující metody:

Funkce Popis
CreateDeviceIndependentResources Vytvoří prostředky, které jsou nezávislé na zařízení, aby je bylo možné opakovaně používat kdekoli.
DiscardDeviceIndependentResources Uvolní prostředky nezávislé na zařízení, jakmile už nejsou potřeba.
CreateDeviceResources Vytvoří prostředky, jako jsou štětce a vykreslovací cíle, které jsou svázané s konkrétním zařízením.
ZahoditZařízeníZdroje Uvolní prostředky závislé na zařízení, jakmile už nebudou potřeba.
DrawD2DContent Používá Direct2D k vykreslení na obrazovku.
KreslitText Kreslí textový řetězec pomocí Direct2D.
OnResize Změní velikost Direct2D vykreslovacího cíle, když se změní velikost okna.

 

Můžete použít poskytnutou ukázku nebo podle pokynů přidat DirectWrite a Direct2D do vlastní aplikace Win32. Další informace o ukázce a přidružených souborech projektu naleznete v DirectWrite HelloWorld.

Kreslení jednoduchého textu

Tato část ukazuje, jak pomocí DirectWrite a Direct2D vykreslit jednoduchý text, který má jeden formát, jak je znázorněno na následujícím snímku obrazovky.

snímek obrazovky

Kreslení jednoduchého textu na obrazovku vyžaduje čtyři součásti:

  • Řetězec znaků, který se má vykreslit.
  • Instance IDWriteTextFormat.
  • Rozměry oblasti určené k obsahování textu.
  • Objekt, který může vykreslit text. V tomto tutoriálu. používáte Direct2D jako cílovou plochu pro vykreslování.

Rozhraní IDWriteTextFormat popisuje název rodiny písem, velikost, tloušťku, styl a roztažení použité k formátování textu a popisuje informace o národním prostředí. IDWriteTextFormat také definuje metody pro nastavení a získání následujících vlastností:

  • Řádkování.
  • Zarovnání textu vzhledem k levému a pravému okraji pole rozložení
  • Zarovnání odstavce vůči hornímu a dolnímu okraji rámce rozložení.
  • Směr čtení.
  • Granularita ořezávání textu, který přetéká přes pole rozvržení.
  • Přírůstková zarážka tabulátoru.
  • Směr toku odstavce.

Rozhraní IDWriteTextFormat je vyžadováno pro kreslicí text, který používá oba procesy popsané v tomto dokumentu .

Před vytvořením objektu IDWriteTextFormat nebo jakéhokoli jiného objektu DirectWrite potřebujete instanciIDWriteFactory. Pomocí IDWriteFactory můžete vytvořit IDWriteTextFormat instance a další objekty DirectWrite. K získání instance továrny použijte funkci DWriteCreateFactory.

Část 1: Deklarujte prostředky DirectWrite a Direct2D.

V této části deklarujete objekty, které použijete později k vytvoření a zobrazení textu jako soukromých datových členů třídy. Všechna rozhraní, funkce a datové typy pro DirectWrite jsou deklarována v souboru hlaviček dwrite.h a ty pro Direct2D jsou deklarovány v d2d1.h; Pokud jste to ještě neudělali, zahrňte do projektu tyto hlavičky.

  1. V souboru záhlaví třídy (SimpleText.h) deklarujte ukazatele na IDWriteFactory a IDWriteTextFormat rozhraní jako privátní členy.

    IDWriteFactory* pDWriteFactory_;
    IDWriteTextFormat* pTextFormat_;
    
    
  2. Deklarujte členy, které mají obsahovat textový řetězec pro vykreslení a délku řetězce.

    const wchar_t* wszText_;
    UINT32 cTextLength_;
    
    
  3. Deklarujte ukazatele na ID2D1Factory, ID2D1HwndRenderTargeta ID2D1SolidColorBrush rozhraní pro vykreslení textu pomocí Direct2D.

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

Část 2: Vytvoření prostředků nezávislých na zařízení

direct2D poskytuje dva typy prostředků: prostředky závislé na zařízení a prostředky nezávislé na zařízeních. Prostředky závislé na zařízení jsou přidružené k vykreslovacímu zařízení a už nefungují, pokud je toto zařízení odebráno. Prostředky nezávislé na zařízení mohou naopak existovat po dobu trvání vaší aplikace.

prostředky DirectWrite jsou nezávislé na zařízení.

V této části vytvoříte prostředky nezávislé na zařízení, které vaše aplikace používá. Tyto prostředky musí být uvolněny voláním metody rozhraní Release.

Některé prostředky, které se používají, musí být vytvořeny pouze jednou a nejsou svázané se zařízením. Inicializace těchto prostředků probíhá v metodě SimpleText::CreateDeviceIndependentResources, která je volána při inicializaci třídy.

  1. Uvnitř metody SimpleText::CreateDeviceIndependentResources v souboru implementace třídy (SimpleText.cpp) zavolejte funkci D2D1CreateFactory k vytvoření rozhraní ID2D1Factory, což je kořenové rozhraní továrny pro všechny objekty Direct2D. Stejnou továrnu použijete k vytvoření instance dalších prostředků Direct2D.

    hr = D2D1CreateFactory(
        D2D1_FACTORY_TYPE_SINGLE_THREADED,
        &pD2DFactory_
        );
    
    
  2. Voláním funkce DWriteCreateFactory vytvořte rozhraní IDWriteFactory, což je rozhraní kořenové továrny pro všechny objekty DirectWrite. Stejnou továrnu použijete k vytvoření instance jiných prostředků DirectWrite.

    if (SUCCEEDED(hr))
    {
        hr = DWriteCreateFactory(
            DWRITE_FACTORY_TYPE_SHARED,
            __uuidof(IDWriteFactory),
            reinterpret_cast<IUnknown**>(&pDWriteFactory_)
            );
    }
    
    
  3. Inicializuje textový řetězec a uloží jeho délku.

    wszText_ = L"Hello World using  DirectWrite!";
    cTextLength_ = (UINT32) wcslen(wszText_);
    
    
  4. Vytvořte objekt rozhraní IDWriteTextFormat pomocí metody IDWriteFactory::CreateTextFormat. IDWriteTextFormat určuje písmo, tloušťku, roztažení, styl a národní prostředí, které se použije k vykreslení textového řetězce.

    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. Vycentrujte text vodorovně a svisle voláním metod IDWriteTextFormat::SetTextAlignment a IDWriteTextFormat::SetParagraphAlignment.

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

V této části jste inicializovali prostředky nezávislé na zařízení, které vaše aplikace používá. V další části inicializujete prostředky závislé na zařízení.

Část 3: Vytvoření prostředků Device-Dependent

V této části vytvoříte ID2D1HwndRenderTarget a ID2D1SolidColorBrush pro vykreslení textu.

Cíl vykreslení je objekt Direct2D, který vytváří prostředky výkresu a vykresluje příkazy kreslení do vykreslovacího zařízení. ID2D1HwndRenderTarget je cíl vykreslení, který se vykreslí na HWND.

Jedním z kreslicích prostředků, které může vytvořit cílový objekt vykreslování, je štětec na malování obrysů, výplní a textu. ID2D1SolidColorBrush maluje jednolitou barvou.

Rozhraní ID2D1HwndRenderTarget a ID2D1SolidColorBrush jsou svázané s vykreslovacím zařízením při jejich vytvoření a musí být uvolněny a znovu vytvořeny, pokud se zařízení stane neplatným.

  1. Uvnitř metody SimpleText::CreateDeviceResources zkontrolujte, zda je ukazatel cílového vykreslení NULL. Pokud ano, načtěte velikost oblasti vykreslení a vytvořte ID2D1HwndRenderTarget této velikosti. Pomocí ID2D1HwndRenderTarget vytvořte 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. Ve funkci SimpleText::DiscardDeviceResources uvolněte jak štětec, tak cílový renderovací objekt.

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

Teď, když jste vytvořili cíl vykreslení a štětec, můžete ho použít k vykreslení textu.

Část 4: Nakreslete text pomocí metody Direct2D DrawText.

  1. Ve třídě SimpleText::DrawText definujte oblast pro rozložení textu načtením dimenzí vykreslovací oblasti a vytvořte Direct2D obdélník se stejnými dimenzemi.

    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. K vykreslení textu na obrazovku použijte metodu ID2D1RenderTarget::DrawText a objekt IDWriteTextFormat. Metoda ID2D1RenderTarget::DrawText přijímá následující parametry:

    • Řetězec, který se má vykreslit.
    • Ukazatel na rozhraní IDWriteTextFormat.
    • Obdélník rozložení Direct2D .
    • Ukazatel na rozhraní, které zveřejňuje ID2D1Brush.
    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.
        );
    
    

Část 5: Vykreslení obsahu okna pomocí Direct2D

Chcete-li vykreslit obsah okna pomocí Direct2D, když je přijata zpráva o malování, postupujte takto:

  1. Vytvořte prostředky závislé na zařízení voláním metody SimpleText::CreateDeviceResources implementované v části 3.
  2. Zavolejte metodu ID2D1HwndRenderTarget::BeginDraw vykreslovacího cíle.
  3. Proveďte metodu volání ID2D1HwndRenderTarget::Clear k vymazání cíle vykreslování.
  4. Volání metody SimpleText::DrawText, která byla implementována v části 4.
  5. Volejte metodu ID2D1HwndRenderTarget::EndDraw vykreslovacího cíle.
  6. V případě potřeby zahoďte prostředky závislé na zařízení, aby se mohly znovu vytvořit při překreslení okna.
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();
}

Třída SimpleText je implementována v SimpleText.h a SimpleText.cpp.

Kreslení textu s více formáty

Tato část ukazuje, jak pomocí DirectWrite a Direct2D vykreslit text s více formáty, jak je znázorněno na následujícím snímku obrazovky.

snímek obrazovky

Kód této části je implementován jako třída MultiformattedText v DirectWrite HelloWorld. Je založená na krocích z předchozí části.

Chcete-li vytvořit víceformátovaný text, použijete rozhraní IDWriteTextLayout a rozhraní IDWriteTextFormat, jak bylo uvedeno v předchozí části. Rozhraní IDWriteTextLayout popisuje formátování a rozložení bloku textu. Kromě výchozího formátování určeného objektem IDWriteTextFormat lze formátování pro konkrétní oblasti textu změnit pomocí IDWriteTextLayout. To zahrnuje název písma, velikost, tloušťku, styl, roztažení, přeškrtnutí a podtržení.

IDWriteTextLayout také poskytuje metody hit-testování. Metriky hit-testování vrácené těmito metodami jsou relativní vzhledem k poli rozložení zadanému při vytvoření objektu rozhraní IDWriteTextLayout pomocí metody CreateTextLayout rozhraní IDWriteFactory.

Rozhraní IDWriteTypography se používá k přidání volitelných OpenType typografických funkcí do rozložení textu, jako jsou swashes a alternativní stylistické sady textu. Typografické funkce lze přidat do určitého rozsahu textu v rámci rozložení textu voláním metody AddFontFeature rozhraní IDWriteTypography. Tato metoda obdrží DWRITE_FONT_FEATURE strukturu jako parametr, který obsahuje konstantu výčtu DWRITE_FONT_FEATURE_TAG a parametr spuštění UINT32. Seznam registrovaných funkcí OpenType najdete v registru OpenType Layout Tag Registry na microsoft.com. Ekvivalentní konstanty výčtu DirectWrite naleznete v tématu DWRITE_FONT_FEATURE_TAG.

Část 1: Vytvoření rozhraní IDWriteTextLayout.

  1. Deklarujte ukazatel na rozhraní IDWriteTextLayout jako člen třídy MultiformattedText.

    IDWriteTextLayout* pTextLayout_;
    
    
  2. Na konci metody MultiformattedText::CreateDeviceIndependentResources vytvořte objekt rozhraní IDWriteTextLayout voláním metody CreateTextLayout. Rozhraní IDWriteTextLayout poskytuje další funkce formátování, jako je možnost použití různých formátů u vybraných částí textu.

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

Část 2: Použití formátování pomocí IDWriteTextLayout.

Formátování, jako je velikost písma, váha a podtržení, lze použít u podřetězeců textu, které se mají zobrazit pomocí rozhraní IDWriteTextLayout.

  1. Nastavte velikost písma pro podřetězec "Di" z "DirectWrite" na 100 deklarací DWRITE_TEXT_RANGE a voláním metody 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. Podtrhněte podřetězec "DirectWrite" voláním metody 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. Nastavte tloušťku písma na tučné pro podřetězec "DirectWrite" voláním IDWriteTextLayout::SetFontWeight metodou.

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

Část 3: Přidání typografických funkcí pomocí IDWriteTypography

  1. Deklarujte a vytvořte objekt rozhraní IDWriteTypography voláním metody IDWriteFactory::CreateTypography.

    // Declare a typography pointer.
    IDWriteTypography* pTypography = NULL;
    
    // Create a typography interface object.
    if (SUCCEEDED(hr))
    {
        hr = pDWriteFactory_->CreateTypography(&pTypography);
    }
    
    
  2. Přidejte funkci písma deklarací objektu DWRITE_FONT_FEATURE, který má zadanou stylistickou sadu 7, a voláním metody 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. Nastavte rozložení textu tak, aby používalo typografii po celém řetězci deklarováním proměnné DWRITE_TEXT_RANGE a voláním IDWriteTextLayout::SetTypography metody a předáním textové oblasti.

    if (SUCCEEDED(hr))
    {
        // Set the typography for the entire string.
        DWRITE_TEXT_RANGE textRange = {0,
                                       cTextLength_};
        hr = pTextLayout_->SetTypography(pTypography, textRange);
    }
    
    
  4. Nastavte novou šířku a výšku objektu rozložení textu v metodě MultiformattedText::OnResize.

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

Část 4: Kreslení textu pomocí Direct2D DrawTextLayout Metoda.

Chcete-li nakreslit text s nastavením rozložení textu určeným objektem IDWriteTextLayout, změňte kód v metodě MultiformattedText::DrawText tak, aby používal IDWriteTextLayout::DrawTextLayout.

  1. Deklarujte D2D1_POINT_2F proměnnou a nastavte ji na levý horní bod okna.

    D2D1_POINT_2F origin = D2D1::Point2F(
        static_cast<FLOAT>(rc.left / dpiScaleX_),
        static_cast<FLOAT>(rc.top / dpiScaleY_)
        );
    
    
  2. Nakreslete text na obrazovku zavoláním ID2D1RenderTarget::D rawTextLayout metody Direct2D render target a předáním IDWriteTextLayout ukazatel.

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

MultiformattedText třída je implementována v MultiformattedText.h a MultiformattedText.cpp.