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


Отрисовать на поверхность GDI

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

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

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

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