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