Инициализация Direct2D
Дата создания: 2012-10-22 16:12:19
Последний раз редактировалось: 2012-10-22 16:18:55
Исходники к уроку:
1. Исходный код инициализации Direct2D
В этом уроке мы настроим нашу заготовку оконного приложения для использования с Direct2D. Главная сегодняшяя цель - уяснить, как происходит инициализация Direct2D. После инициализации мы выведем простую фигуру на экран.
Инициализация Direct2D
Инициализация Direct2D достаточно простая (по сравнению с инициализацией Direct3D :) и включает в себя следующие шаги:
1. Создание фабрики ID2D1Factory.
2. Создание объекта, на который будет происходить вывод графики - ID2D1RenderTarget.
3. Создание инструментов рисования (кисти, изображения). Мы начнём работать с кистями - ID2D1SolidColorBrush.
После этого можно начинать рисовать на объекте, который выводит графику.
Функция D2D1CreateFactory
Как и в других библиотеках DirectX, в Direct2D всё тоже начинается с функции. Сначала нужно создать объект ID2D1Factory (factory - фабрика). Данный объект позволит создавать различные ресурсы Direct2D.
Для выделения памяти под ID2D1Factory исопльзуется функция D2D1CreateFactory. Функция перегруженная, мы будем использовать вариант с двумя аргументами:
!1? templateПервый аргумент - тип фабрики: однопоточная, многопоточная. Начнём с однопоточных, поэтому этот параметр будет таким: D2D1_FACTORY_TYPE_SINGLE_THREADED.
Второй аргумент - адрес объекта ID2D1RenderTarget. После вызова функции этот аргумент будет содержать адрес созданной фабрики.
Давайте создадим фабрику. Перед вызовом D2D1CreateFactory нужно объявить интерфейс ID2D1RenderTarget:
!1? ID2D1Factory* factory = NULL; D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,&factory);?1!Теперь мы можем использовать переменную factory для создания ресурсов.
Создание HwndRenderTarget
Следующая задача - связать окно нашего приложения с Direct2D. Для этого нужно с помощью описателя окна (window handle) создать ресурс HwndRenderTarget (render target - цель вывода графики). Этот ресурс выводит, созданную с помощью него, графику в указанное окно.
HwndRenderTarget создаётся с помощью метода D2D1Factory::CreateHwndRenderTarget:
!1? HRESULT CreateHwndRenderTarget( [ref] const D2D1_RENDER_TARGET_PROPERTIES &renderTargetProperties, [ref] const D2D1_HWND_RENDER_TARGET_PROPERTIES &hwndRenderTargetProperties, [out] ID2D1HwndRenderTarget **hwndRenderTarget );?1!Первый аргумент - ссылка на заполненную структурную переменную D2D1_RENDER_TARGET_PROPERTIES - свойства ресурса визуализации. Можно автоматически заполнить эту переменную, вызвав функцию RenderTargetProperties. RenderTargetProperties находится в пространстве имён D2D1. Структура D2D1_RENDER_TARGET_PROPERTIES заполняется следующей информацией: формат пикселей, разрешение изображение (dpi) и т.д.
Второй аргумент - ссылка на D2D1_HWND_RENDER_TARGET_PROPERTIES - свойства окна, в которое будет осуществляться вывод графики. Здесь также можно воспользоваться вспомогательной функцией HwndRenderTargetProperties (тоже в пространстве имён D2D1), которая создаст нужную структурную переменную. В функцию нужно передать два параметра: описатель окна и размеры области вывода. Размеры области вывода должны быть в формате D2D1_SIZE_U - эта структура хранит пару целых чисел: ширина, высота. Вы не поверите, но для заполнения этой структуры тоже существует специальная функция - SizeU.
Третий параметр - адрес на объект ID2D1HwndRenderTarget, в котором и будет сохранён ресурс визуализации после выполнения метода:
!1? ID2D1HwndRenderTarget* rt = NULL; factory->CreateHwndRenderTarget( D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties( hWnd,D2D1::SizeU(rc.right-rc.left, rc.bottom-rc.top)), &rt);?1!Теперь rt может "рисовать".
Собственно, с инициализацией всё. Давайте теперь посмотрим как происходит рисование.
Создание кисти
В Direct2D кисти представлены интерфейсами ID2D1SolidColorBrush, ID2D1RadialGradientBrush, ID2D1BitmapBrush. Сегодня мы познакомимся с первым - ID2D1SolidColorBrush. Данная кисть закрашивает необходимую область каким-либо цветом.
Кисть ID2D1SolidColorBrush создаётся методом ID2D1RenderTarget::CreateSolidColorBrush. Данный метод перегружен. Мы рассмотрим вариант с двумя аргументами: цвет кисти и адрес создаваемой кисти:
!1? ID2D1SolidColorBrush* rbrush = NULL; rt->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::DarkRed), &rbrush);?1!Первый аргумент - цвет, заполняется через конструктор класса ColorF - единственный аргумент - константа класса ColorF. Список всех констант можно найти в документации к Direct2D.
После вызова метода CreaeSolidColorBrush у нас всё готово к рисованию.
Рисование прямоугольников в Direct2D
Вывод графики в Direct2D осуществляется между двумя вызовами интерфейса ID2D1HwndRenderTarget: BeginDraw (начать рисование), EndDraw (закончить рисование). В своём коде я расположил эти вызовы в основном цикле после попытки захвата сообщения.
При рисовании сначала нужно очистить область рисования. Для этого используется метод Clear с аргументом - цветом фона:
!1? rt->Clear(D2D1::ColorF(D2D1::ColorF::White));?1!Direct2D рисует прямоугольники с помощью метода ID2D1RenderTarget::DrawRectangle:
!1? void DrawRectangle( [ref] const D2D1_RECT_F &rect, [in] ID2D1Brush *brush, FLOAT strokeWidth = 1.0f, [in, optional] ID2D1StrokeStyle *strokeStyle = NULL );?1!Первый аргумент - координаты прямоугольника. Можно заполнить с помощью функции D2D1::RectF. Аргументы: x левого верхнего угла, y левого верхнего угла, x правого нижнего угла, y правого нижнего угла: !1? rt->DrawRectangle(D2D1::RectF(200.0f,200.0f,300.0f,300.0f),rbrush);?1!
В данном случае создаётся прямоугольник размером 100*100. Второй аргумент - кисть, которой будет рисоваться прямоугольник.
Третий и четвёртый аргументы необязательны. Третий - толщина линии, четвёртый - вид линии.
Полный код инициализации Direct2D
Давайте посмотрим на полный код. В исходнике к данном уроку есть готовый проект, который вы можете скомплировать и увидеть результат самостоятельно.
!1? #include <windows.h> #include <d2d1.h> #pragma comment(lib,"d2d1.lib") LRESULT _stdcall WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ); int _stdcall WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASS wc; wc.style = CS_OWNDC; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(6); wc.lpszMenuName = 0; wc.lpszClassName = L"class"; RegisterClass(&wc); HWND hWnd = CreateWindow( L"class", L"Direct2D init", WS_OVERLAPPEDWINDOW,100,100,600,600, NULL,NULL,hInstance,NULL); ID2D1Factory* factory = NULL; D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,&factory); ID2D1HwndRenderTarget* rt = NULL; factory->CreateHwndRenderTarget( D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties( hWnd,D2D1::SizeU(500,500)) ,&rt); ID2D1SolidColorBrush* rbrush = NULL; rt->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::Red), &rbrush); ShowWindow(hWnd,nCmdShow); UpdateWindow(hWnd); MSG msg; while(true) { if(PeekMessage(&msg,0,0,0,PM_REMOVE)) { if(msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } rt->BeginDraw(); rt->Clear(D2D1::ColorF(D2D1::ColorF::White)); rt->DrawRectangle( D2D1::RectF(200.0f,200.0f,300.0f,300.0f), rbrush,100.0f,NULL); rt->EndDraw(); } if (rbrush != NULL) rbrush->Release(); if (rt != NULL) rt->Release(); if (factory != NULL) factory->Release(); return 0; } LRESULT _stdcall WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_DESTROY: PostQuitMessage(0); return 0; default: return DefWindowProc(hWnd,msg,wParam,lParam); } } ?1!В результате работы этой программы мы увидим окно с красным квадратом посередине.
Завершение программы
Не забывайте, что при завершении программы необходимо освободить все ресурсы:
!1? if (rbrush != NULL) rbrush->Release(); if (rt != NULL) rt->Release(); if (factory != NULL) factory->Release();?1!Заключение
В данном уроке мы рассмотрели инициализацию Direct2D. В следующих уроках мы рассмотрим различные виды кистей.
На сегодня всё.