Direct2D 快速入门

Direct2D 是用于创建 2D 图形的本机代码即时模式 API。 本主题说明如何在典型的 Win32 应用程序中使用 Direct2D 绘制到 HWND

注意

如果要创建使用 Direct2D 的 Windows 应用商店应用,请参阅 direct2D 快速入门Windows 8主题。

 

本主题包含以下各节:

绘制简单矩形

若要使用 GDI 绘制矩形,可以处理 WM_PAINT 消息,如以下代码所示。

switch(message)
{

    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            BeginPaint(hwnd, &ps);

            // Obtain the size of the drawing area.
            RECT rc;
            GetClientRect(
                hwnd,
                &rc
            );          

            // Save the original object
            HGDIOBJ original = NULL;
            original = SelectObject(
                ps.hdc,
                GetStockObject(DC_PEN)
            );

            // Create a pen.            
            HPEN blackPen = CreatePen(PS_SOLID, 3, 0);

            // Select the pen.
            SelectObject(ps.hdc, blackPen);

            // Draw a rectangle.
            Rectangle(
                ps.hdc, 
                rc.left + 100, 
                rc.top + 100, 
                rc.right - 100, 
                rc.bottom - 100);   

            DeleteObject(blackPen);

            // Restore the original object
            SelectObject(ps.hdc, original);

            EndPaint(hwnd, &ps);
        }
        return 0;

// Code for handling other messages. 

使用 Direct2D 绘制相同矩形的代码类似:它创建绘图资源,描述要绘制的形状,绘制形状,然后释放绘图资源。 以下各节详细介绍了其中每个步骤。

步骤 1:包括 Direct2D 标头

除了 Win32 应用程序所需的标头外,还包括 d2d1.h 标头。

步骤 2:创建 ID2D1Factory

任何 Direct2D 示例首先需要创建 ID2D1Factory

ID2D1Factory* pD2DFactory = NULL;
HRESULT hr = D2D1CreateFactory(
    D2D1_FACTORY_TYPE_SINGLE_THREADED,
    &pD2DFactory
    );

ID2D1Factory 接口是使用 Direct2D 的起点;使用 ID2D1Factory 创建 Direct2D 资源。

创建工厂时,可以指定它是多线程还是单线程。 (有关多线程工厂的详细信息,请参阅 ID2D1Factory 参考页上的备注。) 此示例创建单线程工厂。

一般情况下,应用程序应创建一次工厂,并在应用程序的整个生命周期内保留该工厂。

步骤 3:创建 ID2D1HwndRenderTarget

创建工厂后,使用它来创建呈现目标。



// Obtain the size of the drawing area.
RECT rc;
GetClientRect(hwnd, &rc);

// Create a Direct2D render target          
ID2D1HwndRenderTarget* pRT = NULL;          
HRESULT hr = pD2DFactory->CreateHwndRenderTarget(
    D2D1::RenderTargetProperties(),
    D2D1::HwndRenderTargetProperties(
        hwnd,
        D2D1::SizeU(
            rc.right - rc.left,
            rc.bottom - rc.top)
    ),
    &pRT
);

呈现目标是可以执行绘图操作并创建与设备相关的绘图资源(如画笔)的设备。 不同类型的呈现器目标呈现到不同的设备。 前面的示例使用 ID2D1HwndRenderTarget,该 ID2D1HwndRenderTarget 呈现到屏幕的一部分。

如果可能,呈现器目标使用 GPU 来加速渲染操作并创建绘图资源。 否则,呈现目标使用 CPU 来处理呈现指令并创建资源。 (创建 render target 时,可以使用 D2D1_RENDER_TARGET_TYPE 标志修改此行为。)

CreateHwndRenderTarget 方法采用三个参数。 第一个参数 (D2D1_RENDER_TARGET_PROPERTIES 结构)指定远程显示选项,是强制呈现目标呈现为软件还是硬件,以及 DPI。 此示例中的代码使用 D2D1::RenderTargetProperties 帮助程序函数接受默认呈现目标属性。

第二个参数 (D2D1_HWND_RENDER_TARGET_PROPERTIES 结构)指定要呈现内容的 HWND 、呈现目标的初始大小 (像素) 及其 呈现选项。 此示例使用 D2D1::HwndRenderTargetProperties 帮助程序函数来指定 HWND 和初始大小。 它使用默认的演示选项。

第三个参数是接收呈现目标引用的指针的地址。

创建呈现目标且硬件加速可用时,可在计算机的 GPU 上分配资源。 通过创建一次呈现器目标并尽可能长时间地保留它,可以获得性能优势。 应用程序应创建一次呈现目标,并在应用程序的生存期或收到 D2DERR_RECREATE_TARGET 错误之前保留这些目标。 收到此错误时,需要重新创建呈现目标 (以及它创建的任何资源) 。

步骤 4:创建画笔

与工厂一样,呈现器目标可以创建绘图资源。 在此示例中,呈现器目标创建画笔。

ID2D1SolidColorBrush* pBlackBrush = NULL;
if (SUCCEEDED(hr))
{
            
    pRT->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF::Black),
        &pBlackBrush
        ); 
}

画笔是绘制区域的对象,如形状的笔划或几何图形的填充。 此示例中的画笔使用预定义的纯色(黑色)绘制区域。

Direct2D 还提供其他类型的画笔:用于绘制线性渐变和径向渐变的渐变画笔,以及用于使用位图和图案进行绘制的位图画笔。

某些绘图 API 提供用于绘制轮廓的笔和用于填充形状的画笔。 Direct2D 不同:它不提供笔对象,但使用画笔绘制轮廓和填充形状。 绘制轮廓时,使用 ID2D1StrokeStyle 接口和画笔来控制路径绘制操作。

画笔只能与创建它的呈现器目标一起使用,以及同一资源域中的其他呈现目标。 通常,应创建一次画笔,并在创建画笔的呈现器目标的生命周期内保留这些画笔。 ID2D1SolidColorBrush 是唯一的例外;由于创建成本相对较低,因此每次绘制帧时都可以创建 ID2D1SolidColorBrush ,而不会造成任何明显的性能下降。 还可以使用单个 ID2D1SolidColorBrush ,每次使用时只需更改其颜色。

步骤 5:绘制矩形

接下来,使用呈现器目标绘制矩形。

 
pRT->BeginDraw();

pRT->DrawRectangle(
    D2D1::RectF(
        rc.left + 100.0f,
        rc.top + 100.0f,
        rc.right - 100.0f,
        rc.bottom - 100.0f),
        pBlackBrush);

HRESULT hr = pRT->EndDraw();  

DrawRectangle 方法采用两个参数:要绘制的矩形和用于绘制矩形轮廓的画笔。 (可选)还可以指定笔划宽度、短划线图案、线条联接和尾帽选项。

必须在发出任何绘图命令之前调用 BeginDraw 方法,并且必须在发出绘图命令后调用 EndDraw 方法。 EndDraw 方法返回一个 HRESULT,指示绘图命令是否成功。

步骤 6:释放资源

如果没有更多要绘制的帧,或者收到 D2DERR_RECREATE_TARGET 错误,请释放呈现目标及其创建的任何设备。

 
SafeRelease(pRT);
SafeRelease(pBlackBrush);

当应用程序使用完 Direct2D 资源 ((例如即将退出) 时)时,请释放 Direct2D 工厂。

 
SafeRelease(pD2DFactory);

创建简单的 Direct2D 应用程序

本主题中的代码演示 Direct2D 应用程序的基本元素。 为简洁起见,本主题省略了编写良好的应用程序的特征的应用程序框架和错误处理代码。 有关显示创建简单 Direct2D 应用程序的完整代码并演示最佳设计做法的更详细演练,请参阅 创建简单的 Direct2D 应用程序

创建简单的 Direct2D 应用程序