前回に引き続きDirect2Dの機能を使い、今度はテキストを描画します。
テキストはDirectWriteという方法で描画でき、GDIよりも高速かつ綺麗な表示が可能だそうです。
本当に綺麗かどうかは、後日検証をしたいと思います。
高速かも怪しいです。
DirectWriteも難しくありません。
凡その概要を書くと・・
・ID2D1Factoryの作成
・ID2D1HwndRenderTargetの作成
・IDWriteFactoryの作成
・IDWriteTextFormatでフォントを作成
・DrawText(~)で描画
です。
※但し、テキストの描画する違う方法として、文字の外枠の線をパス(曲線)に変換し、
そのパスを描画する方法などもあります。(これは後日)
ソースコード
#include <Windows.h>
#include <tchar.h>
#include <iostream>
// Direct2DのHeader
#include <d2d1.h>
// DirectWriteのHeader
#include <dwrite.h>
// lib Direct2D
#pragma comment( lib, "d2d1.lib" )
// lib DirectWrite
#pragma comment( lib, "dwrite.lib" )
#define WINDOW_WIDTH 1080
#define WINDOW_HEIGHT 720
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
#define CLASS_NAME "CLASS TEST01"
#define PROC_NAME "test01"
template<class T>
inline void safe_release(T& p) {
if (p) {
p->Release();
p = nullptr;
}
}
// グローバル変数として定義
// Direct2D用のファクトリ
ID2D1Factory* g_pD2d1Factory = nullptr;
// RenderTarget
ID2D1HwndRenderTarget* g_pRenderTarget = nullptr;
// DirectWrite用のファクトリー
IDWriteFactory* g_pDWFactory = nullptr;
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPreInst, LPTSTR lpCmdLine, int nCmdShow)
{
HWND hwnd;
MSG msg;
if (!hPreInst) {
WNDCLASS my_prog;
my_prog.style = CS_HREDRAW | CS_VREDRAW;
my_prog.lpfnWndProc = WndProc;
my_prog.cbClsExtra = 0;
my_prog.cbWndExtra = 0;
my_prog.hInstance = hInstance;
my_prog.hIcon = NULL;
my_prog.hCursor = LoadCursor(NULL, IDC_ARROW);
my_prog.hbrBackground = NULL;
my_prog.lpszMenuName = NULL;
my_prog.lpszClassName = _T(CLASS_NAME);
if (!RegisterClass(&my_prog)) {
return FALSE;
}
}
RECT rect = {
static_cast<LONG>(0),
static_cast<LONG>(0),
static_cast<LONG>(WINDOW_WIDTH),
static_cast<LONG>(WINDOW_HEIGHT)
};
AdjustWindowRect(
&rect, // クライアント矩形
WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION, // ウィンドウスタイル
FALSE // メニューフラグ
);
hwnd = CreateWindow(_T(CLASS_NAME),
_T(PROC_NAME),
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_THICKFRAME | WS_MAXIMIZEBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
rect.right - rect.left, // ウィンドウの幅
rect.bottom - rect.top, // ウィンドウの高さ
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
do {
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} while (msg.message != WM_QUIT);
return (int)(msg.wParam);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_SIZE: {
D2D1_SIZE_U oPixelSize = { LOWORD(lParam), HIWORD(lParam) };
// ターゲットリサイズ
g_pRenderTarget->Resize(&oPixelSize);
break;
}
case WM_DESTROY: {
// ID2D1HwndRenderTargetの破棄
safe_release(g_pRenderTarget);
// ID2D1Factoryの破棄
safe_release(g_pD2d1Factory);
// IDWriteFactoryの破棄
safe_release(g_pDWFactory);
PostQuitMessage(0);
break;
}
case WM_CREATE: {
CREATESTRUCT* tpCreateSt = (CREATESTRUCT*)lParam;
HRESULT hResult = S_OK;
// Direct2D用のファクトリーの作成
hResult = D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, &g_pD2d1Factory);
if (SUCCEEDED(hResult)) {
// RenderTargetのサイズを指定
D2D1_SIZE_U oPixelSize = {
static_cast<UINT32>(tpCreateSt->cx)
, static_cast<UINT32>(tpCreateSt->cy)
};
D2D1_RENDER_TARGET_PROPERTIES oRenderTargetProperties = D2D1::RenderTargetProperties();
D2D1_HWND_RENDER_TARGET_PROPERTIES oHwndRenderTargetProperties = D2D1::HwndRenderTargetProperties(hwnd, oPixelSize);
// Direct2DのRenderTargetの作成
hResult = g_pD2d1Factory->CreateHwndRenderTarget(
oRenderTargetProperties
, oHwndRenderTargetProperties
, &g_pRenderTarget
);
// DirectWriteのFactryを作成
if (SUCCEEDED(hResult)) {
hResult = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(&g_pDWFactory));
}
}
break;
}
case WM_PAINT: {
D2D1_SIZE_F oTargetSize = g_pRenderTarget->GetSize();
// 描画開始(Direct2D)
g_pRenderTarget->BeginDraw();
// 初期化マトリクスを行列にセット
g_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
// 背景の色を赤でクリア
D2D1_COLOR_F oBKColor = { 1.0f, 0.0f, 0.0f, 1.0f };
g_pRenderTarget->Clear(oBKColor);
// テキストフォーマットの作成
IDWriteTextFormat* pTextFormat = nullptr;
{
g_pDWFactory->CreateTextFormat(
L"Meiryo"
, NULL
, DWRITE_FONT_WEIGHT_NORMAL
, DWRITE_FONT_STYLE_NORMAL//DWRITE_FONT_STYLE_OBLIQUE
, DWRITE_FONT_STRETCH_NORMAL
, 64
, L""
, &pTextFormat
);
}
// ブラシの作成
ID2D1SolidColorBrush* pFontBrush = nullptr;
// 青いブラシを作成
g_pRenderTarget->CreateSolidColorBrush(
D2D1::ColorF(0.0f // R
, 0.0f // G
, 1.0f // B
, 1.0f // A
)
, &pFontBrush
);
std::wstring strText = L"コワーキングスペースでの開発";
// テキストの描画
g_pRenderTarget->DrawText(
strText.c_str() // 文字列
, strText.size() // 文字数
, pTextFormat
, &D2D1::RectF(0, 0, oTargetSize.width, oTargetSize.height)
, pFontBrush
, D2D1_DRAW_TEXT_OPTIONS_NONE
);
// ブラシの破棄
safe_release(pFontBrush);
// フォントの破棄
safe_release(pTextFormat);
// 描画終了(Direct2D)
g_pRenderTarget->EndDraw();
break;
}
default:
return(DefWindowProc(hwnd, msg, wParam, lParam));
}
return (0L);
}