Краткое руководство по Direct2D для Windows 8
Direct2D — это API прямого кода для создания двухD-графики. В этом разделе показано, как использовать Direct2D для рисования в Windows::UI::Core::CoreWindow.
Этот раздел состоит из следующих подразделов.
- Рисование простого прямоугольника
- Шаг 1. Включение заголовка Direct2D
- Шаг 2. Создание ID2D1Factory1
- Шаг 3. Создание ID2D1Device и ID2D1DeviceContext
- Шаг 4. Создание кисти
- Шаг 5. Рисование прямоугольника
- Пример кода
Рисование простого прямоугольника
Чтобы нарисовать прямоугольник с помощью 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
В дополнение к заголовкам, необходимым для приложения, включите заголовки d2d1.h и d2d1_1.h.
Шаг 2. Создание ID2D1Factory1
Одна из первых вещей, которую делает любой пример Direct2D, — это создание ID2D1Factory1.
DX::ThrowIfFailed(
D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
__uuidof(ID2D1Factory1),
&options,
&m_d2dFactory
)
);
Интерфейс ID2D1Factory1 является отправной точкой для использования Direct2D; используйте ID2D1Factory1 для создания ресурсов Direct2D.
При создании фабрики можно указать, является ли она многопоточной или однопоточной. (Дополнительные сведения о многопоточных фабриках см. в примечаниях на странице справочника по ID2D1Factory.) В этом примере создается однопоточная фабрика.
Как правило, приложение должно создать фабрику один раз и сохранить ее в течение всего срока действия приложения.
Шаг 3. Создание ID2D1Device и ID2D1DeviceContext
После создания фабрики используйте ее для создания устройства Direct2D, а затем используйте устройство для создания контекста устройства Direct2D. Чтобы создать эти объекты Direct2D, необходимо иметь устройство Direct3D 11 , устройство DXGI и цепочку буферов DXGI. Сведения о создании необходимых компонентов см. в разделе Устройства и контексты устройств .
// Obtain the underlying DXGI device of the Direct3D11.1 device.
DX::ThrowIfFailed(
m_d3dDevice.As(&dxgiDevice)
);
// Obtain the Direct2D device for 2-D rendering.
DX::ThrowIfFailed(
m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice)
);
// And get its corresponding device context object.
DX::ThrowIfFailed(
m_d2dDevice->CreateDeviceContext(
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
&m_d2dContext
)
);
Контекст устройства — это устройство, которое может выполнять операции рисования и создавать зависимые от устройства ресурсы рисования, такие как кисти. Контекст устройства также используется для связывания ID2D1Bitmap с поверхностью DXGI для использования в качестве целевого объекта отрисовки. Контекст устройства может отображаться для различных типов целевых объектов.
Приведенный здесь код объявляет свойства растрового рисунка, который связывается с цепочкой буферов DXGI, которая отрисовывается в CoreWindow. Метод ID2D1DeviceContext::CreateBitmapFromDxgiSurface получает поверхность Direct2D из поверхности DXGI. Это делает его таким образом, что все, что отображается в целевом ID2D1Bitmap , отображается на поверхности цепочки буферов.
Получив поверхность Direct2D, используйте метод ID2D1DeviceContext::SetTarget , чтобы задать его в качестве активного целевого объекта отрисовки.
// Now we set up the Direct2D render target bitmap linked to the swapchain.
// Whenever we render to this bitmap, it will be directly rendered to the
// swapchain associated with the window.
D2D1_BITMAP_PROPERTIES1 bitmapProperties =
BitmapProperties1(
D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
m_dpi,
m_dpi
);
// Direct2D needs the dxgi version of the backbuffer surface pointer.
ComPtr<IDXGISurface> dxgiBackBuffer;
DX::ThrowIfFailed(
m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))
);
// Get a D2D surface from the DXGI back buffer to use as the D2D render target.
DX::ThrowIfFailed(
m_d2dContext->CreateBitmapFromDxgiSurface(
dxgiBackBuffer.Get(),
&bitmapProperties,
&m_d2dTargetBitmap
)
);
// So now we can set the Direct2D render target.
m_d2dContext->SetTarget(m_d2dTargetBitmap.Get());
Шаг 4. Создание кисти
Как и в случае с фабрикой, контекст устройства может создавать ресурсы рисования. В этом примере контекст устройства создает кисть.
ComPtr<ID2D1SolidColorBrush> pBlackBrush;
DX::ThrowIfFailed(
m_d2dContext->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::Black),
&pBlackBrush
)
);
Кисть — это объект, который рисует область, например росчерк фигуры или заливку геометрии. Кисть в этом примере закрашивает область предопределенным сплошным цветом, черным цветом.
Direct2D также предоставляет другие типы кистей: градиентные кисти для рисования линейных и радиальных градиентов, точечные кисти для рисования точечными рисунками и узорами и, начиная с Windows 8, кисть изображения для рисования с отрисованным изображением.
Некоторые API рисования предоставляют ручки для рисования контуров и кисти для заполнения фигур. Direct2D отличается: он не предоставляет объект пера, но использует кисть для рисования контуров и заполнения фигур. При рисовании контуров используйте интерфейс ID2D1StrokeStyle или начиная с Windows 8 интерфейса ID2D1StrokeStyle1 с кистью для управления операциями поглаживания пути.
Кисть может использоваться только с целевым объектом отрисовки, который ее создал, и с другими целевыми объектами отрисовки в том же домене ресурсов. Как правило, кисти следует создавать один раз и сохранять их на протяжении всего времени существования созданного целевого объекта отрисовки. ID2D1SolidColorBrush является одиноким исключением; Так как создание является относительно недорогим, вы можете создавать ID2D1SolidColorBrush каждый раз при рисовании кадра без заметного снижения производительности. Вы также можете использовать один id2D1SolidColorBrush и просто изменять его цвет или прозрачность каждый раз при его использовании.
Шаг 5. Рисование прямоугольника
Затем используйте контекст устройства для рисования прямоугольника.
m_d2dContext->BeginDraw();
m_d2dContext->DrawRectangle(
D2D1::RectF(
rc.left + 100.0f,
rc.top + 100.0f,
rc.right - 100.0f,
rc.bottom - 100.0f),
pBlackBrush);
DX::ThrowIfFailed(
m_d2dContext->EndDraw()
);
DX::ThrowIfFailed(
m_swapChain->Present1(1, 0, ¶meters);
);
Метод DrawRectangle принимает два параметра: прямоугольник для рисования и кисть, используемая для рисования контура прямоугольника. При необходимости можно также указать ширину штриха, шаблон дефиса, соединение линий и конечный заголовок.
Перед выполнением команд рисования необходимо вызвать метод BeginDraw , а после завершения выполнения команд рисования — метод EndDraw . Метод EndDraw возвращает HRESULT , который указывает, были ли команды рисования успешными. В противном случае вспомогательная функция ThrowIfFailed вызовет исключение.
Метод IDXGISwapChain::P resent переключает буферную поверхность на поверхность на экране для отображения результата.
Пример кода
В коде в этом разделе показаны основные элементы приложения Direct2D. Для краткости в разделе пропускается платформа приложений и код обработки ошибок, характерный для правильно написанного приложения.