Graphicsオブジェクトのコンストラクタはpublicではないため、newでは作成できません。よって他の方法によって取得する必要があります。
Controlの派生クラスに描画するときには、そのPaintイベントのPaintEventArgsから取得できます。
private void Form1_Paint( object sender, PaintEventArgs e ) { Graphics g = e.Graphics; g.DrawLine( Pens.Black, 0, 0, 10, 20 ); }
Controlの派生クラスでPaintイベント以外で描画するには、そのクラスのCreateGraphics()を呼び出します。
Graphics g = this.CreateGraphics(); g.DrawLine( Pens.Black, 0, 0, 10, 20 );
特定のImageに描画するならば、Graphics.FromImage()からそれを操作できるGraphicsを取得できます。
Image image = Image.FromFile("sample.bmp"); Graphics g = Graphics.FromImage(image); g.DrawLine(Pens.Black, 0, 0, 10, 20);Graphics.FromImage メソッド (Image) (System.Drawing) | MSDN
Color構造体のプロパティはすべて読み取り専用のため、色を変更するときにはオブジェクトを作成し直します。
HSB (HSV) の値を取得するメソッドは用意されていますが、設定する方法は提供されていないため、その必要があるときには独自に実装します。Is there a built-in C#/.NET System API for HSV to RGB? - Stack Overflow
メソッド | 作成基準 | 備考 |
---|---|---|
FromArgb(int argb) | 32bitのARGB値から | argbは、AARRGGBBの順 |
FromArgb(int alpha, Color baseColor) | 8bitのアルファ値と、基となるColor構造体から | |
FromArgb(int red, int green, int blue) | 8bitの赤、緑、青から | |
FromArgb(int alpha, int red, int green, int blue) | 8bitのアルファ値、赤、緑、青から | 引数はすべて0~255の範囲 |
Color red = Color.FromArgb(255, 0, 0);
メソッド | 作成基準 |
---|---|
FromKnownColor(KnownColor color) | KnownColor列挙型の要素から |
FromName(string name) | 定義済みの色の名前から (有効な名前は、KnownColor列挙型の要素の名前と同じ) |
public static Color FromKnownColor( KnownColor color )Color.FromKnownColor メソッド (KnownColor) (System.Drawing) | MSDN
public static Color FromName( string name )Color.FromName メソッド (String) (System.Drawing) | MSDN
プロパティ | 対象 |
---|---|
ActiveBorder | アクティブなウィンドウ境界線 |
︙ | |
Highlight | 選択された項目の背景色 |
︙ | |
Window | クライアント領域の背景色 |
WindowText | クライアント領域のテキストの色 |
すべて静的なプロパティで、SystemColors.WindowText
のように取得できます。
Color color = Color.AliceBlue; // 定義済みの色 string name = color.Name; // "AliceBlue" byte red = color.R; // 240 int argbVal = color.ToArgb(); // -984833 string argb = Convert.ToString(argbVal, 16); // "fff0f8ff"
RGB値を指定して作成した色は、そのコードが名前となります。
Color color = Color.FromArgb(0x1, 0x2, 0x3); string name = color.Name; // "ff010203" int argbVal = color.ToArgb(); string argb = Convert.ToString(argbVal, 16); // "ff010203" string rgb = Convert.ToString(argbVal, 16).Remove(0, 2); // "010203"
Pen p1 = new Pen( Color.Black ); Pen p2 = Pens.Black; Pen p3 = SystemPens.WindowText;
Pen(Brush brush) Pen(Brush brush, float width) Pen(Color color) Pen(Color color, float width)Pen コンストラクター (System.Drawing)
widthを省略すると既定値の1.0となり、0.0と指定するとPageUnitやPageScaleに無関係に1ピクセル幅となります。
newで作成したリソースはDispose()を呼ぶか、usingステートメントを用いて破棄します。 Pen.Dispose Method (System.Drawing) | MSDN c# - What happens if I don't call Dispose on the pen object? - Stack Overflow
using (Pen pen = new Pen(Color.Gray, 0.0f))
{
//
}
一方でPensやSystemPensクラスから返されるリソースは、プロセスの終了時にGdipクラスによって破棄されるため、呼び出し側では破棄しません。Black - Pens.cs WindowText - SystemPens.cs ClearThreadData - Gdiplus.cs
public SolidBrush(
Color color //
)
SolidBrush コンストラクター (Color) (System.Drawing) | MSDN
public TextureBrush(
Image bitmap //
)
TextureBrush コンストラクター (Image) (System.Drawing) | MSDN
public HatchBrush( HatchStyle hatchstyle, // Color foreColor // )HatchBrush コンストラクター (HatchStyle, Color) (System.Drawing.Drawing2D) | MSDN
public LinearGradientBrush( Rectangle rect, // Color color1, // Color color2, // LinearGradientMode linearGradientMode // )LinearGradientBrush コンストラクター (Rectangle, Color, Color, LinearGradientMode) (System.Drawing.Drawing2D) | MSDN
public PathGradientBrush( Point[] points, // WrapMode wrapMode // )
Brush b1 = new SolidBrush( Color.White ); Brush b2 = Brushes.White; Brush b3 = SystemBrushes.Window;
型 | プロパティ | 内容 |
---|---|---|
int | X | 左上隅のx座標 |
int | Y | 左上隅のy座標 |
int | Width | 幅 |
int | Height | 高さ |
Point | Location | 左上隅の座標。getではnew Point(X, Y) が返される Location - Rectangle.cs |
Size | Size | サイズ。getではnew Size(Width, Height) が返される Size - Rectangle.cs |
int | Left | 左上隅のx座標。Xから取得するのと同じ Left - Rectangle.cs |
int | Right | 右上隅のx座標。X+Width |
メソッド | 機能 |
---|---|
Inflate(Size) | このRectangleの大きさを、変更できる。中心を維持しながら、XとY方向それぞれに拡大される |
Offset(Point) | このRectangleの位置を、変更できる |
Contains(Point) | 指定位置が、このRectangleに含まれているか判定できる |
Contains(Rectangle) | 指定のRectangleの全体が、このRectangleに含まれているか判定できる |
Union(Rectangle, Rectangle) | |
Rectangle rec = new Rectangle(0, 0, 100, 200); // {X = 0 Y = 0 Width = 100 Height = 200} rec.Inflate(100, 100); // {X = -100 Y = -100 Width = 300 Height = 400} rec.Offset(10, 10); // {X = -90 Y = -90 Width = 300 Height = 400}
2つのRectangleが結合 (union) したRectangleを取得できます。
public static System.Drawing.Rectangle Union ( System.Drawing.Rectangle a, System.Drawing.Rectangle b );Rectangle.Union(Rectangle, Rectangle) メソッド (System.Drawing) | Microsoft Docs
Rectangle r1 = new Rectangle(10, 0, 10, 30); Rectangle r2 = new Rectangle(0, 10, 30, 10); Rectangle r3 = Rectangle.Union(r1, r2); // "{X=0,Y=0,Width=30,Height=30}" Rectangle r4 = Rectangle.Union(r1, Rectangle.Empty); // "{X=0,Y=0,Width=20,Height=30}"
メソッド | 描画される図形 |
---|---|
DrawArc() | 円弧 |
DrawBezier() | ベジェ曲線 (ベジエ スプライン (Bézier spline)) |
DrawBeziers() | ベジェ曲線。一連の (ベジエ スプライン (Bézier spline)) |
DrawClosedCurve() | カーディナル スプライン。閉じた (Cardinal spline) |
DrawCurve() | カーディナル スプライン。配列を通過する (Cardinal spline) |
DrawEllipse() | 楕円 |
DrawIcon() | アイコン (Icon)。スケーリングされた |
DrawIconUnstretched() | アイコン (Icon)。スケーリングされていない |
DrawImage() | イメージ (Image)。スケーリングされた |
DrawImageUnscaled() | イメージ (Image)。スケーリングされていない。つまり元のサイズ |
DrawImageUnscaledAndClipped() | イメージ (Image)。スケーリングされず切り取り (クリッピング) された |
DrawLine() | 直線。2つの点を結ぶ |
DrawLines() | 線分。配列を接続する |
DrawPie() | 扇形 |
DrawPolygon() | 多角形。配列で定義された |
DrawRectangle() | 四角形 |
DrawRectangles() | 四角形。一連の |
DrawString() | 文字列 |
DrawPath() | GraphicsPathの図形 |
メソッド | 描画される図形 |
---|---|
FillClosedCurve() | カーディナル スプライン。閉じた |
FillEllipse() | 楕円 |
FillPie() | 扇形 |
FillPolygon() | 多角形 |
FillRectangle() | 四角形 |
FillRectangles() | 四角形。一連の |
FillRegion() | 四角形とパスから成る図形 |
FillPath() | GraphicsPathの図形 |
1本の直線はDrawLine()で、連続した直線はDrawLines()で描画します。また終了点を開始点に接続するならば、DrawPolygon()を用います。
Graphics g = e.Graphics; Pen pen1 = new Pen(ForeColor); g.DrawLine(pen1, 10, 0, 20, 30); Point[] points = { new Point(10,0), new Point(20,30), new Point(0,10), }; Pen pen2 = new Pen(ForeColor); g.DrawLines(pen2, points);
public void DrawLine( Pen pen, int x1, int y1, int x2, int y2 )Graphics.DrawLine メソッド (Pen, Int32, Int32, Int32, Int32) (System.Drawing) | MSDN
public void DrawLines( Pen pen, Point[] points )Graphics.DrawLines メソッド (Pen, Point[]) (System.Drawing) | MSDN
public void DrawPolygon( Pen pen, Point[] points )Graphics.DrawPolygon メソッド (Pen, Point[]) (System.Drawing) | MSDN
public void DrawEllipse( Pen pen, int x, int y, int width, int height )
public void DrawEllipse( Pen pen, Rectangle rect )Graphics.DrawEllipse メソッド (System.Drawing) - desc | MSDN
たとえばフォームのクライアント領域に内接する円を描くならば、次のようにします。
Graphics g = e.Graphics; g.DrawEllipse(Pens.Red, form.ClientRectangle);
public void DrawRectangle( Pen pen, int x, // 描画する四角形の左上のx座標 int y, // 描画する四角形の左上のy座標 int width, // 描画する四角形の幅 int height // 描画する四角形の高さ )Graphics.DrawRectangle メソッド (Pen, Int32, Int32, Int32, Int32) (System.Drawing) | MSDN
public void FillRectangle( Brush brush, int x, // 塗りつぶす四角形の左上のx座標 int y, // 塗りつぶす四角形の左上のy座標 int width, // 塗りつぶす四角形の幅 int height // 塗りつぶす四角形の高さ )Graphics.FillRectangle メソッド (Brush, Int32, Int32, Int32, Int32) (System.Drawing) | MSDN
DrawRectangle()ではペンの幅が影響するため、描画される位置や幅がFillRectangle()と異なることがあります。
Graphics g = e.Graphics; g.ScaleTransform(10.0f, 10.0f); g.FillRectangle(Brushes.Black, 10, 10, 1, 1); // 下図の1列目に描画 g.FillRectangle(Brushes.Black, 10, 20, 2, 2); g.DrawRectangle(Pens.Black, 20, 10, 1, 1); // 下図の2列目に描画 g.DrawRectangle(Pens.Black, 20, 20, 2, 2); using (Pen pen = new Pen(Color.Black, 0.0f)) { g.DrawRectangle(pen, 30, 10, 1, 1); // 下図の3列目に描画 g.DrawRectangle(pen, 30, 20, 2, 2); }
出力例
イメージを描画できます。
メソッド | 描画範囲と形状 |
---|---|
DrawImage(Image, Point) | 全体が、元のサイズで描画 |
DrawImage(Image, Point[]) | 全体が、指定の3点を頂点とする平行四辺形の形状にスケーリングされて描画 |
DrawImage(Image, Rectangle) | 全体が、指定の四角形の形状にスケーリングされて描画 |
DrawImage(Image, Rectangle, Rectangle, GraphicsUnit) | 指定部分が、指定の四角形の形状にスケーリングされて描画 |
public void DrawImage( Image image, Rectangle destRect, int srcX, int srcY, int srcWidth, int srcHeight, GraphicsUnit srcUnit, // 切り取り部を定義するための単位 ImageAttributes imageAttrs, // 変色とガンマ情報 Graphics.DrawImageAbort callback, // 描画時に呼び出されるコールバック IntPtr callbackData // このメソッドの停止を決定するためのコールバックの追加データ )Graphics.DrawImage メソッド (Image, Rectangle, Int32, Int32, Int32, Int32, GraphicsUnit, ImageAttributes, Graphics.DrawImageAbort, IntPtr) (System.Drawing) | MSDN
imageに問題があると、このメソッドの呼び出しで「コード -1073740940 (0xc0000374) で終了しました。」としてアプリケーションがクラッシュします。
画像の一部の切り取り (クリッピング) だけをするならば、スケーリングを伴わないDrawImageUnscaledAndClipped()を用います。
public void DrawImageUnscaledAndClipped( Image image, Rectangle rect )Graphics.DrawImageUnscaledAndClipped メソッド (Image, Rectangle) (System.Drawing) | MSDN
点を描画するメソッドは用意されていないため、1ピクセル幅の四角形を描画することで代用します。c# - Draw a single pixel on Windows Forms - Stack Overflow
g.FillRectangle(Brushes.Black, x, y, 1, 1);
またはBitmapを作成し、それのSetPixel()でピクセルの色を指定することで実現します。
Bitmap bitmap = new Bitmap(100, 100); bitmap.SetPixel(10, 10, Color.Red); Graphics g = e.Graphics; g.DrawImage(bitmap, 0, 0);
public void DrawString ( string s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.RectangleF layoutRectangle, System.Drawing.StringFormat format );DrawString(String, Font, Brush, RectangleF, StringFormat) - Graphics.DrawString Method (System.Drawing) | Microsoft Docs
互換性が問題とならないならば、GDIを用いるTextRenderer.DrawText()を使用します。c# - Graphics.DrawString vs TextRenderer.DrawText?Which can Deliver Better Quality - Stack Overflow
public static void DrawText ( System.Drawing.IDeviceContext dc, string text, System.Drawing.Font font, System.Drawing.Rectangle bounds, System.Drawing.Color foreColor, System.Windows.Forms.TextFormatFlags flags );DrawText(IDeviceContext, String, Font, Rectangle, Color, TextFormatFlags) - TextRenderer.DrawText Method (System.Windows.Forms) | Microsoft Docs
TextFormatFlags flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter; TextRenderer.DrawText(e.Graphics, text, font, bounds, foreColor, flags);
public System.Drawing.SizeF MeasureString (
string text,
System.Drawing.Font font,
int width, // 文字列の最大幅
System.Drawing.StringFormat format
);
MeasureString(String, Font, Int32, StringFormat) - Graphics.MeasureString メソッド (System.Drawing) | Microsoft Docs
string text = "SAMPLE"; int maxWidth = 100; StringFormat stringFormat = new StringFormat(StringFormatFlags.NoClip); SizeF size = e.Graphics.MeasureString( text, this.Font, maxWidth, stringFormat);
TextRenderer.MeasureText()でも取得できます。
public static System.Drawing.Size MeasureText (
string text,
System.Drawing.Font font,
System.Drawing.Size proposedSize, // 最大サイズ
System.Windows.Forms.TextFormatFlags flags
);
MeasureText(String, Font, Size, TextFormatFlags) - TextRenderer.MeasureText メソッド (System.Windows.Forms) | Microsoft Docs
string text = "SAMPLE"; Size proposedSize = new Size(100, 50); Size size = TextRenderer.MeasureText( text, this.Font, proposedSize, TextFormatFlags.Default);
public void TranslateTransform( float dx, // x軸方向の移動量 float dy // y軸方向の移動量 )Graphics.TranslateTransform メソッド (Single, Single) (System.Drawing) | MSDN
public void ScaleTransform( float sx, // x軸方向の拡大率 float sy // y軸方向の拡大率 )Graphics.ScaleTransform メソッド (Single, Single) (System.Drawing) | MSDN
拡大率を負数とすることで、軸を反転できます。たとえばsyを-1.0とするとy軸の正の方向が上向きとなり、グラフの描画に便利です。ただし軸を反転させるだけではy軸の正の領域が描画範囲から外れるため、必要ならばTranslateTransform()でy軸方向に移動させます。
スケールを変更すると直線などの幅にも影響するため、それが期待するものでなければペンの幅を0.0とします。
public void RotateTransform(
float angle // 回転角度
)
Graphics.RotateTransform メソッド (Single) (System.Drawing) | MSDN
Imageを継承したクラスを90度単位で回転させるならば、RotateFlip()で可能です。
たとえばフォーム左下が(-1.0,-1.0)、右上が(1.0,1.0)で、中央が(0,0)となるように座標を変換するには、次のようにします。
float width = 2.0f; float height = -2.0f; Graphics g = e.Graphics; g.ScaleTransform(form.ClientSize.Width / width, form.ClientSize.Height / height); g.TranslateTransform(width / 2.0f, height / 2.0f); // フォームの中央が(0,0)となるように移動 using (Pen pen = new Pen(Color.Black, 0.0f)) { g.DrawLine(pen, -1.0f, 0.0f, 1.0f, 0.0f); // x軸の描画 g.DrawLine(pen, 0.0f, -1.0f, 0.0f, 1.0f); // y軸の描画 }
前述の、Graphics.TranslateTransform()メソッドなどで変換します。
GraphicsPathに直線セグメントなどを追加し、それに変換行列を乗じます。そしてGraphics.DrawPath()などで描画します。ローカル変換 - グローバル変換とローカル変換 | MSDN
GraphicsPath graphicsPath = new GraphicsPath(); graphicsPath.AddLine(10, 20, 10, 40); Matrix matrix = new Matrix(); matrix.Scale(2.0f, 1.0f); matrix.Translate(0.0f, -1.0f); graphicsPath.Transform(matrix); Graphics g = e.Graphics; Pen pen = new Pen(ForeColor); g.DrawPath(pen, graphicsPath);
GraphicsのSmoothingModeプロパティにAntiAliasまたはHighQualityを指定することで、以降描画する画像にアンチエイリアシングが適用されます。
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
列挙子 | 数値 | 意味 |
---|---|---|
Invalid | -1 | 無効なモード |
Default | 0 | アンチエイリアシングなし (いずれでも同じ効果) |
HighSpeed | 1 | |
None | 3 | |
HighQuality | 2 | アンチエイリアシングあり (いずれでも同じ効果) |
AntiAlias | 4 |
次の3つの解決法があります。
DoubleBufferedプロパティがprotectedのため、それを継承したクラスを作成した上でDoubleBufferedをtrueとします。
this.DoubleBuffered = true;
ControlのSetStyle()も同様にprotectedのため、継承したクラスを作成した上で設定します。.NET TIPS:背景の描画を禁止して再描画時のちらつきをなくすには? - @IT 遠藤孝信 (2004/08/19)
this.SetStyle(ControlStyles.Opaque, true);
次の2つの解決法があります。