GDI+で、文字列美容がの詳細矩形の取得には、MeasureCharacterRangesメソッドを利用します。 事前にSetMeasurableCharacterRangesメソッドで、計測したい文字位置と文字列サイズを指定しておきます。
#include <stdio.h> #include <tchar.h> #include <locale.h> #include <string> #include <vector> #include <windows.h> #include <wingdi.h> #include <gdiplus.h> // ライブラリ #pragma comment( lib, "gdiplus.lib" ) /* メインウインドウイベント処理 */ 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; // ウインドウを表示する ::ShowWindow( hWnd, SW_SHOW ); } break; case WM_DESTROY: //-------------------------------------------- // WM_DESTROY //-------------------------------------------- { // 終了する( 引数はそのまま終了コードとなります ) ::PostQuitMessage( 0 ); } break; case WM_PAINT: //-------------------------------------------- // WM_PAINT //-------------------------------------------- { PAINTSTRUCT tPaintStruct; // 描画開始 HDC hDC = ::BeginPaint( hWnd, &tPaintStruct ); { Gdiplus::Graphics oGraphics( hDC ); // ウインドウ矩形を取得 RECT tRect; ::GetClientRect( hWnd, &tRect ); /* GDI+による文字描画詳細矩形の取得 */ std::wstring strDrawString = L"おはよう。こんにちは、Hello!!"; { Gdiplus::Font oFont( L"MS ゴシック", 72 ); // 文字列描画矩形 Gdiplus::RectF oRectF( 0, 0, (Gdiplus::REAL)tRect.right, (Gdiplus::REAL)tRect.bottom ); // 文字列フォーマット Gdiplus::StringFormat oStringFormat; // 書き出し位置を左上へ oStringFormat.SetAlignment( Gdiplus::StringAlignmentNear ); oStringFormat.SetLineAlignment( Gdiplus::StringAlignmentNear ); /* 計測するキャラクターレンジの生成(最大32文字まで) */ std::vector<Gdiplus::CharacterRange> vecCharcterRenges; for ( int nI = 0; nI < (int)strDrawString.size(); nI++ ) { // 計測したい文字位置と、文字列の長さを指定する vecCharcterRenges.push_back( Gdiplus::CharacterRange( nI, 1 ) ); } // 計測したいキャラクターレンジを設定 oStringFormat.SetMeasurableCharacterRanges( vecCharcterRenges.size(), &vecCharcterRenges[ 0 ] ); // 結果の数を取得 int nCount = oStringFormat.GetMeasurableCharacterRangeCount(); /* 文字列の描画 */ { // 描画用ブラシ(青) Gdiplus::SolidBrush oBrush( Gdiplus::Color( 0, 0, 255 ) ); // 文字列の描画 oGraphics.DrawString( strDrawString.c_str(), -1, &oFont, oRectF, &oStringFormat, &oBrush ); } // 計測結果取得用バッファ確保 Gdiplus::Region* pRegion = new Gdiplus::Region[ nCount ]; // 文字矩形の計測 oGraphics.MeasureCharacterRanges( strDrawString.c_str(), -1, &oFont, oRectF, &oStringFormat, nCount, pRegion ); /* 文字矩形の描画 */ { // 文字矩形描画用ペン(赤) Gdiplus::Pen oPen( Gdiplus::Color( 255, 0, 0 ), 1 ); // 文字矩形描画 for ( int nI = 0; nI < nCount; nI++ ) { Gdiplus::RectF oRectF; // 文字矩形を取得 ( pRegion + nI )->GetBounds( &oRectF, &oGraphics ); // 文字の矩形を描画 oGraphics.DrawRectangles( &oPen, &oRectF, 1 ); } } // 計測結果取得用バッファ破棄 delete [] pRegion; } } // 描画終了 ::EndPaint( hWnd, &tPaintStruct ); } return( FALSE ); } // デフォルト処理呼び出し return ::DefWindowProc( hWnd, uMsg, wParam, lParam ); } /* GDI+による文字描画詳細矩形の取得 */ int _tmain ( int argc , _TCHAR* argv[] ) { // 標準出力にユニコードを表示できるようにする setlocale( LC_ALL, "Japanese" ); WNDCLASSEX tWndClass; HINSTANCE hInstance; TCHAR* cpClassName; TCHAR* cpWindowName; TCHAR* cpMenu; HWND hWnd; MSG tMsg; // GDI+の開始 ULONG_PTR gdiplusToken; Gdiplus::GdiplusStartupInput gdiplusStartupInput; Gdiplus::GdiplusStartup( &gdiplusToken, &gdiplusStartupInput, 0 ); // アプリケーションインスタンス hInstance = ::GetModuleHandle( NULL ); // クラス名称 cpClassName = _T("MainWindowClass"); // メニュー cpMenu = MAKEINTRESOURCE( NULL ); // ウインドウ名称 cpWindowName = _T("GDI+による詳細文字描画矩形の取得"); // ウインドウクラスパラメータセット 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 ); } // GDI+の終了 Gdiplus::GdiplusShutdown( gdiplusToken ); // WM_QUITの終了コードを返却する return( tMsg.wParam ); }