呈现到 GDI 图面

在某些情况下,你可能希望能够在 GDI 图面上显示DirectWrite文本。 IDWriteBitmapRenderTarget 接口封装要呈现文本的位图和设备上下文。 使用 IDWriteGdiInterop::CreateBitmapRenderTarget 方法创建 IDWriteBitmapRenderTarget,如以下代码所示。

if (SUCCEEDED(hr))
{
    hr = g_pGdiInterop->CreateBitmapRenderTarget(hdc, r.right, r.bottom, &g_pBitmapRenderTarget);
}

若要使用 IDWriteBitmapRenderTarget 呈现,必须实现派生自 IDWriteTextRenderer 接口的自定义文本呈现器回调接口。 必须实现用于绘制字形运行、下划线、删除线、内联对象等的方法。 有关方法的完整列表,请参阅 IDWriteTextRenderer 参考页。 并非每个方法都必须实现,它们只能返回 E_NOTIMPL,并且绘图将继续。

然后,可以使用 IDWriteTextLayout::D raw 方法并将实现的回调接口作为参数传递来绘制文本。 IDWriteTextLayout::D raw 方法调用所提供的自定义呈现器回调的方法。 DrawGlyphRunDrawUnderlineDrawInlineObjectDrawStrikethrough 方法执行绘图函数。

DrawGlyphRun 的实现中,调用 IDWriteBitmapRenderTarget::D rawGlyphRun 方法来绘制字形。 下划线、删除线和内联对象的呈现必须由自定义呈现器完成。

IDWriteBitmapRenderTarget::D rawGlyphRun 具有可选的 RECT out 参数,其中包含绘制文本的区域的边界。 可以使用此信息通过 GDI 提供的 SetBoundsRect 函数为设备上下文设置边界矩形。 以下代码是自定义呈现器 DrawGlyphRun 方法的示例实现。

STDMETHODIMP GdiTextRenderer::DrawGlyphRun(
    __maybenull void* clientDrawingContext,
    FLOAT baselineOriginX,
    FLOAT baselineOriginY,
    DWRITE_MEASURING_MODE measuringMode,
    __in DWRITE_GLYPH_RUN const* glyphRun,
    __in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
    IUnknown* clientDrawingEffect
    )
{
    HRESULT hr = S_OK;

    // Pass on the drawing call to the render target to do the real work.
    RECT dirtyRect = {0};

    hr = pRenderTarget_->DrawGlyphRun(
        baselineOriginX,
        baselineOriginY,
        measuringMode,
        glyphRun,
        pRenderingParams_,
        RGB(0,200,255),
        &dirtyRect
        );
    

    return hr;
}

IDWriteBitmapRenderTarget 接口呈现到内存中 DC) (设备上下文。 使用 IDWriteBitmapRenderTarget::GetMemoryDC 方法获取此 DC 的句柄。 执行绘图后,必须将 IDWriteBitmapRenderTarget 对象的内存 DC 复制到目标 GDI 图面。

可以使用 GetBoundsRect 函数检索边界矩形,然后将边界矩形与 BitBlt 函数结合使用,将呈现的DirectWrite文本从内存 DC 复制到 GDI 图面,如以下代码所示。

// Transfer from DWrite's rendering target to the window.
BitBlt(
    hdc,
    0, 0,
    size.cx, size.cy,
    memoryHdc,
    0, 0, 
    SRCCOPY | NOMIRRORBITMAP
    );