Поделиться через


Отрисовка на GDI Surface

В некоторых случаях может потребоваться отображать DirectWrite текст на поверхности GDI. Интерфейс IDWriteBitmapRenderTarget инкапсулирует растровое изображение и контекст устройства для отрисовки текста. Вы создаете IDWriteBitmapRenderTarget с помощью метода IDWriteGdiInterop::CreateBitmapRenderTarget , как показано в следующем коде.

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 вызывает методы пользовательского обратного вызова отрисовщика, который вы предоставляете. Методы DrawGlyphRun, DrawUnderline, DrawInlineObject и DrawStrikethrough выполняют функции рисования.

В реализации DrawGlyphRun вызовите метод IDWriteBitmapRenderTarget::D rawGlyphRun для рисования глифов. Отрисовка подчеркивающих, зачеркивающих и встроенных объектов должна выполняться пользовательским отрисовщиком.

IDWriteBitmapRenderTarget::D rawGlyphRun имеет необязательный параметр RECT out, содержащий границы области, в которой был нарисован текст. Эти сведения можно использовать для задания ограничивающего прямоугольника для контекста устройства с помощью функции SetBoundsRect , предоставляемой GDI. Ниже приведен пример реализации метода 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 . Как только рисование будет выполнено, память контроллера домена объекта IDWriteBitmapRenderTarget должна быть скопирована в целевую поверхность GDI.

Ограничивающий прямоугольник можно получить с помощью функции GetBoundsRect, а затем использовать ограничивающий прямоугольник с функцией BitBlt, чтобы скопировать отрисованный DirectWrite текст из контроллера домена памяти на поверхность GDI, как показано в следующем коде.

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