呈现目标是从 ID2D1RenderTarget 接口继承的资源。 呈现目标会创建用于绘图的资源并执行实际的绘图操作。 本文介绍不同类型的 Direct2D 呈现目标以及如何使用它们。
呈现目标
呈现目标是从 ID2D1RenderTarget 接口继承的资源。 呈现目标会创建用于绘图的资源并执行实际的绘图操作。 有多种呈现目标可用于通过以下方式呈现图形:
- ID2D1HwndRenderTarget 对象会将内容呈现到窗口。
- ID2D1DCRenderTarget 对象呈现到 GDI 设备上下文。
- 位图呈现目标对象将内容呈现到屏幕外位图。
- DXGI 呈现目标对象呈现到 DXGI 图面,以便与 Direct3D 一起使用。
由于呈现目标与特定的呈现设备相关联,因此它是一种依赖于设备的资源,如果设备被移除,它就会停止运行。
呈现目标功能
你可以指定呈现目标是否使用硬件加速以及远程显示是由本地计算机呈现还是由远程计算机呈现。 可以为有锯齿或无锯齿的呈现设置呈现目标。 对于具有大量基元的呈现场景,开发人员还可以在别名模式下呈现二维图形,并使用 D3D 多重采样抗锯齿来实现更大的可伸缩性。
呈现目标还可以将绘图操作分组到由 ID2D1Layer 接口表示的层中。 在呈现帧时,图层可用于收集绘图操作,以便组合在一起进行呈现。 对于某些应用场景,这可以是呈现到位图呈现目标的有用替代方法,然后重用位图内容,因为分层的分配成本低于 ID2D1BitmapRenderTarget。
目标可以创建与自身兼容的新呈现目标,这对于中间离屏呈现很有用,同时会保留在原始项上设置的各种呈现目标属性。
还可以在 Direct2D 呈现目标上通过调用 QueryInterface 获取到一个 ID2D1GdiInteropRenderTarget 的呈现目标,该目标具有 GetDC 和 ReleaseDC 方法,可以用于检索 GDI 设备上下文。 仅当使用 D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE 标志集创建呈现目标时,才能通过 GDI 进行呈现。 这种方法对于主要使用 Direct2D 呈现,但具有可扩展性模型或其他需要使用 GDI+ 呈现的旧内容的应用程序非常有用。 有关详细信息,请参阅 Direct2D 和 GDI 互操作概述。
呈现目标资源
就像工厂一样,呈现目标可以创建绘图资源。 呈现目标创建的任何资源都是设备相关的资源(就像呈现目标一样)。 呈现目标可以创建以下类型的资源:
- 位图
- 刷子
- 图层
- 网格
绘图命令
要呈现内容,你可以使用呈现目标绘图方法。 在开始绘制之前,调用 ID2D1RenderTarget::BeginDraw 方法。 绘制完成后,调用 ID2D1RenderTarget::EndDraw 方法。 在这些调用之间,你可以使用 Draw 和 Fill 方法来呈现绘图资源。 大多数 Draw 和 Fill 方法都采用形状(基本形状或几何形状)和用于填充或勾勒形状轮廓的画笔。
呈现目标提供剪裁、应用不透明度掩码和转换坐标空间的方法。
Direct2D 使用左手坐标系:正 x 轴值向右移动,正 y 轴值向下移动。
错误处理
呈现目标绘图命令不指示请求的操作是否成功。 要查明是否存在绘制错误,请调用呈现目标 Flush 方法或 EndDraw 方法以获取 HRESULT。
示例:将内容呈现到窗口
以下示例使用 CreateHwndRenderTarget 方法创建 ID2D1HwndRenderTarget。
RECT rc;
GetClientRect(m_hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(
rc.right - rc.left,
rc.bottom - rc.top
);
// Create a Direct2D render target.
hr = m_pD2DFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(m_hwnd, size),
&m_pRenderTarget
);
以下示例使用 ID2D1HwndRenderTarget 将文本绘制到窗口。
// 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;
}
此示例中已省略代码。