Direct2D導入(ID2D1HwndRenderTarget)
今回はDirect2Dを用いて、下記のような描画を行うところまで実装してみたいと思います。
ウィンドウ生成、表示関数
Direct2Dの描画先として、通常のWindowsのウィンドウを作成、実行する関数を準備します。
内容は一般的なもので、特に変わったものではありません。
HWND CreateHWND(WNDPROC wndProc) { WNDCLASSEX wndclass; wndclass.cbSize = sizeof(WNDCLASSEX); wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; wndclass.lpfnWndProc = wndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = GetModuleHandle(NULL); wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = NULL; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = L"Main Window"; wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); RegisterClassEx(&wndclass); HWND hwnd = CreateWindow( L"Main Window", L"Main Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, wndclass.hInstance, NULL ); return hwnd; }
void Run(HWND hwnd) { ShowWindow(hwnd, SW_SHOWNORMAL); MSG msg; while (GetMessage(&msg, nullptr, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } }
Direct2D初期化
ID2D1HwndRenderTargetを生成する関数を作成します。
ID2D1Factory経由で作成を行います。
#include <d2d1.h> #pragma comment(lib, "d2d1.lib") #include <wrl\client.h> using namespace Microsoft::WRL; ComPtr<ID2D1HwndRenderTarget> CreateRenderTarget(HWND hwnd) { ComPtr<ID2D1Factory> factory; AssertHR(D2D1CreateFactory<ID2D1Factory>(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory)); ComPtr<ID2D1HwndRenderTarget> renderTarget; AssertHR(factory->CreateHwndRenderTarget( D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties(hwnd), &renderTarget )); return renderTarget; }
楕円描画
RenderTargetいっぱいに楕円を描画する関数となります。
void Draw(ID2D1HwndRenderTarget* renderTarget) { renderTarget->BeginDraw(); renderTarget->Clear(D2D1::ColorF(D2D1::ColorF::LightYellow)); D2D1_SIZE_F size = renderTarget->GetSize(); float rx = size.width / 2; float ry = size.height / 2; D2D1_ELLIPSE ellipse = D2D1::Ellipse(D2D1::Point2F(rx, ry), rx, ry); ComPtr<ID2D1SolidColorBrush> brush; AssertHR(renderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Orange), &brush)); renderTarget->FillEllipse(ellipse, brush.Get()); AssertHR(renderTarget->EndDraw()); }
WndProc
WM_SIZEにてRenderTargetのサイズを変更し、WM_PAINTにて上記のDraw関数を呼ぶよう実装します。
ComPtr<ID2D1HwndRenderTarget> g_renderTarget; LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_PAINT: Draw(g_renderTarget.Get()); return 0; case WM_SIZE: g_renderTarget->Resize(D2D1::SizeU(LOWORD(lParam), HIWORD(lParam))); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, msg, wParam, lParam); }
main
最終的にmain関数はこのようになります。
int main() { HWND hwnd = CreateHWND(WndProc); g_renderTarget = CreateRenderTarget(hwnd); Run(hwnd); return 0; }