如何绘制文本

若要使用 Direct2D 绘制文本,请使用 ID2D1RenderTarget::D rawText 方法处理具有单一格式的文本。 或者,将 ID2D1RenderTarget::D rawTextLayout 方法用于多种格式、高级 OpenType 功能或命中测试。 这些方法使用 DirectWrite API 提供高质量的文本显示。

DrawText 方法

若要绘制具有单一格式的文本,请使用 DrawText 方法。 若要使用此方法,请先使用 IDWriteFactory 创建 IDWriteTextFormat 实例。

以下代码创建 IDWriteTextFormat 对象,并将其存储在 m_pTextFormat 变量中。

// Create resources which are not bound
// to any device. Their lifetime effectively extends for the
// duration of the app. These resources include the Direct2D and
// DirectWrite factories,  and a DirectWrite Text Format object
// (used for identifying particular font characteristics).
//
HRESULT DemoApp::CreateDeviceIndependentResources()
{
    static const WCHAR msc_fontName[] = L"Verdana";
    static const FLOAT msc_fontSize = 50;
    HRESULT hr;

    // Create a Direct2D factory.
    hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory);

    if (SUCCEEDED(hr))
    {        
        // Create a DirectWrite factory.
        hr = DWriteCreateFactory(
            DWRITE_FACTORY_TYPE_SHARED,
            __uuidof(m_pDWriteFactory),
            reinterpret_cast<IUnknown **>(&m_pDWriteFactory)
            );
    }
    if (SUCCEEDED(hr))
    {
        // Create a DirectWrite text format object.
        hr = m_pDWriteFactory->CreateTextFormat(
            msc_fontName,
            NULL,
            DWRITE_FONT_WEIGHT_NORMAL,
            DWRITE_FONT_STYLE_NORMAL,
            DWRITE_FONT_STRETCH_NORMAL,
            msc_fontSize,
            L"", //locale
            &m_pTextFormat
            );
    }
    if (SUCCEEDED(hr))
    {
        // Center the text horizontally and vertically.
        m_pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
        
        m_pTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
    }

    return hr;
}

由于 IDWriteFactoryIDWriteTextFormat 对象是 与设备无关的资源,因此只需创建一次即可提高应用程序的性能,而无需在每次呈现帧时重新创建它们。

创建文本格式对象后,可以将它与呈现器目标一起使用。 以下代码使用呈现器目标的 DrawText 方法 (m_pRenderTarget 变量) 绘制文本。

//  Called whenever the application needs to display the client
//  window. This method writes "Hello, World"
//
//  Note that this function will automatically discard device-specific
//  resources if the Direct3D device disappears during function
//  invocation, and will recreate the resources the next time it's
//  invoked.
//
HRESULT DemoApp::OnRender()
{
    HRESULT hr;

    hr = CreateDeviceResources();

    if (SUCCEEDED(hr))
    {
        static const WCHAR sc_helloWorld[] = L"Hello, World!";

        // Retrieve the size of the render target.
        D2D1_SIZE_F renderTargetSize = m_pRenderTarget->GetSize();

        m_pRenderTarget->BeginDraw();

        m_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());

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

        m_pRenderTarget->DrawText(
            sc_helloWorld,
            ARRAYSIZE(sc_helloWorld) - 1,
            m_pTextFormat,
            D2D1::RectF(0, 0, renderTargetSize.width, renderTargetSize.height),
            m_pBlackBrush
            );

        hr = m_pRenderTarget->EndDraw();

        if (hr == D2DERR_RECREATE_TARGET)
        {
            hr = S_OK;
            DiscardDeviceResources();
        }
    }

    return hr;
}

DrawTextLayout 方法

DrawTextLayout 方法呈现 IDWriteTextLayout 对象。 使用此方法可将多种格式应用于文本块 (例如将部分文本) 下划线、使用高级 OpenType 功能或执行命中测试支持。

DrawTextLayout 方法还具有重复绘制相同文本的性能优势。 IDWriteTextLayout 对象度量并在创建文本时对其进行布局。 如果仅创建 IDWriteTextLayout 对象一次,并且每次必须重新绘制文本时重复使用它,则性能会提高,因为系统不必再次测量和布局文本。

在使用 DrawTextLayout 方法之前,必须使用 IDWriteFactory 创建 IDWriteTextFormatIDWriteTextLayout 对象。 创建这些对象后,调用 DrawTextLayout 方法。

有关详细信息和示例,请参阅 文本格式和布局 概述。

DrawText

DrawTextLayout

IDWriteTextFormat

IDWriteTextLayout

文本格式和布局