CreateFont 関数で64×64ドットの大きい論理フォントを作成して「九九一覧」を描画します。
- SetBkMode 関数で背景モードを TRANSPARENT 定数で透過表現。
- CreateFont 関数で64×64ドットの大きい論理フォントを作成。
- SelectObject 関数で新しい論理フォントに切り替え。
- funcDrawKuku 関数で九九一覧を描画。
- SelectObject 関数で GetStockObject 関数の SYSTEM_FONT 定数に切り替え。
- DeleteObject 関数で作成した論理フォントを削除。
プロトタイプ宣言
HFONT CreateFont( int nHeight, // フォントの高さ int nWidth, // 平均文字幅 int nEscapement, // 文字送り方向の角度 int nOrientation, // ベースラインの角度 int fnWeight, // フォントの太さ DWORD fdwItalic, // 斜体にするかどうか DWORD fdwUnderline, // 下線を付けるかどうか DWORD fdwStrikeOut, // 取り消し線を付けるかどうか DWORD fdwCharSet, // 文字セットの識別子 DWORD fdwOutputPrecision, // 出力精度 DWORD fdwClipPrecision, // クリッピング精度 DWORD fdwQuality, // 出力品質 DWORD fdwPitchAndFamily, // ピッチとファミリ LPCTSTR lpszFace // フォント名 );
上記の CreateFont 関数は引数が14個もあって使いづらいので便利なマクロ関数を2つ紹介します。1つ目は apiCreateFont マクロ関数でフォントの文字幅、高さ、太さ、斜体、下線、取り消し線、フォント名の7つの引数を取ります。このマクロ関数で一通りのフォントを作成できますが、たまに文字セットを SYMBOL_CHARSET を使いたくなる場合があります。そこで文字セットを引数で指定できる apiCreateFontEx マクロ関数も紹介します。こちらはフォントの文字幅、高さ、太さ、斜体、下線、取り消し線、文字セット、フォント名の8つの引数を取ります。このように便利なマクロ関数を独自に用意しておくとプログラミングが楽になります。その他にも break 付きの CASE、DEFAULT も用意すると switch 文のときに毎回 break 命令を記述しなくても良くなります。こちらも便利ですからヘッダ部に定義します。
サンプル
下記に「九九一覧」を描画する funcDrawKuku 関数とプロシージャ関数を載せます。
なお WinMain 関数の基本部のウインドウ・クラスの登録、ウインドウの作成、メッセージ・ループは省略してます。
ご自身で記述して下さい。
//============================================================================== // 九九一覧を描こう //============================================================================== #include <tchar.h> #include <Windows.h> //------------------------------------------------ // break付きのキーワード //------------------------------------------------ #define CASE break;case #define DEFAULT break;default //------------------------------------------------ // このファイルで使用する定数 //------------------------------------------------ #define CHP_WIDTH (64) // タイルの横サイズ #define CHP_HEIGHT (64) // タイルの縦サイズ //------------------------------------------------ // このファイルで使用する関数 //------------------------------------------------ #define apiCreateFont(x,y,n,i,u,v,s) apiCreateFontEx(x,y,n,i,u,v,SHIFTJIS_CHARSET,s) #define apiCreateFontEx(x,y,n,i,u,v,c,s) CreateFont(y,x,0,0,n,i,u,v,c,\ OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,\ (FIXED_PITCH|FF_DONTCARE),s) //------------------------------------------------ // 九九一覧の描画 //------------------------------------------------ static VOID funcDrawKuku( HDC hDC ) { TCHAR szBuff[ 10 ]; RECT rc; for ( INT cy = 1 ; cy <= 9 ; cy++ ){ for ( INT cx = 1 ; cx <= 9 ; cx++ ){ wsprintf( szBuff, TEXT("%ld"), (cx * cy) ); SetRect( &rc, 0, 0, CHP_WIDTH, CHP_HEIGHT ); // 影文字 OffsetRect( &rc, ((cx - 1) * CHP_WIDTH), ((cy - 1) * CHP_HEIGHT) ); SetTextColor( hDC, RGB(0x00,0x00,0x00) ); DrawText( hDC, szBuff, -1, &rc, (DT_CENTER | DT_VCENTER | DT_SINGLELINE) ); // 薄い赤色 OffsetRect( &rc, -1, -1 ); SetTextColor( hDC, RGB(0xFF,0xCC,0xCC) ); DrawText( hDC, szBuff, -1, &rc, (DT_CENTER | DT_VCENTER | DT_SINGLELINE) ); // 濃い赤色 OffsetRect( &rc, -2, -2 ); SetTextColor( hDC, RGB(0xFF,0x00,0x00) ); DrawText( hDC, szBuff, -1, &rc, (DT_CENTER | DT_VCENTER | DT_SINGLELINE) ); } } } //------------------------------------------------ // ウインドウ・プロシージャの関数 //------------------------------------------------ extern LRESULT CALLBACK mainWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch ( uMsg ){ CASE WM_CREATE: CASE WM_CLOSE: DestroyWindow( hWnd ); CASE WM_DESTROY: PostQuitMessage( 0 ); CASE WM_PAINT: { PAINTSTRUCT ps; HDC hDC; hDC = BeginPaint( hWnd, &ps ); SetBkMode( hDC, TRANSPARENT ); SelectObject( hDC, apiCreateFont(0,48,FW_NORMAL,0,0,0,TEXT("HG明朝E")) ); funcDrawKuku( hDC ); DeleteObject( SelectObject(hDC,GetStockObject(SYSTEM_FONT)) ); EndPaint( hWnd, &ps ); } DEFAULT:return DefWindowProc( hWnd, uMsg, wParam, lParam ); } return 0; }
解説
//------------------------------------------------ // 九九一覧の描画 //------------------------------------------------ static VOID funcDrawKuku( HDC hDC ) { TCHAR szBuff[ 10 ]; RECT rc; for ( INT cy = 1 ; cy <= 9 ; cy++ ){ for ( INT cx = 1 ; cx <= 9 ; cx++ ){ wsprintf( szBuff, TEXT("%ld"), (cx * cy) ); SetRect( &rc, 0, 0, CHP_WIDTH, CHP_HEIGHT ); // 影文字 OffsetRect( &rc, ((cx - 1) * CHP_WIDTH), ((cy - 1) * CHP_HEIGHT) ); SetTextColor( hDC, RGB(0x00,0x00,0x00) ); DrawText( hDC, szBuff, -1, &rc, (DT_CENTER | DT_VCENTER | DT_SINGLELINE) ); // 薄い赤色 OffsetRect( &rc, -1, -1 ); SetTextColor( hDC, RGB(0xFF,0xCC,0xCC) ); DrawText( hDC, szBuff, -1, &rc, (DT_CENTER | DT_VCENTER | DT_SINGLELINE) ); // 濃い赤色 OffsetRect( &rc, -2, -2 ); SetTextColor( hDC, RGB(0xFF,0x00,0x00) ); DrawText( hDC, szBuff, -1, &rc, (DT_CENTER | DT_VCENTER | DT_SINGLELINE) ); } } }
九九一覧ですから横方向と縦方向の繰り返し文で9×9=81個の数値を描画します。
for ( INT cy = 1 ; cy <= 9 ; cy++ ){ for ( INT cx = 1 ; cx <= 9 ; cx++ ){ /* ここで九九一覧の1つの数値を描画 */ } }
1つの数値は cx、cy を掛け算して wsprintf 関数で数値から文字列に変換します。
TCHAR szBuff[ 10 ]; wsprintf( szBuff, TEXT("%ld"), (cx * cy) );
続いて DrawText 関数で64×64ドットの領域に数値を描くために RECT 構造体の rc にサイズをセットします。
RECT rc; SetRect( &rc, 0, 0, CHP_WIDTH, CHP_HEIGHT );
上記の rc に描画する場所の座標分だけ OffsetRect 関数でずらします。
cx は 1~9 の数値ですから 1 引いて 0~8 にした値に横方向のドット数(CHP_WIDTH=64)を掛けます。
cy も 1~9 の数値ですから 1 引いて 0~8 にした値に縦方向のドット数(CHP_HEIGHT=64)を掛けます。
その後に SetTextColor 関数で影色を指定してから DrawText 関数で描画します。
// 影文字 OffsetRect( &rc, ((cx - 1) * CHP_WIDTH), ((cy - 1) * CHP_HEIGHT) ); SetTextColor( hDC, RGB(0x00,0x00,0x00) ); DrawText( hDC, szBuff, -1, &rc, (DT_CENTER | DT_VCENTER | DT_SINGLELINE) );
続いて薄い赤色を描くために OffsetRect 関数で1ドット左上にずらします。
その後に SetTextColor 関数で薄い赤色を指定してから DrawText 関数で描画します。
// 薄い赤色 OffsetRect( &rc, -1, -1 ); SetTextColor( hDC, RGB(0xFF,0xCC,0xCC) ); DrawText( hDC, szBuff, -1, &rc, (DT_CENTER | DT_VCENTER | DT_SINGLELINE) );
続いて濃い赤色を描くために OffsetRect 関数で2ドット左上にずらします。
その後に SetTextColor 関数で濃い赤色を指定してから DrawText 関数で描画します。
// 濃い赤色 OffsetRect( &rc, -2, -2 ); SetTextColor( hDC, RGB(0xFF,0x00,0x00) ); DrawText( hDC, szBuff, -1, &rc, (DT_CENTER | DT_VCENTER | DT_SINGLELINE) );
上記のように影文字、薄い赤色、濃い赤色の順にドットをずらして同じ文字を3つ描くと実行結果のように少々カッコ良い「九九一覧」が描画できます。SetTextColor 関数で緑色系統、青色系統、紫色系統、桃色系統、橙色系統などに変更すると面白いでしょう。