C#でフリーハンドで線を引く

C# コンピュータ
C#

線を引く機能とマウスの移動イベントを組み合わせると、ペイントソフトのフリーハンドで線を引く機能のようなものが作れるので試してみました。

事前準備

線を引くサンプル

ソース

ファイル名:drawline.cs

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;

/*
 線を引く
*/

class Program
{
    [STAThread]
    static void Main()
    {
        Application.Run(new Form1());
    }
}

class Form1 : Form
{
    // ピクチャボックスコントロール
    PictureBox picbox = new PictureBox();
        
    // コンストラクタ
    public Form1()
    {
        // 800x600のカラービットマップオブジェクトを生成
        var bitmap = new Bitmap(800, 600, PixelFormat.Format32bppArgb);
        
        // ビットマップオブジェクトからグラフィックオブジェクトを取得
        using (var graphics = Graphics.FromImage(bitmap))
        {
            // 開始位置
            var startPoint = new Point(0,0);
            // 終了位置
            var endPoint = new Point(799,599);
            // 黒色で開始位置から終了位置へ直線を引く
            graphics.DrawLine(Pens.Black, startPoint, endPoint);
        }
        
        // ビットマップをピクチャボックスに割り当て
        picbox.Image = bitmap;
        
        // コントロールをフォームに登録
        this.Controls.Add(picbox);
            
        // イベントを追加
        this.Load += Form1_Load;
        this.Resize += Form1_Resize;
    }
    
    // フォームロードイベント
    private void Form1_Load(object sender, EventArgs e)
    {
        Form1_Resize(sender, e);
    }
    // フォームリサイズイベント
    private void Form1_Resize(object sender, EventArgs e)
    {
        // コントロールをフォーム一杯に広げる
        picbox.Size = this.ClientSize;
    }
        
}

コンパイル

Powershellで実行

PS>csc drawline.cs

実行

Powershellで実行

PS>.\drawline

説明

成功すると斜めの線が引かれるはずです。実際線を引くメソッドはDrawLine(ペン、開始位置、終了位置)でペンは既存の黒色を使いました。

フリーハンドで線を引く

ソース

ファイル名:freehand.cs

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;

/*
 フリーハンドで線を引く
*/

class Program
{
    [STAThread]
    static void Main()
    {
        Application.Run(new Form1());
    }
}

class Form1 : Form
{
    // ピクチャボックスコントロール
    PictureBox picbox = new PictureBox();
    
    // マウス位置
    Point LastMousePoint;
    
    // 描画フラグ
    bool DrawingFlag = false;
    
    // コンストラクタ
    public Form1()
    {
        // 800x600のカラービットマップオブジェクトを生成
        var bitmap = new Bitmap(800, 600, PixelFormat.Format32bppArgb);
        
        // ビットマップをピクチャボックスに割り当て
        picbox.Image = bitmap;
        
        // コントロールをフォームに登録
        this.Controls.Add(picbox);
            
        // イベントを追加
        this.Load += Form1_Load;
        this.Resize += Form1_Resize;
        
        picbox.MouseDown += Picbox_MouseDown;
        picbox.MouseUp += Picbox_MouseUp;
        picbox.MouseMove += Picbox_MouseMove;
    }
    
    // フォームロードイベント
    private void Form1_Load(object sender, EventArgs e)
    {
        Form1_Resize(sender, e);
    }
    // フォームリサイズイベント
    private void Form1_Resize(object sender, EventArgs e)
    {
        // コントロールをフォーム一杯に広げる
        picbox.Size = this.ClientSize;
    }
    
    // ピクチャボックスマウスボタン押し込み
    private void Picbox_MouseDown(object sender, MouseEventArgs e)
    {
        // フラグOn
        DrawingFlag = true;
        
        // マウスの位置を記憶
        LastMousePoint = new Point(e.X, e.Y);
    }
    // ピクチャボックスマウスボタン解放
    private void Picbox_MouseUp(object sender, MouseEventArgs e)
    {
        // フラグOff
        DrawingFlag = false;
        
    }
    // ピクチャボックスマウス移動
    private void Picbox_MouseMove(object sender, MouseEventArgs e)
    {
        // 描画中でない場合即戻る
        if (DrawingFlag == false)
        {
            return;
        }

        // ビットマップオブジェクトからグラフィックオブジェクトを取得
        using (var graphics = Graphics.FromImage(picbox.Image))
        {
            // 開始位置
            var startPoint = LastMousePoint;
            // 終了位置
            var endPoint = new Point(e.X, e.Y);
            // 黒色で開始位置から終了位置へ直線を引く
            graphics.DrawLine(Pens.Black, startPoint, endPoint);
        }
        // ピクチャボックスの再描画
        picbox.Refresh();

        // マウスの位置を記憶
        LastMousePoint = new Point(e.X, e.Y);
    }
}

コンパイル

Powershellで実行

PS>csc freehand.cs

実行

Powershellで実行

PS>.\freehand

使い方

ピクチャボックス上でマウスをクリックすると開始しマウスを動かすと線が引かれます。マウスをボタンを解放すると停止します。

説明

マウスの移動イベントで座標を拾い、前回のマウスの座標と今回の座標を線で結ぶことでフリーハンドで線を引く機能を実現させています。

フリーハンドで線を引く(スクロールバー付き)

ソース

ファイル名:freehand2.cs

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;

/*
 フリーハンドで線を引く(スクロールバー付き)
*/

class Program
{
    [STAThread]
    static void Main()
    {
        Application.Run(new Form1());
    }
}

class Form1 : Form
{
    // ピクチャボックスコントロール
    PictureBox picbox = new PictureBox();
    
    // パネルコントロール
    Panel panel = new Panel();
    
    // マウス位置
    Point LastMousePoint;
    
    // 描画フラグ
    bool DrawingFlag = false;
    
    // コンストラクタ
    public Form1()
    {
        // パネルにスクロールバーをつける
        panel.AutoScroll = true;
        
        // ピクチャボックスのサイズ変更モード
        picbox.SizeMode = PictureBoxSizeMode.AutoSize;
        picbox.Location = new Point(0, 0);
        
        // 800x600のカラービットマップオブジェクトを生成
        var bitmap = new Bitmap(800, 600, PixelFormat.Format32bppArgb);
        
        // ビットマップをピクチャボックスに割り当て
        picbox.Image = bitmap;
        
        // コントロールをフォームに登録
        panel.Controls.Add(picbox);
        this.Controls.Add(panel);
            
        // イベントを追加
        this.Load += Form1_Load;
        this.Resize += Form1_Resize;
        
        picbox.MouseDown += Picbox_MouseDown;
        picbox.MouseUp += Picbox_MouseUp;
        picbox.MouseMove += Picbox_MouseMove;
    }
    
    // フォームロードイベント
    private void Form1_Load(object sender, EventArgs e)
    {
        Form1_Resize(sender, e);
    }
    // フォームリサイズイベント
    private void Form1_Resize(object sender, EventArgs e)
    {
        // コントロールをフォーム一杯に広げる
        picbox.Size = this.ClientSize;
        panel.Size = this.ClientSize;
    }
    
    // ピクチャボックスマウスボタン押し込み
    private void Picbox_MouseDown(object sender, MouseEventArgs e)
    {
        // フラグOn
        DrawingFlag = true;
        
        // マウスの位置を記憶
        LastMousePoint = new Point(e.X, e.Y);
    }
    // ピクチャボックスマウスボタン解放
    private void Picbox_MouseUp(object sender, MouseEventArgs e)
    {
        // フラグOff
        DrawingFlag = false;
        
    }
    // ピクチャボックスマウス移動
    private void Picbox_MouseMove(object sender, MouseEventArgs e)
    {
        // 描画中でない場合即戻る
        if (DrawingFlag == false)
        {
            return;
        }

        // ビットマップオブジェクトからグラフィックオブジェクトを取得
        using (var graphics = Graphics.FromImage(picbox.Image))
        {
            // 開始位置
            var startPoint = LastMousePoint;
            // 終了位置
            var endPoint = new Point(e.X, e.Y);
            // 黒色で開始位置から終了位置へ直線を引く
            graphics.DrawLine(Pens.Black, startPoint, endPoint);
        }
        // ピクチャボックスの再描画
        picbox.Refresh();

        // マウスの位置を記憶
        LastMousePoint = new Point(e.X, e.Y);
    }
}

コンパイル

Powershellで実行

PS>csc freehand2.cs

実行

Powershellで実行

PS>.\freehand2

使い方

スクロールバーのつまみを操作することでスクロール可能

説明

ピクチャボックスのマウスの移動イベントで拾えるマウスの座標は、ピクチャボックスのクライアント領域から見た座標ではなく、画像全体から見た座標になります。ピクチャボックスにスクロールバーをつけてスクロールさせた場合でも特別座標計算の必要がないのが、大変ありがたいです。

コメント