C#で図形描画を始める方法|初心者でもわかるGraphics・Canvas・直線・円・四角形の描き方
はじめに
C#で図形描画を始めたいと思ったとき、多くの初心者が最初に迷うのが「Graphicsを使えばいいのか」「Canvasを使えばいいのか」「直線や円、四角形はどうやって描くのか」という点です。
C#では、Windows FormsのGraphicsクラスを使って画面や画像に図形を描画できます。また、WPFではCanvasというパネルを使い、LineやRectangle、Ellipseなどの図形オブジェクトを配置して描画できます。
この記事では、C#で図形描画を始めるために必要な基礎知識から、直線・円・四角形の描き方、マウス操作による描画、保存や再描画の考え方まで、初心者にもわかりやすく解説します。
1. C#の図形描画でできること
C#の図形描画を使うと、画面上に線や円、四角形などの図形を表示したり、画像ファイルとして保存したりできます。単純な図形だけでなく、複数の図形を組み合わせることで、グラフ、図解、簡単なゲーム画面、お絵描きアプリのような機能も作れます。
C#で図形描画を学ぶと、アプリの見た目を自由にカスタマイズできるようになり、プログラムで画像を生成する処理にも応用できます。
1-1. C#で描ける基本図形|直線・円・四角形・楕円・多角形
C#では、次のような基本図形を描画できます。
直線は、開始位置と終了位置を指定して描きます。たとえば、画面の左上から右下に向かって線を引くような処理です。
四角形は、左上の座標、幅、高さを指定して描きます。枠線だけを描くことも、塗りつぶすこともできます。
円や楕円は、指定した四角形の範囲に収まる形で描画します。幅と高さが同じなら円になり、異なれば楕円になります。
多角形は、複数の点を指定して、それらを線で結ぶことで描画します。三角形、五角形、自由な形の図形などを表現できます。
Windows FormsのGraphicsでは、主に次のようなメソッドを使います。
C#DrawLine // 直線を描く
DrawRectangle // 四角形の枠線を描く
DrawEllipse // 円や楕円の枠線を描く
DrawPolygon // 多角形の枠線を描く
FillRectangle // 四角形を塗りつぶす
FillEllipse // 円や楕円を塗りつぶす
FillPolygon // 多角形を塗りつぶす
WPFのCanvasでは、次のような図形クラスを使います。
C#Line // 直線
Rectangle // 四角形
Ellipse // 円・楕円
Polygon // 多角形
このように、C#の図形描画では基本的な図形を簡単に扱えます。
1-2. 図形描画が使われる場面|お絵描きアプリ・グラフ・ゲーム・画像生成
C#の図形描画は、さまざまなアプリ開発で使われます。
代表的なのは、お絵描きアプリです。マウスでドラッグした位置に線を描いたり、クリックした場所に円や四角形を配置したりできます。
グラフ表示にも図形描画はよく使われます。棒グラフなら四角形、折れ線グラフなら直線、散布図なら小さな円を描くことで実現できます。
ゲーム開発でも、簡単な2Dゲームであれば図形描画だけでキャラクターや弾、障害物などを表現できます。たとえば、四角形をプレイヤー、円をボールとして扱う簡単なゲームを作ることも可能です。
また、画面に表示するだけでなく、Bitmapに図形を描画すれば、画像ファイルとして保存できます。プログラムでサムネイル画像、図解画像、帳票画像などを自動生成したい場合にも便利です。
1-3. 初心者が最初に理解すべき「描画先」と「描画方法」
C#で図形描画を学ぶときは、まず「どこに描くのか」と「どうやって描くのか」を分けて考えることが大切です。
「描画先」とは、図形を表示する場所のことです。Windows Formsならフォーム、パネル、PictureBox、Bitmapなどが描画先になります。WPFならCanvasなどの画面要素が描画先になります。
「描画方法」とは、実際に線や円、四角形を描く手段です。Windows FormsではGraphicsオブジェクトを使って描画します。WPFではCanvas上に図形オブジェクトを追加して描画します。
初心者は、まず次のように考えると理解しやすくなります。
C#描画先:どこに描くか
描画方法:何を使って描くか
描画内容:直線、円、四角形など何を描くか
C#の図形描画では、この3つを意識するとコードの意味がわかりやすくなります。
2. C#で図形描画を始める前に知っておきたい基礎
図形描画のコードを書く前に、座標、色、線、塗りつぶしなどの基本を理解しておきましょう。これらはGraphicsでもCanvasでも共通する考え方です。
2-1. 座標の考え方|左上が原点でX軸・Y軸が増える方向
C#の画面描画では、多くの場合、画面の左上が座標の原点になります。原点の座標は(0, 0)です。
横方向がX座標、縦方向がY座標です。右に進むほどXの値が大きくなり、下に進むほどYの値が大きくなります。
たとえば、座標(50, 100)は、左上から右に50ピクセル、下に100ピクセルの位置を意味します。
数学のグラフでは上方向にYが増えることが多いですが、画面描画では下方向にYが増える点に注意しましょう。
C#左上 Xが増える方向 →
(0,0)
|
|
↓
Yが増える方向
四角形を描く場合は、左上の座標と幅、高さを指定します。
C#g.DrawRectangle(Pens.Black, 50, 50, 100, 80);
このコードでは、左上が(50, 50)、幅が100、高さが80の四角形を描画します。
2-2. PenとBrushの違い|線を描く場合と塗りつぶす場合
Windows FormsのGraphicsで図形を描くときによく使うのがPenとBrushです。
Penは線を描くための道具です。直線、四角形の枠線、円の枠線などを描くときに使います。
C#Pen pen = new Pen(Color.Blue, 3);
g.DrawLine(pen, 10, 10, 200, 10);
このコードでは、青色で太さ3ピクセルの直線を描きます。
一方、Brushは図形を塗りつぶすための道具です。四角形や円の内部を色で塗るときに使います。
C#Brush brush = new SolidBrush(Color.Red);
g.FillEllipse(brush, 50, 50, 100, 100);
このコードでは、赤色で塗りつぶされた円を描きます。
つまり、枠線を描きたい場合はPen、塗りつぶしたい場合はBrushを使います。
2-3. 色・線の太さ・塗りつぶしを指定する基本
色はColorを使って指定します。あらかじめ用意されている色名を使うこともできます。
C#Color.Red
Color.Blue
Color.Green
Color.Black
Color.White
線の太さはPenを作るときに指定します。
C#Pen pen = new Pen(Color.Black, 5);
この場合、黒色で太さ5ピクセルの線になります。
塗りつぶしの色はSolidBrushで指定します。
C#Brush brush = new SolidBrush(Color.Yellow);
この場合、黄色で図形を塗りつぶせます。
コードでは次のように使います。
C#using (Pen pen = new Pen(Color.Black, 3))
using (Brush brush = new SolidBrush(Color.LightBlue))
{
g.DrawRectangle(pen, 20, 20, 150, 100);
g.FillEllipse(brush, 200, 20, 100, 100);
}
PenやBrushは使い終わったら破棄する必要があるため、usingを使うのが基本です。
2-4. Draw系メソッドとFill系メソッドの違い
Graphicsのメソッドには、Drawで始まるものとFillで始まるものがあります。
Draw系メソッドは、図形の枠線を描きます。
C#g.DrawRectangle(Pens.Black, 20, 20, 100, 80);
g.DrawEllipse(Pens.Blue, 150, 20, 100, 80);
Fill系メソッドは、図形の内部を塗りつぶします。
C#g.FillRectangle(Brushes.Red, 20, 120, 100, 80);
g.FillEllipse(Brushes.Green, 150, 120, 100, 80);
枠線だけを描きたいときはDraw系、色で塗りたいときはFill系を使います。
枠線と塗りつぶしの両方を使いたい場合は、先にFill系で塗りつぶし、その後にDraw系で枠線を描くときれいに表示できます。
C#g.FillRectangle(Brushes.LightBlue, 50, 50, 120, 80);
g.DrawRectangle(Pens.Navy, 50, 50, 120, 80);
3. C#の図形描画はGraphicsとCanvasのどちらを使うべきか
C#で図形描画を調べると、GraphicsとCanvasという言葉がよく出てきます。どちらも図形描画に関係しますが、使われる場面が異なります。
Windows Formsでは主にGraphicsを使います。WPFでは主にCanvasを使います。
どちらを選ぶべきかは、作りたいアプリの種類によって変わります。
3-1. Graphicsとは|WinFormsや画像描画で使う基本クラス
Graphicsは、Windows Formsや画像処理で図形を描くために使うクラスです。
フォームやPictureBoxの上に線や円を描いたり、Bitmapに図形を描いて画像として保存したりできます。
たとえば、Windows FormsのPaintイベントでは、次のようにGraphicsを使います。
C#private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawLine(Pens.Black, 10, 10, 200, 100);
}
e.Graphicsが描画用のGraphicsオブジェクトです。このオブジェクトに対してDrawLineやDrawRectangleを呼び出すことで図形を描画します。
Bitmapに描画する場合は、次のようにします。
C#Bitmap bitmap = new Bitmap(300, 200);
using (Graphics g = Graphics.FromImage(bitmap))
{
g.Clear(Color.White);
g.DrawEllipse(Pens.Red, 50, 50, 100, 100);
}
bitmap.Save("sample.png");
このようにGraphicsは、画面描画だけでなく画像生成にも使えます。
3-2. Canvasとは|WPFで図形を配置して描くためのパネル
Canvasは、WPFで使われるレイアウト用のパネルです。Canvasの中に図形オブジェクトを配置することで、直線、四角形、円などを表示できます。
WPFでは、Line、Rectangle、Ellipseなどの図形そのものがオブジェクトとして存在します。
たとえば、XAMLでCanvasに四角形を配置する場合は次のように書きます。
XML<Canvas Background="White">
<Rectangle Width="120"
Height="80"
Stroke="Black"
Fill="LightBlue"
Canvas.Left="50"
Canvas.Top="40" />
</Canvas>
このコードでは、Canvas上の左から50、上から40の位置に四角形を配置しています。
WPFのCanvasは、図形を部品として配置するイメージです。そのため、あとから図形の位置や色を変更しやすいという特徴があります。
3-3. GraphicsとCanvasの違いを初心者向けに比較
GraphicsとCanvasの違いを簡単にまとめると、次のようになります。
| 項目 | Graphics | Canvas |
|---|---|---|
| 主な用途 | Windows Forms、画像描画 | WPFの画面描画 |
| 描画の考え方 | メソッドで直接描く | 図形オブジェクトを配置する |
| 代表的な図形 | DrawLine、DrawRectangleなど | Line、Rectangle、Ellipseなど |
| 再描画 | Paintイベントで描き直す | 配置した図形が保持されやすい |
| 画像保存 | Bitmapと組み合わせやすい | 画面UI向き |
| 初心者向けの理解 | キャンバスにペンで描くイメージ | 図形部品を置くイメージ |
Graphicsは「描く処理」をコードで実行する方式です。一方、Canvasは「図形を配置する」方式です。
そのため、Windows Formsで簡単に図形描画を試したい場合はGraphicsがわかりやすいです。WPFで画面部品として図形を扱いたい場合はCanvasが向いています。
3-4. 目的別の選び方|WinForms・WPF・画像ファイル出力
目的に応じて、GraphicsとCanvasを使い分けましょう。
Windows Formsアプリを作るなら、Graphicsを使うのが基本です。フォームやPictureBoxに図形を描けます。
WPFアプリを作るなら、Canvasを使うのが自然です。XAMLで図形を配置でき、C#コードから追加や変更もできます。
画像ファイルを出力したい場合は、BitmapとGraphicsの組み合わせが便利です。画面に表示しなくても、メモリ上で画像を作成してPNGやJPEGとして保存できます。
初心者がまず学ぶなら、Windows FormsのGraphicsから始めると、直線・円・四角形の描き方を理解しやすいです。その後、WPFを使う場合にCanvasを学ぶとスムーズです。
4. Windows FormsでGraphicsを使って図形を描画する方法
ここからは、Windows FormsでGraphicsを使って図形を描画する方法を解説します。
Windows Formsでは、フォームのPaintイベントやPictureBox、Bitmapなどに対して図形を描けます。
4-1. WinFormsプロジェクトを作成する手順
Visual StudioでWindows Formsアプリを作成する基本手順は次のとおりです。
まず、Visual Studioを起動します。次に「新しいプロジェクトの作成」を選択します。
プロジェクトテンプレートから「Windows Forms App」を選びます。C#用のテンプレートを選択してください。
プロジェクト名を入力し、保存場所を指定して作成します。
フォームデザイナーが表示されたら、Form1が最初の画面になります。このフォームに対して図形を描画していきます。
Paintイベントを使う場合は、フォームを選択した状態でイベント一覧からPaintを追加するか、コードに直接イベント処理を記述します。
4-2. Paintイベントで図形を描画する基本
Windows Formsで図形を描画する基本は、Paintイベントを使う方法です。
Paintイベントは、フォームを表示するときや再描画が必要になったときに呼び出されます。
C#private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawLine(Pens.Black, 10, 10, 200, 100);
g.DrawRectangle(Pens.Blue, 50, 120, 150, 80);
g.DrawEllipse(Pens.Red, 250, 120, 100, 100);
}
このコードでは、フォーム上に直線、四角形、円を描画しています。
PaintEventArgsのe.Graphicsを使うのが重要です。Paintイベント内では、基本的にこのGraphicsオブジェクトに対して描画します。
フォームのコンストラクタでPaintイベントを登録する場合は、次のように書きます。
C#public Form1()
{
InitializeComponent();
this.Paint += Form1_Paint;
}
これでフォームが描画されるタイミングでForm1_Paintが呼ばれます。
4-3. PictureBoxに図形を描画する方法
PictureBoxに図形を描画したい場合も、Paintイベントを使えます。
フォームにPictureBoxを配置し、名前をpictureBox1にしておきます。
C#public Form1()
{
InitializeComponent();
pictureBox1.Paint += pictureBox1_Paint;
}
Paintイベント内で描画します。
C#private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.Clear(Color.White);
g.DrawLine(Pens.Black, 10, 10, 200, 100);
g.DrawRectangle(Pens.Blue, 30, 120, 120, 80);
g.FillEllipse(Brushes.Orange, 180, 120, 100, 100);
}
PictureBoxのPaintイベントを使うと、フォーム全体ではなくPictureBoxの範囲内に図形を描画できます。
背景を白にしたい場合は、g.Clear(Color.White)を使います。ただし、毎回クリアされるため、描いた図形を保持したい場合は、後述するBitmapやリスト管理が必要です。
4-4. Bitmapに描画して画像として扱う方法
描画した内容を画像として保存したい場合は、Bitmapに対してGraphicsで描画します。
C#Bitmap bitmap = new Bitmap(400, 300);
using (Graphics g = Graphics.FromImage(bitmap))
{
g.Clear(Color.White);
using (Pen pen = new Pen(Color.Blue, 3))
using (Brush brush = new SolidBrush(Color.LightPink))
{
g.DrawLine(pen, 20, 20, 350, 50);
g.FillEllipse(brush, 100, 100, 120, 120);
g.DrawRectangle(Pens.Black, 250, 120, 100, 80);
}
}
bitmap.Save("drawing.png");
このコードでは、400×300ピクセルのBitmapを作成し、その上に図形を描いてdrawing.pngとして保存しています。
画面に表示したい場合は、PictureBoxのImageに設定できます。
C#pictureBox1.Image = bitmap;
Bitmapを使うと、描画内容が画像として残るため、保存や再利用がしやすくなります。
4-5. Graphicsを使うときの注意点|Disposeと再描画
Graphicsを使うときは、いくつか注意点があります。
まず、自分で作成したGraphics、Pen、Brush、Bitmapなどは適切に破棄する必要があります。特にGraphics.FromImageで作成したGraphicsは、usingで囲むのが基本です。
C#using (Graphics g = Graphics.FromImage(bitmap))
{
// 描画処理
}
PenやBrushも自分で作成した場合はusingを使います。
C#using (Pen pen = new Pen(Color.Red, 2))
{
g.DrawLine(pen, 10, 10, 100, 100);
}
ただし、Pens.BlackやBrushes.Redのような標準オブジェクトは自分で破棄しません。
また、Paintイベント以外でフォームに直接描画すると、ウィンドウが隠れたりサイズ変更されたりしたときに描画内容が消えることがあります。画面に図形を表示し続けたい場合は、Paintイベントで毎回描き直すか、Bitmapに描画して保持するようにしましょう。
5. Graphicsで直線・円・四角形を描く基本コード
ここでは、Graphicsを使って直線、四角形、円を描く基本コードを紹介します。C#の図形描画で最初に覚えるべき内容です。
5-1. DrawLineで直線を描く方法
直線を描くには、DrawLineメソッドを使います。
C#g.DrawLine(Pens.Black, 10, 10, 200, 100);
引数は、ペン、開始X座標、開始Y座標、終了X座標、終了Y座標です。
C#g.DrawLine(ペン, 開始X, 開始Y, 終了X, 終了Y);
色や太さを指定したい場合は、Penを作成します。
C#using (Pen pen = new Pen(Color.Blue, 4))
{
g.DrawLine(pen, 20, 20, 250, 120);
}
このコードでは、青色で太さ4ピクセルの直線を描きます。
5-2. DrawRectangleで四角形を描く方法
四角形の枠線を描くには、DrawRectangleを使います。
C#g.DrawRectangle(Pens.Black, 50, 50, 150, 100);
引数は、ペン、左上X座標、左上Y座標、幅、高さです。
C#g.DrawRectangle(ペン, X, Y, 幅, 高さ);
線の色や太さを変える場合は、Penを作成します。
C#using (Pen pen = new Pen(Color.Green, 3))
{
g.DrawRectangle(pen, 60, 60, 180, 90);
}
このコードでは、緑色で太さ3ピクセルの四角形を描きます。
5-3. DrawEllipseで円・楕円を描く方法
円や楕円の枠線を描くには、DrawEllipseを使います。
C#g.DrawEllipse(Pens.Red, 50, 50, 100, 100);
幅と高さが同じ場合は円になります。
C#g.DrawEllipse(Pens.Red, 50, 50, 100, 100);
幅と高さが異なる場合は楕円になります。
C#g.DrawEllipse(Pens.Blue, 200, 50, 150, 80);
DrawEllipseは、指定した四角形の中に収まるように円や楕円を描きます。そのため、X座標、Y座標、幅、高さの考え方はDrawRectangleと似ています。
5-4. FillRectangleで四角形を塗りつぶす方法
四角形を塗りつぶすには、FillRectangleを使います。
C#g.FillRectangle(Brushes.LightBlue, 50, 50, 150, 100);
引数は、ブラシ、X座標、Y座標、幅、高さです。
C#g.FillRectangle(ブラシ, X, Y, 幅, 高さ);
枠線も描きたい場合は、塗りつぶした後にDrawRectangleを使います。
C#g.FillRectangle(Brushes.LightBlue, 50, 50, 150, 100);
g.DrawRectangle(Pens.Blue, 50, 50, 150, 100);
このようにすると、水色で塗りつぶした四角形に青い枠線を付けられます。
5-5. FillEllipseで円を塗りつぶす方法
円や楕円を塗りつぶすには、FillEllipseを使います。
C#g.FillEllipse(Brushes.Orange, 80, 80, 100, 100);
このコードでは、オレンジ色の円を描きます。
枠線も付けたい場合は、次のようにします。
C#g.FillEllipse(Brushes.Orange, 80, 80, 100, 100);
g.DrawEllipse(Pens.DarkOrange, 80, 80, 100, 100);
塗りつぶしを先に行い、そのあと枠線を描くのが基本です。逆にすると、枠線が塗りつぶしで隠れてしまう場合があります。
5-6. 複数の図形を組み合わせて描画するサンプル
複数の図形を組み合わせると、簡単なイラストのようなものも描けます。
C#private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.Clear(Color.White);
// 家の本体
g.FillRectangle(Brushes.LightYellow, 100, 150, 180, 120);
g.DrawRectangle(Pens.Black, 100, 150, 180, 120);
// 屋根
Point[] roof =
{
new Point(90, 150),
new Point(190, 80),
new Point(290, 150)
};
g.FillPolygon(Brushes.Brown, roof);
g.DrawPolygon(Pens.Black, roof);
// ドア
g.FillRectangle(Brushes.SaddleBrown, 170, 210, 40, 60);
g.DrawRectangle(Pens.Black, 170, 210, 40, 60);
// 窓
g.FillRectangle(Brushes.LightBlue, 120, 175, 40, 40);
g.DrawRectangle(Pens.Black, 120, 175, 40, 40);
g.FillRectangle(Brushes.LightBlue, 220, 175, 40, 40);
g.DrawRectangle(Pens.Black, 220, 175, 40, 40);
// 太陽
g.FillEllipse(Brushes.Orange, 320, 30, 60, 60);
g.DrawEllipse(Pens.DarkOrange, 320, 30, 60, 60);
}
このサンプルでは、四角形、多角形、円を組み合わせて家と太陽を描いています。基本図形だけでも、組み合わせ次第でさまざまな表現ができます。
6. WPFのCanvasで図形を描画する方法
WPFでは、Canvasに図形オブジェクトを配置して描画します。Windows FormsのGraphicsとは考え方が少し違いますが、図形を部品として扱えるため、位置や色の変更がしやすいという特徴があります。
6-1. WPFでCanvasを配置する基本
WPFでCanvasを使うには、XAMLにCanvasを配置します。
XML<Window x:Class="WpfDrawingSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="C# 図形描画" Height="400" Width="600">
<Canvas Name="MyCanvas" Background="White">
</Canvas>
</Window>
Name="MyCanvas"を指定しておくと、C#コードからCanvasにアクセスできます。
Background="White"を指定しておくと、Canvasの背景が白になります。背景を指定していないと、マウスイベントが反応しにくい場合があるため、初心者は背景色を設定しておくと安心です。
6-2. Lineで直線を描く方法
WPFで直線を描くには、Lineを使います。
XAMLで書く場合は次のようになります。
XML<Line X1="20" Y1="20"
X2="250" Y2="100"
Stroke="Black"
StrokeThickness="3" />
X1とY1が開始位置、X2とY2が終了位置です。
C#コードから追加する場合は、次のようにします。
C#Line line = new Line
{
X1 = 20,
Y1 = 20,
X2 = 250,
Y2 = 100,
Stroke = Brushes.Black,
StrokeThickness = 3
};
MyCanvas.Children.Add(line);
WPFでは、線も1つのオブジェクトとしてCanvasに追加します。
6-3. Rectangleで四角形を描く方法
WPFで四角形を描くには、Rectangleを使います。
XAMLで書く場合は次のようになります。
XML<Rectangle Width="150"
Height="100"
Stroke="Blue"
StrokeThickness="3"
Fill="LightBlue"
Canvas.Left="50"
Canvas.Top="50" />
WidthとHeightでサイズを指定し、Canvas.LeftとCanvas.Topで位置を指定します。
C#コードでは次のように書きます。
C#Rectangle rect = new Rectangle
{
Width = 150,
Height = 100,
Stroke = Brushes.Blue,
StrokeThickness = 3,
Fill = Brushes.LightBlue
};
Canvas.SetLeft(rect, 50);
Canvas.SetTop(rect, 50);
MyCanvas.Children.Add(rect);
Strokeが枠線の色、Fillが塗りつぶしの色です。
6-4. Ellipseで円・楕円を描く方法
WPFで円や楕円を描くには、Ellipseを使います。
XML<Ellipse Width="100"
Height="100"
Stroke="Red"
StrokeThickness="3"
Fill="Pink"
Canvas.Left="250"
Canvas.Top="50" />
幅と高さが同じなら円、異なれば楕円になります。
C#コードから追加する場合は次のようにします。
C#Ellipse ellipse = new Ellipse
{
Width = 100,
Height = 100,
Stroke = Brushes.Red,
StrokeThickness = 3,
Fill = Brushes.Pink
};
Canvas.SetLeft(ellipse, 250);
Canvas.SetTop(ellipse, 50);
MyCanvas.Children.Add(ellipse);
WPFのCanvasでは、図形をあとから移動したり、色を変更したりしやすいのがメリットです。
6-5. Canvas.LeftとCanvas.Topで図形の位置を指定する方法
Canvas上で図形の位置を指定するには、Canvas.LeftとCanvas.Topを使います。
Canvas.Leftは左からの距離、Canvas.Topは上からの距離です。
XML<Rectangle Width="100"
Height="60"
Fill="SkyBlue"
Canvas.Left="80"
Canvas.Top="120" />
C#コードでは、Canvas.SetLeftとCanvas.SetTopを使います。
C#Canvas.SetLeft(rect, 80);
Canvas.SetTop(rect, 120);
この考え方は、Windows Formsの座標指定と似ています。左上を基準にして、右に行くほどXが増え、下に行くほどYが増えます。
6-6. C#コードからCanvasに図形を追加する方法
C#コードからCanvasに複数の図形を追加するサンプルを見てみましょう。
C#private void DrawShapes()
{
MyCanvas.Children.Clear();
Line line = new Line
{
X1 = 20,
Y1 = 20,
X2 = 300,
Y2 = 80,
Stroke = Brushes.Black,
StrokeThickness = 2
};
MyCanvas.Children.Add(line);
Rectangle rect = new Rectangle
{
Width = 120,
Height = 80,
Stroke = Brushes.Blue,
StrokeThickness = 3,
Fill = Brushes.LightBlue
};
Canvas.SetLeft(rect, 50);
Canvas.SetTop(rect, 120);
MyCanvas.Children.Add(rect);
Ellipse ellipse = new Ellipse
{
Width = 100,
Height = 100,
Stroke = Brushes.Red,
StrokeThickness = 3,
Fill = Brushes.LightPink
};
Canvas.SetLeft(ellipse, 220);
Canvas.SetTop(120);
MyCanvas.Children.Add(ellipse);
}
MyCanvas.Children.Addで図形を追加し、MyCanvas.Children.ClearでCanvas上の図形をすべて消去できます。
7. マウス操作で図形を描画する方法
図形描画を使ったアプリでは、マウス操作で図形を描く機能がよく使われます。クリックした位置に図形を描いたり、ドラッグした範囲に四角形や円を描いたりできます。
7-1. マウスクリック位置の座標を取得する方法
Windows Formsでマウスクリック位置を取得するには、MouseDownイベントを使います。
C#private void Form1_MouseDown(object sender, MouseEventArgs e)
{
int x = e.X;
int y = e.Y;
MessageBox.Show($"クリック位置: X={x}, Y={y}");
}
e.Xとe.Yで、クリックされた位置の座標を取得できます。
クリック位置に円を描きたい場合は、座標を保存してから再描画します。
C#private Point clickPoint;
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
clickPoint = e.Location;
Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.FillEllipse(Brushes.Red, clickPoint.X - 10, clickPoint.Y - 10, 20, 20);
}
Invalidate()を呼び出すと、フォームが再描画され、Paintイベントが実行されます。
7-2. ドラッグ操作で直線を描く方法
ドラッグで直線を描くには、マウスを押した位置と離した位置を記録します。
C#private Point startPoint;
private Point endPoint;
private bool hasLine = false;
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
startPoint = e.Location;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
endPoint = e.Location;
hasLine = true;
Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (hasLine)
{
e.Graphics.DrawLine(Pens.Black, startPoint, endPoint);
}
}
このコードでは、マウスを押した位置から離した位置まで直線を描きます。
ドラッグ中にも線を表示したい場合は、MouseMoveイベントで現在位置を更新します。
C#private bool isDragging = false;
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
startPoint = e.Location;
endPoint = e.Location;
isDragging = true;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
endPoint = e.Location;
Invalidate();
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
endPoint = e.Location;
isDragging = false;
hasLine = true;
Invalidate();
}
7-3. ドラッグ範囲に四角形や円を描く方法
ドラッグした範囲に四角形や円を描くには、開始点と終了点から描画範囲を計算します。
マウスを左上から右下にドラッグするとは限らないため、Math.MinとMath.Absを使って矩形を作るのがポイントです。
C#private Rectangle GetRectangle(Point p1, Point p2)
{
int x = Math.Min(p1.X, p2.X);
int y = Math.Min(p1.Y, p2.Y);
int width = Math.Abs(p1.X - p2.X);
int height = Math.Abs(p1.Y - p2.Y);
return new Rectangle(x, y, width, height);
}
四角形を描く場合は次のようにします。
C#private void Form1_Paint(object sender, PaintEventArgs e)
{
if (isDragging || hasLine)
{
Rectangle rect = GetRectangle(startPoint, endPoint);
e.Graphics.DrawRectangle(Pens.Blue, rect);
}
}
円や楕円を描く場合は、DrawEllipseを使います。
C#private void Form1_Paint(object sender, PaintEventArgs e)
{
if (isDragging || hasLine)
{
Rectangle rect = GetRectangle(startPoint, endPoint);
e.Graphics.DrawEllipse(Pens.Red, rect);
}
}
この方法なら、どの方向にドラッグしても正しく図形を描けます。
7-4. 描画した図形をリストで管理する考え方
Paintイベントでは、画面が再描画されるたびに描画処理が実行されます。そのため、描いた図形を残したい場合は、図形の情報をリストで管理します。
たとえば、四角形を複数描く場合は、List<Rectangle>を使います。
C#private List<Rectangle> rectangles = new List<Rectangle>();
private Point startPoint;
private Point endPoint;
private bool isDragging = false;
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
startPoint = e.Location;
endPoint = e.Location;
isDragging = true;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
endPoint = e.Location;
Invalidate();
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
isDragging = false;
Rectangle rect = GetRectangle(startPoint, e.Location);
rectangles.Add(rect);
Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
foreach (Rectangle rect in rectangles)
{
e.Graphics.DrawRectangle(Pens.Blue, rect);
}
if (isDragging)
{
Rectangle preview = GetRectangle(startPoint, endPoint);
e.Graphics.DrawRectangle(Pens.Red, preview);
}
}
このコードでは、確定した四角形をリストに保存し、Paintイベントで毎回描き直しています。ドラッグ中の図形はプレビューとして赤色で表示しています。
7-5. 再描画しても図形が消えないようにする方法
C#の図形描画で初心者がよく困るのが、「描いた図形が消える」という問題です。
フォームに直接描いた図形は、ウィンドウが再描画されると消えることがあります。これを防ぐには、描画内容を何らかの形で保持する必要があります。
主な方法は2つあります。
1つ目は、図形の情報をリストで保持し、Paintイベントで毎回描き直す方法です。直線なら開始点と終了点、四角形なら座標とサイズ、円なら外接する四角形の情報を保存します。
2つ目は、Bitmapに描画して、そのBitmapを表示する方法です。Bitmapに直接描いた内容は画像として保持されるため、再描画しても消えにくくなります。
アプリ内で図形をあとから編集したい場合は、リスト管理が向いています。単純なお絵描きのように描いた線を画像として残したい場合は、Bitmap管理が向いています。
8. 図形描画をきれいに見せるテクニック
基本的な図形描画ができるようになったら、見た目をきれいにするテクニックも覚えておきましょう。線をなめらかにしたり、半透明にしたり、重なり順を調整したりできます。
8-1. アンチエイリアスで線や円をなめらかにする方法
Graphicsで円や斜め線を描くと、ギザギザが目立つことがあります。このギザギザを目立ちにくくするには、アンチエイリアスを有効にします。
C#using System.Drawing.Drawing2D;
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.DrawEllipse(Pens.Black, 50, 50, 150, 150);
g.DrawLine(Pens.Red, 20, 20, 250, 180);
}
SmoothingMode.AntiAliasを指定すると、線や円がなめらかに表示されます。特に円、楕円、斜め線を描くときに効果があります。
8-2. 線の色・太さ・破線を変更する方法
線の色や太さを変えるには、Penを作成します。
C#using (Pen pen = new Pen(Color.Blue, 5))
{
g.DrawLine(pen, 20, 20, 250, 20);
}
破線を描くには、PenのDashStyleを設定します。
C#using System.Drawing.Drawing2D;
using (Pen pen = new Pen(Color.Red, 3))
{
pen.DashStyle = DashStyle.Dash;
g.DrawRectangle(pen, 50, 50, 150, 100);
}
点線にしたい場合は、DashStyle.Dotを使います。
C#using (Pen pen = new Pen(Color.Green, 3))
{
pen.DashStyle = DashStyle.Dot;
g.DrawLine(pen, 20, 100, 250, 100);
}
線の表現を変えるだけで、図形描画の見た目は大きく変わります。
8-3. 半透明の図形を描く方法
半透明の図形を描くには、Color.FromArgbを使います。
C#Color semiTransparentRed = Color.FromArgb(128, Color.Red);
using (Brush brush = new SolidBrush(semiTransparentRed))
{
g.FillEllipse(brush, 50, 50, 150, 150);
}
FromArgbの最初の値は透明度です。0に近いほど透明、255に近いほど不透明になります。
複数の半透明図形を重ねると、重なった部分の色が混ざって見えます。
C#using (Brush redBrush = new SolidBrush(Color.FromArgb(128, Color.Red)))
using (Brush blueBrush = new SolidBrush(Color.FromArgb(128, Color.Blue)))
{
g.FillEllipse(redBrush, 50, 50, 150, 150);
g.FillEllipse(blueBrush, 120, 50, 150, 150);
}
半透明は、選択範囲の表示、ハイライト、グラフの重なり表現などに便利です。
8-4. 図形の重なり順を制御する方法
Graphicsでは、後から描いた図形が前面に表示されます。
C#g.FillRectangle(Brushes.Blue, 50, 50, 120, 120);
g.FillEllipse(Brushes.Red, 100, 100, 120, 120);
この場合、赤い円が青い四角形の上に表示されます。
逆にしたい場合は、描画する順番を入れ替えます。
C#g.FillEllipse(Brushes.Red, 100, 100, 120, 120);
g.FillRectangle(Brushes.Blue, 50, 50, 120, 120);
WPFのCanvasでも、基本的には後から追加した図形が前面に表示されます。また、Panel.ZIndexを使うと重なり順を指定できます。
C#Canvas.SetZIndex(rectangle, 1);
Canvas.SetZIndex(ellipse, 2);
ZIndexの値が大きいほど前面に表示されます。
8-5. 背景色やキャンバスサイズを設定する方法
Windows Formsで背景色を設定するには、フォームやPictureBoxのBackColorを使います。
C#this.BackColor = Color.White;
pictureBox1.BackColor = Color.White;
Paintイベント内で背景を塗りつぶす場合は、Clearを使います。
C#e.Graphics.Clear(Color.White);
Bitmapの場合は、画像全体の背景色として使えます。
C#using (Graphics g = Graphics.FromImage(bitmap))
{
g.Clear(Color.White);
}
WPFのCanvasでは、Backgroundを指定します。
XML<Canvas Name="MyCanvas" Background="White" Width="500" Height="300" />
背景色やサイズを最初に決めておくと、図形の座標や配置を考えやすくなります。
9. 描画した図形を保存・消去・更新する方法
図形描画アプリを作る場合、描いた内容を保存したり、クリアしたり、ボタン操作で描き直したりする機能が必要になることがあります。
9-1. 描画内容を画像ファイルとして保存する方法
Graphicsで描画した内容を画像ファイルとして保存するには、Bitmapに描画してSaveメソッドを使います。
C#Bitmap bitmap = new Bitmap(400, 300);
using (Graphics g = Graphics.FromImage(bitmap))
{
g.Clear(Color.White);
g.DrawRectangle(Pens.Black, 50, 50, 150, 100);
g.FillEllipse(Brushes.Red, 220, 80, 100, 100);
}
bitmap.Save("output.png", System.Drawing.Imaging.ImageFormat.Png);
PictureBoxに表示しているBitmapを保存する場合は、次のようにできます。
C#Bitmap bitmap = pictureBox1.Image as Bitmap;
if (bitmap != null)
{
bitmap.Save("saved.png", System.Drawing.Imaging.ImageFormat.Png);
}
ファイル形式はPNG、JPEG、BMPなどを指定できます。
C#bitmap.Save("output.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
bitmap.Save("output.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
図形をきれいに保存したい場合は、背景色を白などで塗ってから保存すると、透明や黒背景の問題を避けやすくなります。
9-2. 描画内容をクリアする方法
Paintイベントで描画している場合は、保持している図形リストを空にしてからInvalidateを呼び出します。
C#rectangles.Clear();
Invalidate();
Bitmapに描画している場合は、Graphicsで背景色を塗り直します。
C#using (Graphics g = Graphics.FromImage(bitmap))
{
g.Clear(Color.White);
}
pictureBox1.Invalidate();
WPFのCanvasで図形を消す場合は、Children.Clearを使います。
C#MyCanvas.Children.Clear();
ただし、Canvas内にボタンなど図形以外の要素も入っている場合は、それらも消えてしまいます。図形だけを消したい場合は、図形用のCanvasを分けるか、対象の要素だけ削除するようにしましょう。
9-3. ボタン操作で図形を描き直す方法
ボタンを押したときに図形を描き直したい場合は、ボタンのClickイベントで状態を変更し、Invalidateを呼び出します。
C#private bool drawCircle = false;
private void button1_Click(object sender, EventArgs e)
{
drawCircle = !drawCircle;
Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.White);
if (drawCircle)
{
e.Graphics.FillEllipse(Brushes.Red, 100, 100, 100, 100);
}
else
{
e.Graphics.FillRectangle(Brushes.Blue, 100, 100, 100, 100);
}
}
このコードでは、ボタンを押すたびに円と四角形が切り替わります。
WPFのCanvasであれば、ボタンのClickイベントでCanvasをクリアし、図形を追加し直します。
C#private void Button_Click(object sender, RoutedEventArgs e)
{
MyCanvas.Children.Clear();
Ellipse ellipse = new Ellipse
{
Width = 100,
Height = 100,
Fill = Brushes.Orange,
Stroke = Brushes.Black
};
Canvas.SetLeft(ellipse, 100);
Canvas.SetTop(ellipse, 80);
MyCanvas.Children.Add(ellipse);
}
9-4. 画面サイズ変更時に図形を再描画する方法
フォームのサイズを変更したときに図形を再描画したい場合は、ResizeイベントでInvalidateを呼び出します。
C#private void Form1_Resize(object sender, EventArgs e)
{
Invalidate();
}
Paintイベント内では、現在のフォームサイズを使って描画位置を計算できます。
C#private void Form1_Paint(object sender, PaintEventArgs e)
{
int width = this.ClientSize.Width;
int height = this.ClientSize.Height;
e.Graphics.Clear(Color.White);
e.Graphics.DrawLine(Pens.Black, 0, 0, width, height);
e.Graphics.DrawEllipse(Pens.Blue, width / 2 - 50, height / 2 - 50, 100, 100);
}
このコードでは、フォームサイズに合わせて対角線と中央の円を描画します。
サイズ変更に対応した図形描画を行う場合は、固定座標だけでなく、画面の幅や高さを使って位置を計算するとよいでしょう。
10. C#の図形描画でよくあるエラーと対処法
C#で図形描画を始めると、図形が表示されない、再描画で消える、座標がずれているなどの問題がよく起こります。ここでは初心者がつまずきやすいポイントを解説します。
10-1. 図形が表示されない原因と確認ポイント
図形が表示されない場合は、まず描画処理が実行されているか確認しましょう。
Paintイベントに正しく登録されていないと、描画コードを書いても実行されません。
C#this.Paint += Form1_Paint;
また、座標が画面外になっていないかも確認します。
C#g.DrawRectangle(Pens.Black, 1000, 1000, 100, 100);
フォームのサイズが小さい場合、この図形は画面外に描かれるため見えません。
線の色と背景色が同じ場合も、図形が表示されていないように見えます。
C#g.DrawLine(Pens.White, 10, 10, 200, 100);
背景が白の場合、白い線は見えません。黒や赤など、背景と違う色を指定しましょう。
10-2. 再描画すると図形が消える原因
フォームに一度だけ直接描画すると、ウィンドウが隠れたり、最小化されたり、サイズ変更されたりしたときに図形が消えることがあります。
これは、Windows Formsの画面が必要に応じて再描画されるためです。
対策としては、Paintイベントで毎回描き直すようにします。
C#private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawRectangle(Pens.Black, 50, 50, 100, 80);
}
マウスで描いた図形を残したい場合は、図形情報をリストに保存してPaintイベントで再描画します。
C#foreach (Rectangle rect in rectangles)
{
e.Graphics.DrawRectangle(Pens.Black, rect);
}
あるいは、Bitmapに描画して画像として保持する方法もあります。
10-3. 座標やサイズの指定ミスで図形が見えない場合
図形が見えない原因として、幅や高さが0になっている場合があります。
C#g.DrawRectangle(Pens.Black, 50, 50, 0, 100);
幅が0なので四角形として表示されません。
ドラッグで図形を描く場合、開始点と終了点の差から幅や高さを計算しますが、マイナス値にならないように注意が必要です。
C#int width = endPoint.X - startPoint.X;
int height = endPoint.Y - startPoint.Y;
このままだと、左上以外の方向にドラッグしたときにうまく描けない場合があります。
対策として、次のようにします。
C#int x = Math.Min(startPoint.X, endPoint.X);
int y = Math.Min(startPoint.Y, endPoint.Y);
int width = Math.Abs(endPoint.X - startPoint.X);
int height = Math.Abs(endPoint.Y - startPoint.Y);
Rectangle rect = new Rectangle(x, y, width, height);
これで、どの方向にドラッグしても正しい範囲で図形を描けます。
10-4. Graphicsオブジェクトの使い方で注意すべき点
Graphicsオブジェクトは、使い方を間違えると図形が消えたり、リソースを無駄に使ったりします。
Paintイベントでは、基本的にe.Graphicsを使います。
C#private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawLine(Pens.Black, 10, 10, 200, 100);
}
一方、CreateGraphicsを使って描画する方法もありますが、初心者にはあまりおすすめしません。
C#Graphics g = this.CreateGraphics();
g.DrawLine(Pens.Black, 10, 10, 200, 100);
g.Dispose();
CreateGraphicsで描いた内容は、再描画されると消えることがあります。画面に残したい図形は、Paintイベントで描くか、Bitmapに描くようにしましょう。
また、自分で作成したGraphicsは必ず破棄します。
C#using (Graphics g = Graphics.FromImage(bitmap))
{
g.DrawEllipse(Pens.Red, 50, 50, 100, 100);
}
usingを使えば、自動的にDisposeされるため安全です。
10-5. System.Drawingが使えない場合の確認ポイント
C#でGraphicsを使う場合、多くのサンプルではSystem.Drawingを使います。
C#using System.Drawing;
しかし、プロジェクトの種類や実行環境によっては、System.Drawingが使えない、または推奨されない場合があります。
Windows Formsアプリであれば、通常はSystem.Drawingを使えます。もし使えない場合は、プロジェクトがWindows Forms用になっているか確認しましょう。
.NETのバージョンによっては、プロジェクトファイルにWindows Formsの設定が必要な場合があります。
XML<PropertyGroup>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
また、System.Drawing.Commonは環境によって扱いに注意が必要です。Windows向けのデスクトップアプリならWindows FormsやWPFを使うのが自然ですが、クロスプラットフォームで画像処理を行いたい場合は、別の画像ライブラリを検討することもあります。
初心者がWindows上でC#の図形描画を学ぶ場合は、まずWindows FormsのGraphics、またはWPFのCanvasから始めるのがおすすめです。
11. 初心者向け|C#図形描画の完成サンプル
最後に、Windows Formsで直線、四角形、円を描画し、マウスドラッグで四角形を追加できる完成サンプルを紹介します。
このサンプルでは、描いた四角形をリストで管理するため、再描画しても図形が消えません。
C#using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace DrawingSample
{
public partial class Form1 : Form
{
private List<Rectangle> rectangles = new List<Rectangle>();
private Point startPoint;
private Point currentPoint;
private bool isDragging = false;
public Form1()
{
InitializeComponent();
this.Text = "C# 図形描画サンプル";
this.BackColor = Color.White;
this.DoubleBuffered = true;
this.Paint += Form1_Paint;
this.MouseDown += Form1_MouseDown;
this.MouseMove += Form1_MouseMove;
this.MouseUp += Form1_MouseUp;
this.Resize += Form1_Resize;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.Clear(Color.White);
// 基本図形の描画
using (Pen linePen = new Pen(Color.Black, 2))
using (Pen rectPen = new Pen(Color.Blue, 3))
using (Pen ellipsePen = new Pen(Color.Red, 3))
using (Brush ellipseBrush = new SolidBrush(Color.FromArgb(120, Color.Orange)))
{
g.DrawLine(linePen, 20, 20, 250, 80);
g.DrawRectangle(rectPen, 50, 120, 150, 90);
g.FillEllipse(ellipseBrush, 250, 110, 120, 120);
g.DrawEllipse(ellipsePen, 250, 110, 120, 120);
}
// 保存済みの四角形を描画
using (Pen savedPen = new Pen(Color.Green, 2))
using (Brush savedBrush = new SolidBrush(Color.FromArgb(80, Color.LightGreen)))
{
foreach (Rectangle rect in rectangles)
{
g.FillRectangle(savedBrush, rect);
g.DrawRectangle(savedPen, rect);
}
}
// ドラッグ中のプレビュー
if (isDragging)
{
Rectangle preview = GetRectangle(startPoint, currentPoint);
using (Pen previewPen = new Pen(Color.DarkOrange, 2))
{
previewPen.DashStyle = DashStyle.Dash;
g.DrawRectangle(previewPen, preview);
}
}
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
startPoint = e.Location;
currentPoint = e.Location;
isDragging = true;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
currentPoint = e.Location;
Invalidate();
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (isDragging)
{
currentPoint = e.Location;
Rectangle rect = GetRectangle(startPoint, currentPoint);
if (rect.Width > 0 && rect.Height > 0)
{
rectangles.Add(rect);
}
isDragging = false;
Invalidate();
}
}
private void Form1_Resize(object sender, EventArgs e)
{
Invalidate();
}
private Rectangle GetRectangle(Point p1, Point p2)
{
int x = Math.Min(p1.X, p2.X);
int y = Math.Min(p1.Y, p2.Y);
int width = Math.Abs(p1.X - p2.X);
int height = Math.Abs(p1.Y - p2.Y);
return new Rectangle(x, y, width, height);
}
}
}
このサンプルのポイントは次のとおりです。
Paintイベントで図形を描画しています。これにより、画面が再描画されても図形を描き直せます。
List<Rectangle>で描画した四角形を管理しています。マウスを離したタイミングでリストに追加し、Paintイベントで毎回描画しています。
DoubleBuffered = trueを設定しているため、再描画時のちらつきを軽減できます。
SmoothingMode.AntiAliasを指定しているため、線や円がなめらかに表示されます。
ドラッグ中は破線のプレビューを表示し、マウスを離すと確定した四角形として保存されます。
このコードを応用すれば、円を描くモード、直線を描くモード、色を変更する機能、画像として保存する機能なども追加できます。
まとめ
C#で図形描画を始めるには、まず座標、Pen、Brush、Draw系メソッド、Fill系メソッドの基本を理解することが大切です。
Windows Formsでは、Graphicsを使って直線、円、四角形などを描画します。フォームやPictureBoxのPaintイベントで描くのが基本で、再描画しても図形が消えないようにするには、図形情報をリストで管理するか、Bitmapに描画して保持します。
WPFでは、CanvasにLine、Rectangle、Ellipseなどの図形オブジェクトを配置して描画します。Canvasは図形を部品として扱えるため、あとから位置や色を変更しやすいのが特徴です。
C#の図形描画では、直線ならDrawLine、四角形ならDrawRectangle、円や楕円ならDrawEllipseを使います。塗りつぶしにはFillRectangleやFillEllipseを使います。
マウス操作を組み合わせれば、クリックした位置に図形を描いたり、ドラッグ範囲に四角形や円を描いたりできます。さらに、アンチエイリアス、線の太さ、破線、半透明、重なり順などを調整すれば、見た目のよい図形描画アプリを作れます。
初心者は、まずWindows FormsのPaintイベントで直線・円・四角形を描くところから始めるのがおすすめです。基本が理解できたら、Bitmapへの描画、画像保存、WPFのCanvas、マウス操作による描画へと少しずつステップアップしていきましょう。

