Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym dokumencie pokazano, jak używać DirectWrite i Direct2D do tworzenia prostego tekstu zawierającego pojedynczy format, a następnie tekstu zawierającego wiele formatów.
Ten samouczek zawiera następujące części:
Kod źródłowy
Kod źródłowy pokazany w tym omówieniu został zaczerpnięty z przykładu DirectWrite Hello World. Każda część jest implementowana w oddzielnej klasie (SimpleText i MultiformattedText) i jest wyświetlana w osobnym oknie podrzędnym. Każda klasa reprezentuje okno platformy Microsoft Win32. Oprócz metody WndProc każda klasa zawiera następujące metody:
| Funkcja | Opis |
|---|---|
| CreateDeviceIndependentResources | Tworzy zasoby niezależne od urządzenia, dzięki czemu mogą być ponownie używane w dowolnym miejscu. |
| Odrzuć zasoby niezależne od urządzenia | Zwalnia zasoby niezależne od urządzenia po tym, jak nie są już potrzebne. |
| CreateDeviceResources | Tworzy zasoby, takie jak pędzle i obiekty docelowe renderowania, które są powiązane z określonym urządzeniem. |
| OdrzućZasobyUrządzenia | Zwalnia zasoby zależne od urządzenia po tym, jak nie są już potrzebne. |
| DrawD2DContent | Używa Direct2D do renderowania na ekranie. |
| RysujTekst | Rysuje ciąg tekstowy przy użyciu Direct2D. |
| OnResize | Zmienia rozmiar obiektu docelowego renderowania Direct2D po zmianie rozmiaru okna. |
Możesz użyć podanego przykładu lub użyć poniższych instrukcji, aby dodać DirectWrite i Direct2D do własnej aplikacji Win32. Aby uzyskać więcej informacji na temat przykładu i skojarzonych plików projektu, zobacz DirectWrite HelloWorld.
Rysowanie prostego tekstu
W tej sekcji pokazano, jak używać DirectWrite i Direct2D do renderowania prostego tekstu, który ma jeden format, jak pokazano na poniższym zrzucie ekranu.
Rysowanie prostego tekstu na ekranie wymaga czterech składników:
- Ciąg znaków do renderowania.
- Wystąpienie IDWriteTextFormat.
- Wymiary obszaru zawierającego tekst.
- Obiekt, który może renderować tekst. W tym samouczku. używasz obiektu docelowego renderowania Direct2D.
Interfejs IDWriteTextFormat opisuje nazwę rodziny czcionek, rozmiar, wagę, styl i rozciąganie używane do formatowania tekstu oraz opisuje informacje o ustawieniach regionalnych. IDWriteTextFormat również definiuje metody ustawiania i uzyskiwania następujących właściwości:
- Odstęp między wierszami.
- Wyrównanie tekstu względem lewej i prawej krawędzi pola układu.
- Wyrównanie akapitu względem górnej i dolnej części ramki układu.
- Kierunek czytania.
- Stopień szczegółowości przycinania tekstu dla tekstu, który przepełnia pole układu.
- Tabulator przyrostowy.
- Kierunek przepływu akapitu.
Interfejs IDWriteTextFormat jest wymagany do rysowania tekstu, który używa obu procesów opisanych w tym dokumencie.
Aby można było utworzyć obiektIDWriteTextFormatlub jakikolwiek inny obiekt DirectWrite, potrzebujesz wystąpienia IDWriteFactory. Użyjesz IDWriteFactory do utworzenia wystąpień IDWriteTextFormat i innych obiektów DirectWrite. Aby uzyskać wystąpienie fabryki, użyj funkcji DWriteCreateFactory.
Część 1. Deklarowanie zasobów DirectWrite i Direct2D.
W tej części zadeklarujesz obiekty, których będziesz używać później do tworzenia i wyświetlania tekstu jako prywatnych składowych danych klasy. Wszystkie interfejsy, funkcje i typy danych dla DirectWrite są deklarowane w pliku nagłówka dwrite.h, a te dla Direct2D są deklarowane w d2d1.h; Jeśli jeszcze tego nie zrobiono, uwzględnij te nagłówki w projekcie.
W pliku nagłówka klasy (SimpleText.h) zadeklaruj wskaźniki do interfejsów IDWriteFactory i IDWriteTextFormat jako prywatne elementy członkowskie.
IDWriteFactory* pDWriteFactory_; IDWriteTextFormat* pTextFormat_;Zadeklaruj zmienne do przechowywania ciągu tekstowego do renderowania i długości ciągu.
const wchar_t* wszText_; UINT32 cTextLength_;Zadeklaruj wskaźniki do ID2D1Factory, ID2D1HwndRenderTargeti ID2D1SolidColorBrush interfejsy renderowania tekstu za pomocą Direct2D.
ID2D1Factory* pD2DFactory_; ID2D1HwndRenderTarget* pRT_; ID2D1SolidColorBrush* pBlackBrush_;
Część 2. Tworzenie niezależnych zasobów urządzenia.
Direct2D udostępnia dwa typy zasobów: zasoby zależne od urządzenia i zasoby niezależne od urządzenia. Zasoby zależne od urządzenia są skojarzone z urządzeniem renderowania i nie działają już, jeśli to urządzenie zostanie usunięte. Z drugiej strony zasoby niezależne od urządzenia mogą być używane przez cały czas działania aplikacji.
zasoby DirectWrite są niezależne od urządzenia.
W tej sekcji utworzysz zasoby niezależne od urządzenia, które są używane przez aplikację. Te zasoby muszą zostać zwolnione poprzez wywołanie metody Release na interfejsie.
Niektóre używane zasoby muszą zostać utworzone tylko raz i nie są powiązane z urządzeniem. Inicjowanie tych zasobów jest umieszczane w metodzie SimpleText::CreateDeviceIndependentResources, która jest wywoływana podczas inicjowania klasy.
Wewnątrz metody SimpleText::CreateDeviceIndependentResources w pliku implementacji klasy (SimpleText.cpp) wywołaj funkcję D2D1CreateFactory, aby utworzyć interfejs ID2D1Factory, który jest głównym interfejsem fabryki dla wszystkich obiektów Direct2D. Używasz tej samej fabryki, aby zainicjować inne zasoby Direct2D.
hr = D2D1CreateFactory( D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory_ );Wywołaj funkcję DWriteCreateFactory, aby utworzyć interfejs IDWriteFactory, który jest głównym interfejsem fabryki dla wszystkich obiektów DirectWrite. Używasz tej samej fabryki do tworzenia instancji innych zasobów DirectWrite.
if (SUCCEEDED(hr)) { hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(&pDWriteFactory_) ); }Zainicjuj ciąg tekstowy i zapisz jego długość.
wszText_ = L"Hello World using DirectWrite!"; cTextLength_ = (UINT32) wcslen(wszText_);Utwórz obiekt interfejsu IDWriteTextFormat przy użyciu metody IDWriteFactory::CreateTextFormat. IDWriteTextFormat określa czcionkę, wagę, rozciągnięcie, styl i ustawienia regionalne, które będą używane do renderowania ciągu tekstowego.
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_ ); }Wyśrodkuj tekst w poziomie i w pionie, wywołując metody IDWriteTextFormat::SetTextAlignment i 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); }
W tej części zainicjowano zasoby niezależne od urządzenia, które są używane przez aplikację. W następnej części zainicjujesz zasoby zależne od urządzenia.
Część 3. Tworzenie zasobów Device-Dependent.
W tej części utworzysz ID2D1HwndRenderTarget i ID2D1SolidColorBrush do renderowania swojego tekstu.
Obiekt docelowy renderowania to obiekt Direct2D, który tworzy zasoby rysunkowe i renderuje polecenia rysowania na urządzeniu renderowania. ID2D1HwndRenderTarget to obiekt docelowy renderowania, który renderuje do HWND.
Jednym z zasobów rysunkowych, które może utworzyć obiekt docelowy renderowania, jest pędzl do malowania konturów, wypełnień i tekstu. ID2D1SolidColorBrush maluje kolorem stałym.
Zarówno interfejsy ID2D1HwndRenderTarget, jak i ID2D1SolidColorBrush są powiązane z urządzeniem renderującym w momencie ich tworzenia i muszą zostać zwolnione oraz utworzone na nowo, jeżeli urządzenie stanie się nieprawidłowe.
Wewnątrz metody SimpleText::CreateDeviceResources sprawdź, czy wskaźnik celu renderowania jest null. Jeśli tak jest, pobierz rozmiar obszaru renderowania i utwórz ID2D1HwndRenderTarget tego rozmiaru. Użyj ID2D1HwndRenderTarget, aby utworzyć 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_ ); } }W metodzie SimpleText::DiscardDeviceResources zwolnij zarówno pędzel, jak i cel renderowania.
SafeRelease(&pRT_); SafeRelease(&pBlackBrush_);
Po utworzeniu elementu docelowego renderowania i pędzla możesz użyć ich do renderowania tekstu.
Część 4. Rysuj tekst przy użyciu metody Direct2D DrawText.
W metodzie SimpleText::DrawText twojej klasy zdefiniuj obszar układu tekstu, pobierając wymiary obszaru renderowania, i utwórz prostokąt Direct2D o tych samych wymiarach.
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_ );Użyj metody ID2D1RenderTarget::DrawText i obiektu IDWriteTextFormat do renderowania tekstu na ekranie. Metoda ID2D1RenderTarget::DrawText przyjmuje następujące parametry:
- Ciąg do renderowania.
- Wskaźnik do interfejsu IDWriteTextFormat.
- Prostokąt układu Direct2D.
- Wskaźnik interfejsu, który uwidacznia 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. );
Część 5. Renderowanie zawartości okna przy użyciu direct2D
Aby renderować zawartość okna przy użyciu Direct2D po odebraniu komunikatu malowania, wykonaj następujące czynności:
- Utwórz zasoby zależne od urządzenia, wywołując metodę SimpleText::CreateDeviceResources zaimplementowaną w części 3.
- Wywołaj metodę ID2D1HwndRenderTarget::BeginDraw obiektu docelowego renderowania.
- Wyczyść obiekt docelowy renderowania, wywołując metodę ID2D1HwndRenderTarget::Clear.
- Wywołaj metodę SimpleText::DrawText zaimplementowaną w części 4.
- Wywołaj metodę ID2D1HwndRenderTarget::EndDraw elementu docelowego renderowania.
- Jeśli jest to konieczne, odrzuć zasoby zależne od urządzenia, aby można je było odtworzyć po ponownym rysowaniu 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();
}
Klasa SimpleText jest implementowana w pliku SimpleText.h i SimpleText.cpp.
Rysowanie tekstu w różnych formatach.
W tej sekcji pokazano, jak używać DirectWrite i Direct2D do renderowania tekstu z wieloma formatami, jak pokazano na poniższym zrzucie ekranu.
Kod tej sekcji jest implementowany jako klasa MultiformattedText w DirectWrite HelloWorld. Jest on oparty na krokach z poprzedniej sekcji.
Aby utworzyć tekst wieloformatowy, należy użyć interfejsuIDWriteTextLayoutoprócz interfejsu IDWriteTextFormat wprowadzonego w poprzedniej sekcji. Interfejs IDWriteTextLayout opisuje formatowanie i układ bloku tekstu. Oprócz domyślnego formatowania określonego przez obiekt IDWriteTextFormat można zmienić formatowanie dla określonych zakresów tekstu przy użyciu IDWriteTextLayout. Obejmuje to nazwę rodziny czcionek, rozmiar, grubość, styl, rozszerzenie, przekreślenie i podkreślenie.
IDWriteTextLayout również udostępnia metody testowania trafień. Metryki testowania trafień zwracane przez te metody są względne względem pola układu określonego podczas tworzenia obiektu interfejsu IDWriteTextLayout przy użyciu metody CreateTextLayout interfejsu IDWriteFactory.
InterfejsIDWriteTypography służy do dodawania opcjonalnych funkcji OpenType typograficznych do układu tekstu, takich jak zawijas i alternatywne style tekstu. Funkcje typograficzne można dodać do określonego zakresu tekstu w układzie tekstu, wywołując metodę AddFontFeature interfejsu IDWriteTypography. Ta metoda odbiera strukturę DWRITE_FONT_FEATURE jako parametr, który zawiera stałą wyliczenia DWRITE_FONT_FEATURE_TAG oraz parametr wykonawczy UINT32. Listę zarejestrowanych funkcji OpenType można znaleźć w rejestrze tagów układu OpenType na stronie microsoft.com. Aby uzyskać równoważne stałe wyliczeniowe DirectWrite, zobacz DWRITE_FONT_FEATURE_TAG.
Część 1. Tworzenie interfejsu IDWriteTextLayout.
Zadeklaruj wskaźnik do interfejsu IDWriteTextLayout jako element członkowski klasy MultiformattedText.
IDWriteTextLayout* pTextLayout_;Na końcu metody MultiformattedText::CreateDeviceIndependentResources utwórz obiekt interfejsu IDWriteTextLayout, wywołując metodę CreateTextLayout. Interfejs IDWriteTextLayout udostępnia dodatkowe funkcje formatowania, takie jak możliwość stosowania różnych formatów do wybranych fragmentów tekstu.
// 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. ); }
Część 2. Stosowanie formatowania za pomocą elementu IDWriteTextLayout.
Formatowanie, takie jak rozmiar czcionki, waga i podkreślenie, można zastosować do podciągów tekstu, które mają być wyświetlane przy użyciu interfejsu IDWriteTextLayout.
Ustaw rozmiar czcionki dla podciągu "Di" w nazwie "DirectWrite" na 100, deklarując DWRITE_TEXT_RANGE i wywołując metodę 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); }Podkreśl fragment "DirectWrite" poprzez wywołanie 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); }Ustaw wagę czcionki na pogrubioną dla podciągu "DirectWrite", wywołując metodę 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); }
Część 3: Dodawanie funkcji typograficznych z IDWriteTypography.
Zadeklaruj i utwórz obiekt interfejsu IDWriteTypography, wywołując metodę IDWriteFactory::CreateTypography.
// Declare a typography pointer. IDWriteTypography* pTypography = NULL; // Create a typography interface object. if (SUCCEEDED(hr)) { hr = pDWriteFactory_->CreateTypography(&pTypography); }Dodaj funkcję czcionki, deklarując obiekt DWRITE_FONT_FEATURE z określonym zestawem stylistycznym 7 i wywołując metodę 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); }Ustaw układ tekstu, aby używać typografii dla całego ciągu, deklarując zmienną DWRITE_TEXT_RANGE i wywołując IDWriteTextLayout::SetTypography metodę i przekazując zakres tekstu.
if (SUCCEEDED(hr)) { // Set the typography for the entire string. DWRITE_TEXT_RANGE textRange = {0, cTextLength_}; hr = pTextLayout_->SetTypography(pTypography, textRange); }Ustaw nową szerokość i wysokość obiektu układu tekstu w metodzie MultiformattedText::OnResize.
if (pTextLayout_) { pTextLayout_->SetMaxWidth(static_cast<FLOAT>(width / dpiScaleX_)); pTextLayout_->SetMaxHeight(static_cast<FLOAT>(height / dpiScaleY_)); }
Część 4. Rysuj tekst przy użyciu metody Direct2D DrawTextLayout.
Aby narysować tekst z ustawieniami układu tekstu określonymi przez obiekt IDWriteTextLayout, zmień kod w metodzie MultiformattedText::DrawText, aby użyć IDWriteTextLayout::DrawTextLayout.
Zadeklaruj zmienną D2D1_POINT_2F i ustaw ją na lewy górny punkt okna.
D2D1_POINT_2F origin = D2D1::Point2F( static_cast<FLOAT>(rc.left / dpiScaleX_), static_cast<FLOAT>(rc.top / dpiScaleY_) );Narysuj tekst na ekranie, wywołując metodę ID2D1RenderTarget::DrawTextLayout docelowego obiektu renderowania Direct2D i przekazując wskaźnik IDWriteTextLayout.
pRT_->DrawTextLayout( origin, pTextLayout_, pBlackBrush_ );
Klasa MultiformattedText jest implementowana w klasie MultiformattedText.h i MultiformattedText.cpp.