チュートリアル: DirectWriteではじめにする
このドキュメントでは、DirectWriteと Direct2D を使用して、1 つの書式を含む単純なテキストを作成し、複数の形式を含むテキストを作成する方法について説明します。
このチュートリアルには、次の部分が含まれています。
ソース コード
この概要に示されているソース コードは、DirectWrite Hello World サンプルから取得します。 各パーツは個別のクラス (SimpleText と MultiformattedText) で実装され、個別の子ウィンドウに表示されます。 各クラスは、Microsoft Win32 ウィンドウを表します。 WndProc メソッドに加えて、各クラスには次のメソッドが含まれています。
機能 | 説明 |
---|---|
CreateDeviceIndependentResources | 任意の場所で再利用できるように、デバイスに依存しないリソースを作成します。 |
DiscardDeviceIndependentResources | 不要になったデバイスに依存しないリソースを解放します。 |
CreateDeviceResources | 特定のデバイスに関連付けられているリソース (ブラシやレンダー ターゲットなど) を作成します。 |
DiscardDeviceResources | 不要になったデバイス依存リソースを解放します。 |
DrawD2DContent | Direct2D を使用して画面にレンダリングします。 |
Drawtext | Direct2D を使用してテキスト文字列を描画します。 |
Onresize | ウィンドウ サイズが変更されたときに Direct2D レンダー ターゲットのサイズを変更します。 |
提供されているサンプルを使用するか、次の手順に従って、DirectWriteと Direct2D を独自の Win32 アプリケーションに追加できます。 サンプルと関連するプロジェクト ファイルの詳細については、「HelloWorld のDirectWrite」を参照してください。
単純なテキストの描画
このセクションでは、次のスクリーン ショットに示すように、DirectWriteと Direct2D を使用して、1 つの形式の単純なテキストをレンダリングする方法について説明します。
画面に単純なテキストを描画するには、次の 4 つのコンポーネントが必要です。
- レンダリングする文字列。
- IDWriteTextFormat のインスタンス。
- テキストを含む領域の寸法。
- テキストをレンダリングできるオブジェクト。 このチュートリアルでは、 Direct2D レンダー ターゲットを使用します。
IDWriteTextFormat インターフェイスは、テキストの書式設定に使用されるフォント ファミリ名、サイズ、重み、スタイル、およびストレッチを記述し、ロケール情報を記述します。 IDWriteTextFormat は、次のプロパティを設定および取得するためのメソッドも定義します。
- 行間。
- レイアウト ボックスの左端と右端を基準としたテキスト配置。
- レイアウト ボックスの上下を基準とした段落の配置。
- 読み取り方向。
- レイアウト ボックスをオーバーフローするテキストのテキスト トリミングの細分性。
- 増分タブ位置。
- 段落フローの方向。
IDWriteTextFormat インターフェイスは、このドキュメントで説明されている両方のプロセスを使用するテキストを描画するために必要です。
IDWriteTextFormat オブジェクトまたはその他のDirectWrite オブジェクトを作成するには、IDWriteFactory インスタンスが必要です。 IDWriteFactory を使用して、IDWriteTextFormat インスタンスとその他のDirectWrite オブジェクトを作成します。 ファクトリ インスタンスを取得するには、 DWriteCreateFactory 関数を 使用します。
パート 1: DirectWriteおよび Direct2D リソースを宣言する。
このパートでは、後でクラスのプライベート データ メンバーとしてテキストを作成および表示するために使用するオブジェクトを宣言します。 DirectWriteのすべてのインターフェイス、関数、およびデータ型は dwrite.h ヘッダー ファイルで宣言され、Direct2D 用のインターフェイス、関数、データ型はすべて d2d1.h で宣言されます。まだ行っていない場合は、プロジェクトにこれらのヘッダーを含めます。
クラス ヘッダー ファイル (SimpleText.h) で、 IDWriteFactory インターフェイスと IDWriteTextFormat インターフェイスへのポインターをプライベート メンバーとして宣言します。
IDWriteFactory* pDWriteFactory_; IDWriteTextFormat* pTextFormat_;
レンダリングするテキスト文字列と文字列の長さを保持するメンバーを宣言します。
const wchar_t* wszText_; UINT32 cTextLength_;
Direct2D でテキストをレンダリングするための ID2D1Factory、ID2D1HwndRenderTarget、ID2D1SolidColorBrush インターフェイスへのポインターを宣言します。
ID2D1Factory* pD2DFactory_; ID2D1HwndRenderTarget* pRT_; ID2D1SolidColorBrush* pBlackBrush_;
パート 2: デバイスに依存しないリソースを作成する。
Direct2D には、デバイス依存リソースとデバイスに依存しないリソースの 2 種類のリソースが用意されています。 デバイスに依存するリソースはレンダリング デバイスに関連付けられるので、そのデバイスが削除された場合は機能しなくなります。 一方、デバイスに依存しないリソースは、アプリケーションのスコープに対して持続する可能性があります。
DirectWriteリソースはデバイスに依存しません。
このセクションでは、アプリケーションで使用されるデバイスに依存しないリソースを作成します。 これらのリソースは、インターフェイスの Release メソッドを呼び出して解放する必要があります。
使用されるリソースの一部は、1 回だけ作成する必要があり、デバイスに関連付けられません。 これらのリソースの初期化は、クラスの初期化時に呼び出される SimpleText::CreateDeviceIndependentResources メソッドに格納されます。
クラス実装ファイル (SimpleText.cpp) の SimpleText::CreateDeviceIndependentResources メソッド内で、D2D1CreateFactory 関数を呼び出して、すべての Direct2D オブジェクトのルート ファクトリ インターフェイスである ID2D1Factory インターフェイスを作成します。 同じファクトリを使用して、他の Direct2D リソースをインスタンス化します。
hr = D2D1CreateFactory( D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory_ );
DWriteCreateFactory 関数を呼び出して IDWriteFactory インターフェイスを作成します。これは、すべてのDirectWrite オブジェクトのルート ファクトリ インターフェイスです。 同じファクトリを使用して、他のDirectWrite リソースをインスタンス化します。
if (SUCCEEDED(hr)) { hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(&pDWriteFactory_) ); }
テキスト文字列を初期化し、その長さを格納します。
wszText_ = L"Hello World using DirectWrite!"; cTextLength_ = (UINT32) wcslen(wszText_);
IDWriteFactory::CreateTextFormat メソッドを使用して、IDWriteTextFormat インターフェイス オブジェクトを作成します。 IDWriteTextFormat は、テキスト文字列のレンダリングに使用されるフォント、太さ、ストレッチ、スタイル、ロケールを指定します。
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_ ); }
IDWriteTextFormat::SetTextAlignment メソッドと 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); }
この部分では、アプリケーションで使用されるデバイスに依存しないリソースを初期化しました。 次のパートでは、デバイスに依存するリソースを初期化します。
パート 3: Device-Dependent リソースを作成する。
このパートでは、テキストをレンダリングするための ID2D1HwndRenderTarget と ID2D1SolidColorBrush を作成します。
レンダー ターゲットは、描画リソースを作成し、描画コマンドをレンダリング デバイスにレンダリングする Direct2D オブジェクトです。 ID2D1HwndRenderTarget は、HWND にレンダリングするレンダー ターゲットです。
レンダー ターゲットで作成できる描画リソースの 1 つは、アウトライン、塗りつぶし、テキストを描画するためのブラシです。 ID2D1SolidColorBrush は、純色で塗りつぶします。
ID2D1HwndRenderTarget インターフェイスと ID2D1SolidColorBrush インターフェイスはどちらも、作成時にレンダリング デバイスにバインドされ、デバイスが無効になった場合は解放して再作成する必要があります。
SimpleText::CreateDeviceResources メソッド内で、レンダー ターゲット ポインターが NULL かどうかをチェックします。 その場合は、レンダリング領域のサイズを取得し、そのサイズの ID2D1HwndRenderTarget を 作成します。 ID2D1HwndRenderTarget を使用して 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_ ); } }
SimpleText::D iscardDeviceResources メソッドで、ブラシとレンダー ターゲットの両方を解放します。
SafeRelease(&pRT_); SafeRelease(&pBlackBrush_);
レンダー ターゲットとブラシを作成したら、それらを使用してテキストをレンダリングできます。
パート 4: Direct2D DrawText メソッドを使用してテキストを描画する。
クラスの SimpleText::D rawText メソッドで、レンダリング領域の寸法を取得してテキスト レイアウトの領域を定義し、同じ寸法の Direct2D 四角形を作成します。
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_ );
ID2D1RenderTarget::D rawText メソッドと IDWriteTextFormat オブジェクトを使用して、テキストを画面にレンダリングします。 ID2D1RenderTarget::D rawText メソッドは、次のパラメーターを受け取ります。
- レンダリングする文字列。
- IDWriteTextFormat インターフェイスへのポインター。
- Direct2D レイアウトの四角形。
- 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. );
パート 5: Direct2D を使用してウィンドウの内容をレンダリングする
ペイント メッセージの受信時に Direct2D を使用してウィンドウの内容をレンダリングするには、次の操作を行います。
- パート 3 で実装されている SimpleText::CreateDeviceResources メソッドを呼び出して、デバイス依存リソースを作成します。
- レンダー ターゲットの ID2D1HwndRenderTarget::BeginDraw メソッドを呼び出します。
- ID2D1HwndRenderTarget::Clear メソッドを呼び出して、レンダー ターゲットをクリアします。
- パート 4 で実装されている SimpleText::D rawText メソッドを呼び出します。
- レンダー ターゲットの ID2D1HwndRenderTarget::EndDraw メソッドを呼び出します。
- 必要に応じて、デバイス依存リソースを破棄して、ウィンドウの再描画時に再作成できるようにします。
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();
}
SimpleText クラスは、SimpleText.h および SimpleText.cpp で実装されます。
複数の書式でテキストを描画する。
このセクションでは、次のスクリーン ショットに示すように、DirectWriteと Direct2D を使用して複数の形式のテキストをレンダリングする方法について説明します。
このセクションのコードは、DirectWrite HelloWorld の MultiformattedText クラスとして実装されています。 これは、前のセクションの手順に基づいています。
複数書式のテキストを作成するには、前のセクションで導入した IDWriteTextFormat インターフェイスに加えて 、IDWriteTextLayout インターフェイスを使用します。 IDWriteTextLayout インターフェイスは、テキスト ブロックの書式設定とレイアウトを記述します。 IDWriteTextFormat オブジェクトで指定された既定の書式設定に加えて、IDWriteTextLayout を使用して、特定のテキスト範囲の書式を変更できます。 これには、フォント ファミリ名、サイズ、太さ、スタイル、ストレッチ、取り消し線、下線が含まれます。
IDWriteTextLayout には、ヒット テスト メソッドも用意されています。 これらのメソッドによって返されるヒット テスト メトリックは、IDWriteTextLayout インターフェイス オブジェクトが IDWriteFactory インターフェイスの CreateTextLayout メソッドを使用して作成されるときに指定されたレイアウト ボックスに対して相対的です。
IDWriteTypography インターフェイスは、オプションの OpenType 文字体裁機能をテキスト レイアウト (スワッシュや代替スタイル テキスト セットなど) に追加するために使用されます。 文字体裁機能は、IDWriteTypography インターフェイスの AddFontFeature メソッドを呼び出すことによって、テキスト レイアウト内の特定のテキスト範囲に追加できます。 このメソッドは、 DWRITE_FONT_FEATURE 構造体を、 DWRITE_FONT_FEATURE_TAG 列挙定数と UINT32 実行パラメーターを含むパラメーターとして受け取ります。 登録されている OpenType 機能の一覧は、microsoft.com の OpenType レイアウト タグ レジストリ にあります。 等価のDirectWrite列挙定数については、「DWRITE_FONT_FEATURE_TAG」を参照してください。
パート 1: IDWriteTextLayout インターフェイスを作成します。
IDWriteTextLayout インターフェイスへのポインターを MultiformattedText クラスのメンバーとして宣言します。
IDWriteTextLayout* pTextLayout_;
MultiformattedText::CreateDeviceIndependentResources メソッドの最後に、CreateTextLayout メソッドを呼び出して IDWriteTextLayout インターフェイス オブジェクトを作成します。 IDWriteTextLayout インターフェイスには、テキストの選択した部分に異なる書式を適用する機能など、追加の書式設定機能が用意されています。
// 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. ); }
パート 2: IDWriteTextLayout を使用した書式設定の適用。
フォント サイズ、太さ、下線などの書式設定は、 IDWriteTextLayout インターフェイスを使用して表示されるテキストの部分文字列に適用できます。
DWRITE_TEXT_RANGEを宣言し、IDWriteTextLayout::SetFontSize メソッドを呼び出して、"DirectWrite" のサブ文字列 "Di" のフォント サイズを 100 に設定します。
// 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); }
IDWriteTextLayout::SetUnderline メソッドを呼び出して、部分文字列 "DirectWrite" に下線を引きます。
// 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); }
IDWriteTextLayout::SetFontWeight メソッドを呼び出して、サブ文字列 "DirectWrite" のフォントの太さを太字に設定します。
if (SUCCEEDED(hr)) { // Format the word "DWrite" to be bold. DWRITE_TEXT_RANGE textRange = {20, 11 }; hr = pTextLayout_->SetFontWeight(DWRITE_FONT_WEIGHT_BOLD, textRange); }
パート 3: IDWriteTypography を使用した文字体裁機能の追加。
IDWriteFactory::CreateTypography メソッドを呼び出して、IDWriteTypography インターフェイス オブジェクトを宣言して作成します。
// Declare a typography pointer. IDWriteTypography* pTypography = NULL; // Create a typography interface object. if (SUCCEEDED(hr)) { hr = pDWriteFactory_->CreateTypography(&pTypography); }
スタイル セット 7 が指定されている DWRITE_FONT_FEATURE オブジェクトを宣言し、 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); }
DWRITE_TEXT_RANGE変数を宣言し、IDWriteTextLayout::SetTypography メソッドを呼び出してテキスト範囲を渡すことで、文字列全体で文字体裁を使用するようにテキスト レイアウトを設定します。
if (SUCCEEDED(hr)) { // Set the typography for the entire string. DWRITE_TEXT_RANGE textRange = {0, cTextLength_}; hr = pTextLayout_->SetTypography(pTypography, textRange); }
MultiformattedText::OnResize メソッドで、テキスト レイアウト オブジェクトの新しい幅と高さを設定します。
if (pTextLayout_) { pTextLayout_->SetMaxWidth(static_cast<FLOAT>(width / dpiScaleX_)); pTextLayout_->SetMaxHeight(static_cast<FLOAT>(height / dpiScaleY_)); }
パート 4: Direct2D DrawTextLayout メソッドを使用してテキストを描画する。
IDWriteTextLayout オブジェクトで指定されたテキスト レイアウト設定でテキストを描画するには、MultiformattedText::D rawText メソッドのコードを、IDWriteTextLayout::D rawTextLayout を使用するように変更します。
D2D1_POINT_2F変数を Delcare し、ウィンドウの左上のポイントに設定します。
D2D1_POINT_2F origin = D2D1::Point2F( static_cast<FLOAT>(rc.left / dpiScaleX_), static_cast<FLOAT>(rc.top / dpiScaleY_) );
Direct2D レンダー ターゲットの ID2D1RenderTarget::D rawTextLayout メソッドを呼び出し、IDWriteTextLayout ポインターを渡して、テキストを画面に描画します。
pRT_->DrawTextLayout( origin, pTextLayout_, pBlackBrush_ );
MultiformattedText クラスは、MultiformattedText.h および MultiformattedText.cpp に実装されます。