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) | Microsoft Learn
このときImageがインデックス付きのピクセル形式 (indexed pixel format) である
だと、「インデックス付きのピクセル形式をもつイメージからグラフィックス オブジェクトを作成することはできません。」としてExceptionが投げられます。また
だと「メモリが不足しています。」としてOutOfMemoryExceptionが投げられます。
Bitmap bitmap = new Bitmap(1, 1, PixelFormat.Format16bppGrayScale);
Graphics g = Graphics.FromImage(bitmap); // OutOfMemoryException
型 | プロパティ | 内容 |
---|---|---|
Region | Clip | クリッピング領域を表すRegion |
RectangleF | ClipBounds | クリッピング領域に、外接する四角形を表すRectangleF |
RectangleF | VisibleClipBounds | 表示クリッピング領域に、外接する四角形を表すRectangleF |
SmoothingMode | SmoothingMode | レンダリングの品質 |
InterpolationMode | InterpolationMode | 補間モード |
補間モード (interpolation mode) によって、2つの終点の中間値の計算方法を指定できます。これは画像を拡大/縮小と回転させるときのアルゴリズムを決定し、画像の品質と処理速度に影響します。
画像を高品質に拡大/縮小するには?:.NET TIPS - @IT 遠藤孝信 (2003/05/02)Invalid | -1 | Equivalent to the Invalid element of the QualityMode enumeration. | |
Default | 0 | Specifies default mode. | |
Low | 1 | Specifies low quality interpolation. | |
High | 2 | Specifies high quality interpolation. | |
Bilinear | 3 | Specifies bilinear interpolation. | 事前フィルタは実行されない。元サイズの50%未満に縮小するのには適さない |
Bicubic | 4 | Specifies bicubic interpolation. | 事前フィルタは実行されない。元サイズの25%未満に縮小するのには適さない |
NearestNeighbor | 5 | Specifies nearest-neighbor interpolation. | |
HighQualityBilinear | 6 | pecifies high-quality, bilinear interpolation. | 高品質の縮小を確かとするため、事前フィルタが実行される |
HighQualityBicubic | 7 | Specifies high-quality, bicubic interpolation. | 高品質の縮小を確かとするため、事前フィルタが実行される。このモードでは、最高品質で変換された画像が生成される |
Bitmap bitmap = new Bitmap(100, 100);
Graphics g = Graphics.FromImage(bitmap);
InterpolationMode mode = g.InterpolationMode; // Bilinear
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);
Color構造体のプロパティはすべて読み取り専用のため、色を変更するときにはオブジェクトを作成し直します。
HSL (HLS) の値を取得するメソッドは用意されていますが、設定する方法は提供されていないため、その必要があるときには独自に実装します。Is there a built-in C#/.NET System API for HSV to RGB? - Stack Overflow
メソッド | 値 | 範囲 |
---|---|---|
GetHue() | 色相値 (hue value) | 0.0-360.0 |
GetSaturation() | 彩度値 (saturation value) | 0.0-1.0 |
GetBrightness() | 輝度値 (lightness value) | 0.0-1.0 |
型 | プロパティ | 内容 |
---|---|---|
byte | A | アルファ要素の値 |
byte | R | 赤要素の値 |
byte | G | 緑要素の値 |
byte | B | 青要素の値 |
Color | Empty | nullである色 |
bool | IsEmpty | trueならば、初期化されていない。Emptyである以外に、未定義の色もこの状態となる IsEmpty - Color.cs |
bool | IsKnownColor | trueならば、定義済みの色 |
bool | IsNamedColor | trueならば、名前付きの色 |
bool | IsSystemColor | trueならば、システム カラー |
メソッド | 作成基準 | 備考 |
---|---|---|
FromArgb(int argb) | 32bitのARGB値から | argbは、AARRGGBBの順 |
FromArgb(int alpha, Color baseColor) | 8bitのアルファ値と、基となるColor構造体から | |
FromArgb(int red, int green, int blue) | 8bitの赤、緑、青から | アルファ値は255 (不透明) となる |
FromArgb(int alpha, int red, int green, int blue) | 8bitのアルファ値、赤、緑、青から | 引数はすべて0~255の範囲 |
Color red = Color.FromArgb(255, 0, 0);
簡単にはColor.Redのようにすることで取得できます。これはnew Color(KnownColor.Red)
とすることと同じです。Red - Color.cs
メソッド | 作成基準 |
---|---|
FromKnownColor(KnownColor color) | KnownColor列挙型の要素から |
FromName(string name) | 定義済みの色の名前から (有効な名前は、KnownColor列挙型の要素の名前と同じ) |
public static Color FromKnownColor( KnownColor color )Color.FromKnownColor メソッド (KnownColor) (System.Drawing) | MSDN
colorの有効性が確認された上で、Color(color)コンストラクタで作成されたインスタンスが返されます。FromKnownColor - Color.cs
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"
Color c1 = Color.Empty; // Name=0, ARGB=(0, 0, 0, 0) Color c2 = Color.Transparent; // Name=Transparent, ARGB=(0, 255, 255, 255)
RGB値を指定して作成した色は、そのコードが名前となります。
Color color = Color.FromArgb(0x1, 0x2, 0x3); string name = color.Name; // "ff010203" int argbVal = color.ToArgb(); // -16711165 (0xff010203) string argb = Convert.ToString(argbVal, 16); // "ff010203" string rgb = Convert.ToString(argbVal, 16).Remove(0, 2); // "010203"
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ピクセル幅となります。
Pen p1 = new Pen( Color.Black ); Pen p2 = Pens.Black; Pen p3 = SystemPens.WindowText;
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
型 | プロパティ | 内容 |
---|---|---|
DashStyle | DashStyle | 破線のスタイル 破線を描く - .NET Tips (VB.NET,C#...) |
DashCap | DashCap | 破線の終点で使用するキャップスタイル |
PenAlignment | Alignment | 配置 |
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) - HatchBrush コンストラクター (System.Drawing.Drawing2D) | Microsoft Learn
public LinearGradientBrush( Rectangle rect, // Color color1, // Color color2, // LinearGradientMode linearGradientMode // 線形グラデーションの方向 )LinearGradientBrush(Rectangle, Color, Color, LinearGradientMode) - LinearGradientBrush コンストラクター (System.Drawing.Drawing2D) | Microsoft Learn
public PathGradientBrush( Point[] points, // WrapMode wrapMode // 塗りつぶしの並べ方 )PathGradientBrush(Point[], WrapMode) - PathGradientBrush コンストラクター (System.Drawing.Drawing2D) | Microsoft Learn
Brush b1 = new SolidBrush( Color.White ); Brush b2 = Brushes.White; Brush b3 = SystemBrushes.Window;
メソッド | 描画される図形 |
---|---|
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()を用います。
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
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 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) で終了しました。」としてアプリケーションがクラッシュします。
imageAttrsを指定することで、色を変更できます。
このメソッドは内部ではサイズを指定しないDrawImage()を呼ぶだけのため、DrawImageUnscaled(Image, Int32, Int32)はDrawImage(Image, Int32, Int32)を呼ぶことと同義です。DrawImageUnscaled - Graphics.cs
画像の一部の切り取り (クリッピング) だけをするならば、スケーリングを伴わない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 Learn
互換性が問題とならないならば、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 Learn
TextFormatFlags flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter; TextRenderer.DrawText(e.Graphics, text, font, bounds, foreColor, flags);
flagsにEndEllipsisを指定して省略記号が描画されたとき、再描画時にその領域が対象とならなかったときには、不要となった省略記号がそのまま残ることがあります。
クリッピング領域が適用されるようにするには、flagsでPreserveGraphicsClippingを指定します。
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 Learn
string text = "SAMPLE"; int maxWidth = 100; StringFormat stringFormat = new StringFormat(StringFormatFlags.NoClip); SizeF size = e.Graphics.MeasureString( text, this.Font, maxWidth, stringFormat); // {Width = 49.7499924 Height = 13.4999981} SizeF size1 = g.MeasureString(text, this.Font, 50); // {Width = 49.7499924 Height = 13.4999981} SizeF size2 = g.MeasureString(text, this.Font, 25); // {Width = 20.80078 Height = 37.4999924} SizeF size3 = g.MeasureString(text, this.Font, 10); // {Width = 10 Height = 73.4999847} SizeF size4 = g.MeasureString(text, this.Font, 1); // {Width = 1 Height = 73.4999847}
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 Learn
string text = "SAMPLE"; Size proposedSize = new Size(100, 50); Size size = TextRenderer.MeasureText( text, this.Font, proposedSize, TextFormatFlags.Default);文字列を描画したときの大きさを計測する - .NET Tips (VB.NET,C#...)
必要なのが文字単体の大きさならば、Fontのプロパティから得られます。
パスに文字列を追加できます。
public void AddString ( string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.Point origin, System.Drawing.StringFormat format );AddString(String, FontFamily, Int32, Single, Point, StringFormat) - GraphicsPath.AddString メソッド (System.Drawing.Drawing2D) | Microsoft Learn
文字列を縁取りをして描画する - .NET Tips (VB.NET,C#...)
次の3つの解決法があります。
DoubleBufferedプロパティがprotectedのため、それを継承したクラスを作成した上でDoubleBufferedをtrueとします。
this.DoubleBuffered = true;
またはリフレクションによりprotectedなプロパティを書き替えます。
PropertyInfo property = typeof(Control).GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); property.SetValue(control, true);
ControlのSetStyle()も同様にprotectedのため、継承したクラスを作成した上で設定します。.NET TIPS:背景の描画を禁止して再描画時のちらつきをなくすには? - @IT 遠藤孝信 (2004/08/19)
this.SetStyle(ControlStyles.Opaque, true);
次の2つの解決法があります。