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

単位を変更して描画する

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

ここでは、メートルやインチ単位の長さを指定して描画や印刷を行う方法を紹介します。

PageUnitプロパティを指定する方法

一番簡単な方法は、描画先のGraphicsオブジェクトのPageUnitプロパティを変更してから描画するという方法でしょう。

PageUnitプロパティはページ座標で使用する長さの単位を指定するためのプロパティで、ページ変換(ページ座標からデバイス座標への変換)で使用されます。GDI+の座標系について詳しくは、MSDNの「座標系の種類」をご覧ください。

PageUnitプロパティにはGraphicsUnit列挙体の値を指定できます。GraphicsUnit列挙体には、以下のようなメンバーがあります(MSDNからの引用です)。つまり、これらの単位を指定できます。

メンバ 説明
Display 表示デバイスの長さの単位を指定します。通常、ビデオ ディスプレイにはピクセル、プリンタには 1/100 インチを指定します。ただし、.NET Framework 1.1以前では、1/75インチを長さの単位に指定します。
Document ドキュメント単位(1/300インチ)を長さの単位に指定します。
Inch インチを長さの単位に指定します。
Millimeter ミリメートルを長さの単位に指定します。
Pixel デバイスピクセルを長さの単位に指定します。
Point プリンタポイント(1/72インチ)を長さの単位に指定します。
World ワールド単位を長さの単位に指定します。

PageUnitプロパティを使った例を以下に示します。このコードはフォームクラスに書かれているものとし、フォームに太さ0.1インチで4X2インチの長方形を描画しています。

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

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    MyBase.OnPaint(e)

    'Penを用意する
    Dim redPen As New Pen(Color.Red, 0.1F)

    'インチ単位にする
    e.Graphics.PageUnit = GraphicsUnit.Inch
    '太さ0.1インチで4X2インチの長方形を描画
    e.Graphics.DrawRectangle(redPen, 0.2F, 0.4F, 4, 2)

    'Penを破棄
    redPen.Dispose()
End Sub
C#
コードを隠すコードを選択
//using System.Drawing;

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint (e);

    //Penを用意する
    Pen redPen = new Pen(Color.Red, 0.1f);
    
    //インチ単位にする
    e.Graphics.PageUnit = GraphicsUnit.Inch;
    //太さ0.1インチで4X2インチの長方形を描画
    e.Graphics.DrawRectangle(redPen, 0.2f, 0.4f, 4, 2);
    
    //Penを破棄
    redPen.Dispose();
}

DPIから計算する方法

もし自分で描画する画面のdpi(dots per inch)を取得して、それを元にピクセル単位の長さを計算できるのであれば、そうすることもできます。dpiはその名の通り、1インチ内のピクセル数を表し、水平方向および垂直方向のdpiは、GraphicsクラスのDpiXとDpiYプロパティで取得することができます。

補足:「HOWTO: How to Make an Application Display Real Units of Measurement」では、GetDeviceCaps関数を使ってdpiを取得する方法が紹介されています。ちなみにDpiXプロパティはGdipGetDpiX関数を使っているようです。

このような方法により、先ほどと同じようにインチ単位で描画する例を示します。

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

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    MyBase.OnPaint(e)

    'Penを用意する
    Dim redPen As New Pen(Color.Red, 0.1F * e.Graphics.DpiX)

    '太さ0.1インチで4X2インチの長方形を描画
    e.Graphics.DrawRectangle(redPen, _
        0.2F * e.Graphics.DpiX, 0.4F * e.Graphics.DpiX, _
        4 * e.Graphics.DpiX, 2 * e.Graphics.DpiX)

    'Penを破棄
    redPen.Dispose()
End Sub
C#
コードを隠すコードを選択
//using System.Drawing;

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint (e);
    
    //Penを用意する
    Pen redPen = new Pen(Color.Red, 0.1f * e.Graphics.DpiX);

    //太さ0.1インチで4X2インチの長方形を描画
    e.Graphics.DrawRectangle(redPen,
        0.2f * e.Graphics.DpiX, 0.4f * e.Graphics.DpiX,
        4 * e.Graphics.DpiX, 2 * e.Graphics.DpiX);

    //Penを破棄
    redPen.Dispose();
}

このように長さをいちいち計算するのが面倒であれば、ScaleTransformメソッドにより、ワールド変換を使って解決することもできます。ワールド変換については、「ワールド変換により画像を平行移動、拡大、縮小、回転して表示する」で説明しています。

また、水平方向と垂直方向のdpiが同じであれば、PageScaleプロパティにより、ページ変換で行うこともできます。

ScaleTransformメソッドを使った例を以下に示します。

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

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    MyBase.OnPaint(e)

    'Penを用意する
    Dim redPen As New Pen(Color.Red, 0.1F)

    'インチ単位にする
    e.Graphics.ScaleTransform(e.Graphics.DpiX, e.Graphics.DpiY)
    '太さ0.1インチで4X2インチの長方形を描画
    e.Graphics.DrawRectangle(redPen, 0.2F, 0.4F, 4, 2)

    'Penを破棄
    redPen.Dispose()
End Sub
C#
コードを隠すコードを選択
//using System.Drawing;

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint (e);
    
    //Penを用意する
    Pen redPen = new Pen(Color.Red, 0.1f);

    //インチ単位にする
    e.Graphics.ScaleTransform(e.Graphics.DpiX, e.Graphics.DpiY);
    //太さ0.1インチで4X2インチの長方形を描画
    e.Graphics.DrawRectangle(redPen, 0.2f, 0.4f, 4, 2);

    //Penを破棄
    redPen.Dispose();
}

もちろんPageUnitプロパティが使えるならばこのような方法を使う必要はないと思いますが、PageUnitプロパティで指定できない単位を使いたい場合はこのような方法が必要になるでしょう。

PageScaleプロパティを指定する方法

最後に蛇足ですが、寸単位で描画する例を示します。ここでは、DpiXとDpiYが同じものとし、PageScaleプロパティを使っています。

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

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    MyBase.OnPaint(e)

    'Penを用意する
    Dim redPen As New Pen(Color.Red, 0.1F)

    '寸単位にする(1インチを0.8382寸とする)
    e.Graphics.PageScale = e.Graphics.DpiX / 0.8382F
    '太さ0.1寸で4X2寸の長方形を描画
    e.Graphics.DrawRectangle(redPen, 0.2F, 0.4F, 4, 2)

    'Penを破棄
    redPen.Dispose()
End Sub
C#
コードを隠すコードを選択
//using System.Drawing;

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint (e);
    
    //Penを用意する
    Pen redPen = new Pen(Color.Red, 0.1f);

    //寸単位にする(1インチを0.8382寸とする)
    e.Graphics.PageScale = e.Graphics.DpiX / 0.8382f;
    //太さ0.1寸で4X2寸の長方形を描画
    e.Graphics.DrawRectangle(redPen, 0.2f, 0.4f, 4, 2);

    //Penを破棄
    redPen.Dispose();
}
  • 履歴:
  • 2013/7/16 .NET Framework 2.0以降のGraphicsUnit.DisplayのMSDNでの説明を追記。

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

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