絵文字は、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 ); }