DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

文字列を回転させて描画する

注意:画像の表示方法が分からないという方は、まず「コントロールやフォームに画像を表示する」をご覧ください。また、文字列を描画させる方法は「文字を書く」をご覧ください。

文字列を回転させて描画する方法としては、「プログラムで画像を動的に作成する」と「画像を回転、反転して表示する」(もしくは「画像を傾けて表示する」)を使って、文字列を書き込んだ画像を作成してその画像を回転して描画する方法と、「ワールド変換により画像を平行移動、拡大、縮小、回転して表示する」を使って文字列を描画する方法が考えられます。

新しく画像を作成して回転させる方法

まずは新しく画像を作成する方法を示します。

VB.NET
コードを隠すコードを選択
'Imports System.Drawing

'表示する文字列
Dim s As String = "DOBON.NET"

'描画先とするImageオブジェクトを作成する
Dim canvas As New Bitmap(PictureBox1.Width, PictureBox1.Height)
'ImageオブジェクトのGraphicsオブジェクトを作成する
Dim g As Graphics = Graphics.FromImage(canvas)

'大きさを調べるためのダミーのBitmapオブジェクトの作成
Dim img0 As New Bitmap(1, 1)

'imgのGraphicsオブジェクトを取得
Dim bg0 As Graphics = Graphics.FromImage(img0)

'使用するFontオブジェクトを作成
Dim fnt As New Font("Arial", 20)

'文字列を描画したときの大きさを計算する
Dim w As Integer = CInt(bg0.MeasureString(s, fnt).Width)
Dim h As Integer = CInt(fnt.GetHeight(bg0))

'Bitmapオブジェクトを作り直す
Dim img As New Bitmap(w, h)

'imgに文字列を描画する
Dim bg As Graphics = Graphics.FromImage(img)
bg.DrawString(s, fnt, Brushes.Black, 0, 0)

'45度で回転するための座標を計算
'ラジアン単位に変換
Dim d As Double = 45 / (180 / Math.PI)
'新しい座標位置を計算する
Dim x As Single = 30.0F
Dim y As Single = 10.0F
Dim x1 As Single = x + img.Width * CSng(Math.Cos(d))
Dim y1 As Single = y + img.Width * CSng(Math.Sin(d))
Dim x2 As Single = x - img.Height * CSng(Math.Sin(d))
Dim y2 As Single = y + img.Height * CSng(Math.Cos(d))
'PointF配列を作成
Dim destinationPoints As PointF() = _
    {New PointF(x, y), New PointF(x1, y1), New PointF(x2, y2)}

'画像を描画
g.DrawImage(img, destinationPoints)

'リソースを解放する
fnt.Dispose()
bg0.Dispose()
img0.Dispose()
img.Dispose()
bg.Dispose()
g.Dispose()

'PictureBox1に表示する
PictureBox1.Image = canvas
C#
コードを隠すコードを選択
//using System.Drawing;

//表示する文字列
string s = "DOBON.NET";

//描画先とするImageオブジェクトを作成する
Bitmap canvas = new Bitmap(PictureBox1.Width, PictureBox1.Height);
//ImageオブジェクトのGraphicsオブジェクトを作成する
Graphics g = Graphics.FromImage(canvas);

//大きさを調べるためのダミーのBitmapオブジェクトの作成
Bitmap img0 = new Bitmap(1, 1);

//imgのGraphicsオブジェクトを取得
Graphics bg0 = Graphics.FromImage(img0);

//使用するFontオブジェクトを作成
Font fnt = new Font("Arial", 20);

//文字列を描画したときの大きさを計算する
int w = (int) bg0.MeasureString(s, fnt).Width;
int h = (int) fnt.GetHeight(bg0);

//Bitmapオブジェクトを作り直す
Bitmap img = new Bitmap(w, h);

//imgに文字列を描画する
Graphics bg = Graphics.FromImage(img);
bg.DrawString(s, fnt, Brushes.Black, 0, 0);

//45度で回転するための座標を計算
//ラジアン単位に変換
double d = 45/(180/Math.PI);
//新しい座標位置を計算する
float x = 30F;
float y = 10F;
float x1 = x + img.Width * (float) Math.Cos(d);
float y1 = y + img.Width * (float) Math.Sin(d);
float x2 = x - img.Height * (float) Math.Sin(d);
float y2 = y + img.Height * (float) Math.Cos(d);
//PointF配列を作成
PointF[] destinationPoints = {new PointF(x, y),
                                    new PointF(x1, y1),
                                    new PointF(x2, y2)};

//画像を描画
g.DrawImage(img, destinationPoints);

//リソースを解放する
fnt.Dispose();
bg0.Dispose();
img0.Dispose();
img.Dispose();
bg.Dispose();
g.Dispose();

//PictureBox1に表示する
PictureBox1.Image = canvas;

ワールド変換を使った方法

上記の例では、文字列を描画するための画像の大きさを計算するためにダミーのBitmapオブジェクトを使っていたりして、かなり面倒なことになっています。

次にワールド変換を使った方法を示します。こちらの方がずっとすっきりしています。

VB.NET
コードを隠すコードを選択
'Imports System.Drawing

'表示する文字列
Dim s As String = "DOBON.NET"

'描画先とするImageオブジェクトを作成する
Dim canvas As New Bitmap(PictureBox1.Width, PictureBox1.Height)
'ImageオブジェクトのGraphicsオブジェクトを作成する
Dim g As Graphics = Graphics.FromImage(canvas)

'ワールド変換行列を45度回転する
g.RotateTransform(45.0F)

'使用するFontオブジェクトを作成
Dim fnt As New Font("Arial", 20)

'文字列を描画
g.DrawString(s, fnt, Brushes.Black, 30, 0)

'リソースを解放する
fnt.Dispose()
g.Dispose()

'PictureBox1に表示する
PictureBox1.Image = canvas
C#
コードを隠すコードを選択
//using System.Drawing;

//表示する文字列
string s = "DOBON.NET";

//PictureBox1のGraphicsオブジェクトを取得
Graphics g = PictureBox1.CreateGraphics();

//ワールド変換行列を45度回転する
g.RotateTransform(45F);

//使用するFontオブジェクトを作成
Font fnt = new Font("Arial", 20);

//文字列を描画
g.DrawString(s, fnt, Brushes.Black, 30, 0);

//リソースを解放する
fnt.Dispose();
g.Dispose();

//PictureBox1に表示する
PictureBox1.Image = canvas;

この方法の難点は描画される位置が分かりにくいということでしょう。つまり、文字列の描画位置も回転変換されるので、描画位置の座標を逆算する必要が出てくるケースがありえます。そのような時は次のようにTranslateTransformメソッドにより平行移動させると良いかもしれません。

VB.NET
コードを隠すコードを選択
'Imports System.Drawing

'表示する文字列
Dim s As String = "DOBON.NET"

'描画先とするImageオブジェクトを作成する
Dim canvas As New Bitmap(PictureBox1.Width, PictureBox1.Height)
'ImageオブジェクトのGraphicsオブジェクトを作成する
Dim g As Graphics = Graphics.FromImage(canvas)

'座標(30, 10)に描画するため、ワールド変換を平行移動
g.TranslateTransform(30, 10)
'ワールド変換行列を45度回転する
g.RotateTransform(45.0F)

'使用するFontオブジェクトを作成
Dim fnt As New Font("Arial", 20)

'文字列を(0, 0)に描画
g.DrawString(s, fnt, Brushes.Black, 0, 0)

'リソースを解放する
fnt.Dispose()
g.Dispose()

'PictureBox1に表示する
PictureBox1.Image = canvas
C#
コードを隠すコードを選択
//using System.Drawing;

//表示する文字列
string s = "DOBON.NET";

//描画先とするImageオブジェクトを作成する
Bitmap canvas = new Bitmap(PictureBox1.Width, PictureBox1.Height);
//ImageオブジェクトのGraphicsオブジェクトを作成する
Graphics g = Graphics.FromImage(canvas);

//座標(30, 10)に描画するため、ワールド変換を平行移動
g.TranslateTransform(30, 10);
//ワールド変換行列を45度回転する
g.RotateTransform(45F);

//使用するFontオブジェクトを作成
Font fnt = new Font("Arial", 20);

//文字列を(0, 0)に描画
g.DrawString(s, fnt, Brushes.Black, 0, 0);

//リソースを解放する
fnt.Dispose();
g.Dispose();

//PictureBox1に表示する
PictureBox1.Image = canvas;
  • 履歴:
  • 2012/8/4 表示する方法を、PictureBox.Imageプロパティを使った方法に変更。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。