わびさびサンプルソース

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

Direct2Dでカラー絵文字を表示する

絵文字は、ID2D1HwndRenderTargetインターフェイスのDrawText()メソッドで、 Unicode文字列として描画することができます。普通に描画するだけだと、通常の文字と同じ単色で描画されます。 そこで、ID2D1HwndRenderTargetインターフェイスのDrawText()メソッドの第6引数に、 D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONTを設定します。すると、 通常文字は単色で描画されますが、絵文字はカラーで描画されるようになります。

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


// define
#ifndef D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT
#define D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT  ( 0x00000004 )
#endif


// 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
);



/*
	UTF32をUTF16に変換する
*/
std::wstring UTF32toUTF16
(
	ULONG qUnicode
)
{
	WCHAR waBuf[ 4 ] = { 0 };

	if ( 0x10000 > qUnicode ) {

		// 0x10000未満
		waBuf[ 0 ] = (WCHAR)qUnicode;
	}
	else {

		// 0x10000以上(サロゲートペアにする)
		waBuf[ 0 ] = (WCHAR)( ( qUnicode - 0x10000 ) / 0x400 + 0xd800 );
		waBuf[ 1 ] = (WCHAR)( ( qUnicode - 0x10000 ) % 0x400 + 0xdc00 );
	}

	// 処理結果を返す
	return( waBuf );
}



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

// 絵文字文字列
std::wstring strEmoji;



/*
	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;

			// 絵文字文字列の生成
			for ( ULONG qUnicode = 0x1f300; qUnicode <= 0x1f5ff; qUnicode++ ) {
				strEmoji += UTF32toUTF16( qUnicode );
			}


			/*
				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
	//--------------------------------------------
		{
			// ターゲットサイズの取得
			D2D1_SIZE_F oTargetSize = pRenderTarget->GetSize();

			// 描画開始
			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
						);
				}


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


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

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

				// テキストフォーマットの破棄
				pTextFormat->Release();

				// ブラシの破棄
				pBrush->Release();
			}

			// 描画終了
			pRenderTarget->EndDraw();
		}
		return( FALSE );
	}

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



実行結果







わびさびサンプルソース

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