わびさびサンプルソース

WindowsやHTML5などのプログラムのサンプルコードやフリーソフトを提供します。

Direct2Dで文字列の幅と高さを取得する

Direct2Dで文字列の幅と高さを取得するには、IDWriteTextLayoutインターフェイスのGetMetrics()メソッドを使います。 取得できるDWRITE_TEXT_METRICS構造体の、left, top, width, heightに矩形が入ります。

#include <stdio.h>
#include <tchar.h>
#include <locale.h>
#include <iostream>
#include <windows.h>
#include <wingdi.h>
#include <d2d1.h>
#include <dwrite.h>



// lib
#pragma comment( lib, "d2d1.lib" )
#pragma comment( lib, "dwrite.lib" )



/*
	メインウインドウイベント処理
*/
LRESULT CALLBACK eMainWindowProc(
	  HWND	 hwnd	// handle to window
	, UINT	 uMsg	// message identifier
	, WPARAM wParam // first message parameter
	, LPARAM lParam // second message parameter
);



// グローバル変数
ID2D1Factory* pD2d1Factory = NULL;
IDWriteFactory* pDWFactory = NULL;
ID2D1HwndRenderTarget* pRenderTarget = NULL;



/*
	Direct2Dで文字列の幅と高さを取得
*/
int _tmain
(
	  int argc
	, _TCHAR* argv[]
)
{
	// 標準出力にユニコードを表示できるようにする
	setlocale( LC_ALL, "Japanese" );

	WNDCLASSEX tWndClass;
	HINSTANCE  hInstance;
	TCHAR*	   cpClassName;
	TCHAR*	   cpWindowName;
	TCHAR*	   cpMenu;
	HWND	   hWnd;
	MSG		   tMsg;


	// アプリケーションインスタンス
	hInstance	 = ::GetModuleHandle( NULL );

	// クラス名称
	cpClassName	 = _T("MainWindowClass");

	// メニュー
	cpMenu		 = MAKEINTRESOURCE( NULL );

	// ウインドウ名称
	cpWindowName = _T("Direct2Dで文字列の幅と高さを取得");

	// ウインドウクラスパラメータセット
	tWndClass.cbSize		= sizeof( WNDCLASSEX );
	tWndClass.style			= CS_HREDRAW | CS_VREDRAW;
	tWndClass.lpfnWndProc	= eMainWindowProc;
	tWndClass.cbClsExtra	= 0;	// ::GetClassLong で取得可能なメモリ
	tWndClass.cbWndExtra	= 0;	// ::GetWindowLong で取得可能なメモリ
	tWndClass.hInstance		= hInstance; 
	tWndClass.hIcon			= ::LoadIcon( NULL, IDI_APPLICATION );
	tWndClass.hCursor		= ::LoadCursor( NULL, IDC_ARROW );
	tWndClass.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
	tWndClass.lpszMenuName	= cpMenu;
	tWndClass.lpszClassName = cpClassName;
	tWndClass.hIconSm		= NULL;

	// ウインドウクラス生成
	if ( 0 == ::RegisterClassEx( &tWndClass ) ) {

		/* 失敗 */
		return( -1 );
	}

	// ウインドウを生成する
	hWnd = ::CreateWindowEx (
		  0						  // extended window style
		, tWndClass.lpszClassName // pointer to registered class name
		, cpWindowName			  // pointer to window name
		, WS_OVERLAPPEDWINDOW	  // window style
		, CW_USEDEFAULT			  // horizontal position of window
		, CW_USEDEFAULT			  // vertical position of window
		, 640					  // window width
		, 480					  // window height
		, NULL					  // handle to parent or owner window
		, NULL					  // handle to menu, or child-window identifier
		, hInstance				  // handle to application instance
		, (VOID*)0x12345678		  // pointer to window-creation data
	);


	/*
		メッセージループ
	*/
	while( 0 != ::GetMessage( &tMsg, NULL, 0, 0 ) ) {
		::TranslateMessage ( &tMsg );
		::DispatchMessage ( &tMsg );
	}

	// WM_QUITの終了コードを返却する
	return( tMsg.wParam );
}



/*
	メインウインドウイベント処理
*/
LRESULT CALLBACK eMainWindowProc
(
	  HWND	 hWnd	// handle to window
	, UINT	 uMsg	// message identifier
	, WPARAM wParam // first message parameter
	, LPARAM lParam // second message parameter
)
{
	switch( uMsg ) {
	case WM_CREATE:
	//--------------------------------------------
	// WM_CREATE
	//--------------------------------------------
		{
			CREATESTRUCT* tpCreateSt = (CREATESTRUCT*)lParam;

			/* パラメータ表示 */
			wprintf(
				L"CREATESTRUCT¥n"
				L"¥tlpCreateParams = 0x%08x¥n"
				L"¥thInstance	   = 0x%08x¥n"
				L"¥thMenu		   = 0x%08x¥n"
				L"¥thwndParent	   = 0x%08x¥n"
				L"¥tcy			   = %d¥n"
				L"¥tcx			   = %d¥n"
				L"¥ty			   = %d¥n"
				L"¥tx			   = %d¥n"
				L"¥tstyle		   = 0x%08x¥n"
				L"¥tlpszName	   = ¥"%s¥"¥n"
				L"¥tlpszClass	   = ¥"%s¥"¥n"
				L"¥tdwExStyle	   = 0x%08x¥n"
				, tpCreateSt->lpCreateParams
				, tpCreateSt->hInstance
				, tpCreateSt->hMenu
				, tpCreateSt->hwndParent
				, tpCreateSt->cy
				, tpCreateSt->cx
				, tpCreateSt->y
				, tpCreateSt->x
				, tpCreateSt->style
				, tpCreateSt->lpszName
				, tpCreateSt->lpszClass
				, tpCreateSt->dwExStyle
			);

			HRESULT hResult = S_OK;


			/*
				ID2D1Factoryの生成
			*/
			hResult = ::D2D1CreateFactory( D2D1_FACTORY_TYPE_MULTI_THREADED, &pD2d1Factory );
			if ( FAILED( hResult ) ) {

				// エラー
				std::wcout << L"D2D1CreateFactory失敗" << std::endl;
				break;
			}


			/*
				IDWriteFactoryの生成
			*/
			hResult = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>( &pDWFactory ) );
			if ( FAILED( hResult ) ) {

				// エラー
				std::wcout << L"D2D1CreateFactory失敗" << std::endl;
				break;
			}


			/*
				ID2D1HwndRenderTargetの生成
			*/
			{
				D2D1_SIZE_U oPixelSize = {
					  tpCreateSt->cx
					, tpCreateSt->cy
				};

				D2D1_RENDER_TARGET_PROPERTIES oRenderTargetProperties = D2D1::RenderTargetProperties();

				D2D1_HWND_RENDER_TARGET_PROPERTIES oHwndRenderTargetProperties = D2D1::HwndRenderTargetProperties( hWnd, oPixelSize );


				/*
					ID2D1HwndRenderTargetの生成
				*/
				hResult = pD2d1Factory->CreateHwndRenderTarget(
						  oRenderTargetProperties
						, oHwndRenderTargetProperties
						, &pRenderTarget
					);
				if ( FAILED( hResult ) ) {

					// エラー
					std::wcout << L"CreateHwndRenderTarget失敗" << std::endl;
					break;
				}
			}

			// ウインドウを表示する
			::ShowWindow( hWnd, SW_SHOW );
		}
		break;


	case WM_DESTROY:
	//--------------------------------------------
	// WM_DESTROY
	//--------------------------------------------
		{
			// ID2D1HwndRenderTargetの破棄
			if ( NULL != pRenderTarget )  {
				pRenderTarget->Release();
			}

			// IDWriteFactoryの破棄
			if ( NULL != pDWFactory ) {
				pDWFactory->Release();
			}

			// ID2D1Factoryの破棄
			if ( NULL != pD2d1Factory )  {
				pD2d1Factory->Release();
			}
			// 終了する( 引数はそのまま終了コードとなります )
			::PostQuitMessage( 0 );
		}
		break;


	case WM_SIZE:
	//--------------------------------------------
	// WM_SIZE
	//--------------------------------------------
		{
			D2D1_SIZE_U oPixelSize = { LOWORD( lParam ), HIWORD( lParam ) };

			// ターゲットリサイズ
			pRenderTarget->Resize( &oPixelSize );
		}
		break;


	case WM_ERASEBKGND:
	//--------------------------------------------
	// WM_ERASEBKGND
	//--------------------------------------------
		{
			;
		}
		return( TRUE );


	case WM_PAINT:
	//--------------------------------------------
	// WM_PAINT
	//--------------------------------------------
		{
			HRESULT hResult = S_OK;

			// ターゲットサイズの取得
			D2D1_SIZE_F oTargetSize = pRenderTarget->GetSize();

			// 描画開始
			PAINTSTRUCT tPaintStruct;
			::BeginPaint( hWnd, &tPaintStruct );

			// 描画開始(Direct2D)
			pRenderTarget->BeginDraw();

			// 背景のクリア
			D2D1_COLOR_F oBKColor = { 1.0f, 1.0f, 1.0f, 1.0f };
			pRenderTarget->Clear( oBKColor );


			/*
				テキストの描画
			*/
			{
				/*
					ブラシの生成(黒)
				*/
				ID2D1SolidColorBrush* pBrush = NULL;
				{
					pRenderTarget->CreateSolidColorBrush(
							  D2D1::ColorF( D2D1::ColorF::Black )
							, &pBrush
						);
				}


				/*
					ブラシの生成(赤)
				*/
				ID2D1SolidColorBrush* pBrushR = NULL;
				{
					pRenderTarget->CreateSolidColorBrush(
							  D2D1::ColorF( D2D1::ColorF::Red )
							, &pBrushR
						);
				}


				/*
					テキストフォーマットの生成
				*/
				IDWriteTextFormat* pTextFormat = NULL;
				{
					pDWFactory->CreateTextFormat(
								  L"Meiryo"
								, NULL
								, DWRITE_FONT_WEIGHT_NORMAL
								, DWRITE_FONT_STYLE_NORMAL
								, DWRITE_FONT_STRETCH_NORMAL
								, 128
								, L""
								,&pTextFormat
							);
				}


				std::wstring strText = L"Hello World!!";

				D2D1_RECT_F tTextRectF;
				{
					IDWriteTextLayout* pTextLayout = NULL;

					// IDWriteTextLayoutの取得
					hResult = pDWFactory->CreateTextLayout(
							  strText.c_str()		// 文字列
							, strText.size()		// 文字列の幅
							, pTextFormat			// DWriteTextFormat
							, oTargetSize.width		// 枠の幅
							, oTargetSize.height	// 枠の高さ
							, &pTextLayout
						);
					if ( SUCCEEDED( hResult ) ) {


						DWRITE_TEXT_METRICS tTextMetrics;

						// Metricsの取得
						pTextLayout->GetMetrics( &tTextMetrics );

						/*
							文字列矩形の取得
						*/
						tTextRectF = D2D1::RectF(
								  tTextMetrics.left							// left
								, tTextMetrics.top							// top
								, tTextMetrics.left + tTextMetrics.width	// right
								, tTextMetrics.top  + tTextMetrics.height	// bottom
							);

						// 四角形の描画
						pRenderTarget->DrawRectangle( &tTextRectF, pBrushR, 1.0f );

						// IDWriteTextLayoutの破棄
						pTextLayout->Release();
					}
				}

				/*
					テキストの描画
				*/
				if ( NULL != pBrush && NULL != pTextFormat ) {

					// テキストの描画
					pRenderTarget->DrawText(
							  strText.c_str()	// 文字列
							, strText.size()	// 文字数
							, pTextFormat
							, &D2D1::RectF( 0, 0, oTargetSize.width, oTargetSize.height )
							, pBrush
							, D2D1_DRAW_TEXT_OPTIONS_NONE
						);
				}

				// テキストフォーマットの破棄
				if ( NULL != pTextFormat ) {
					pTextFormat->Release();
				}

				// ブラシの破棄(赤)
				if ( NULL != pBrushR ) {
					pBrushR->Release();
				}

				// ブラシの破棄(黒)
				if ( NULL != pBrush ) {
					pBrush->Release();
				}
			}

			// 描画終了(Direct2D)
			pRenderTarget->EndDraw();

			// 描画終了
			::EndPaint( hWnd, &tPaintStruct );
		}
		return( FALSE );
	}

	// デフォルト処理呼び出し
	return ::DefWindowProc( hWnd, uMsg, wParam, lParam );
}



実行結果







わびさびサンプルソース

WindowsやHTML5などのプログラムのサンプルコードやフリーソフトを提供します。