C# マウス操作で基本図形描画

基本図形の描画 

 先ずは基本図形をpictureBox上に描画します。
 下図はpictureBoxに写真を呼び込んだ状態です。写真の上に描画します。


 “基本図形”ボタンを押すと下図の様に長方形,楕円,円(塗り潰し)を描画します。


 “スプライン曲線”ボタンを押すと下図の通り、予めプログラム内に入力してある座標に基づき曲線を描きます。

 以上の描画に関する内容は、〔dobon.net〕様ホームページを参考にさせて頂きました。
 〔dobon.net〕https://dobon.net/vb/dotnet/graphics/index.html

 

マウスドラッグ&ドロップ描画

 次にマウスドラッグ&ドロップを使って、楕円を描画します。下の図の黒い点線の長方形はマウスドラッグ領域を表しています。左上角部が視点で右下角部がドラッグ中のマウスカーソル位置となります。

 終点を確定し、ドロップする(マウスを離す)と領域が確定し、下図の通り楕円を描画します。

 

マウスイベント

 今回、下記3つのマウスイベントを使用しています。マウスダウン(ドラッグ開始)時に、変数(draw_flag )を‘true’にし、マウスアップ(ドロップ)時に変数を‘false’に戻すことで、3つの処理を一連の動作として処理します。
 各イベント発生時にコントロール上の座標を取得出来るので、マウスダウン(ドラッグ開始)時の座標を始点、マウスアップ(ドロップ)時の座標を終点として、2点を対角とする長方形内に収まる楕円を描画します。
 マウスダウンとマウスアップの間に発生するマウスムーブイベント時は、選択範囲を示す黒い点線の長方形を連続的に更新しています。

表:使用するpictureBoxのマウスイベント

No イベント 内  容
1 MouseDown マウスクリック(ドラッグ開始)時発生
2 MouseMove マウス移動中(ドラッグ中)連続的に発生。
3 MouseUp ドロップ時(マウスボタンを離す)に発生。

 

pictureBox構成

 外観上の描画領域は1つですが、実際には3つのpictureBoxを重ねて1つの描画領域を構成しています。最下層(pictureBox1)は、コメントやマーク等を追加したい写真等を表示します。実際に描画は行いません。
最上層(pictureBox3)はドラッグ&ドロップ中の描画に関する一時的な情報を描画します。
中間層(pictureBox2)はドロップ時の確定情報を、既に中間層に書かれている内容に追加し、描画します。

 

プログラム

 プログラムです。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ListViewTest
{
    public partial class Frm_01 : Form
    {

        bool draw_flag = false;
        Point mus_dn = new Point();

        public Frm_01()
        {
            InitializeComponent();
        }

        private void Frm_01_Load(object sender, EventArgs e)
        {
            pictureBox1.SizeMode=PictureBoxSizeMode.StretchImage;
            pictureBox1.ImageLocation = @"";//pictureBox1に格納する画像パス
         
            // pictureBox1に対し、PictureBox2を透明化する処理
            pictureBox2.Parent = pictureBox1;
            pictureBox2.BackColor = Color.Transparent;

            // 元のParent(Form)に対する座標を補正する
            pictureBox2.Location = new Point(pictureBox2.Location.X-pictureBox1.Location.X, pictureBox2.Location.Y - pictureBox1.Location.Y);
            pictureBox2.Size = pictureBox1.Size;

            // pictureBox1に対し、PictureBox2を透明化する処理
            pictureBox3.Parent = pictureBox2;
            pictureBox3.BackColor = Color.Transparent;

            // 元のParent(Form)に対する座標を補正する
            pictureBox3.Location = new Point(pictureBox3.Location.X - pictureBox1.Location.X, pictureBox3.Location.Y - pictureBox1.Location.Y);
            pictureBox3.Size = pictureBox2.Size;
        }


        // 画面リセット
        private void button1_Click(object sender, EventArgs e)
        {
            pictureBox2.Image = null;
        }

        // 基本図形描画
        private void button2_Click(object sender, EventArgs e)
        {
            pictureBox2.Image = null;

            int pic_w = pictureBox2.Width;
            int pic_h = pictureBox2.Height;
            int pic_margin = 5;

            int rect_w = pic_w - 2 * pic_margin - 1;
            int rect_h = pic_h - 2 * pic_margin - 1;

            int crcl_x = pic_w / 2 - rect_h / 2;


            Bitmap cvs = new Bitmap(pic_w, pic_h);
            Graphics g = Graphics.FromImage(cvs);

            Pen p1 = new Pen(Color.Blue, 2);                                    // 長方形の線色指定
            Pen p2 = new Pen(Color.FromArgb(128, 255, 0, 0), 10);               // 楕円の線色指定
            SolidBrush b1 = new SolidBrush(Color.FromArgb(128, 0, 255, 0));     // 円の塗り潰し色
            
            g.DrawRectangle(p1, pic_margin, pic_margin, rect_w, rect_h);        // 長方形(始点と幅,高さ指定)
            g.DrawEllipse(p2, pic_margin, pic_margin, rect_w, rect_h);          // 楕円(指定は長方形と同じ)
            g.FillEllipse(b1, crcl_x, pic_margin, rect_h, rect_h);              // 円(塗り潰し色)

            p1.Dispose();
            p2.Dispose();
            b1.Dispose();

            g.Dispose();

            pictureBox2.Image = cvs;
        }


        // スプライン曲線
        private void button3_Click(object sender, EventArgs e)
        {
            pictureBox2.Image = null;

            int pic_w = pictureBox2.Width;
            int pic_h = pictureBox2.Height;

            Bitmap cvs = new Bitmap(pic_w, pic_h);
            Graphics g = Graphics.FromImage(cvs);

            Point p01 = new Point(60, 40);
            Point p02 = new Point(120, 300);
            Point p03 = new Point(240, 60);
            Point p04 = new Point(400, 280);
            Point p05 = new Point(440, 200);
            Point p06 = new Point(380, 120);

            Point[] c_points = { p01,p02,p03,p04,p05,p06 };

            Pen p_b = new Pen(Color.FromArgb(80, 0, 0, 255), 10);
            Pen p_r = new Pen(Color.FromArgb(80, 255, 0, 0), 10);
            Pen p_g = new Pen(Color.FromArgb(80, 0, 255, 0), 10);

            // カーディナルスプライン(0~1設定,Default:0.5, 直線:0)
            g.DrawCurve(p_b , c_points , 0.5F);
            g.DrawCurve(p_r, c_points, 1);
            g.DrawClosedCurve(p_g, c_points, 1, FillMode.Alternate);

            p_b.Dispose();
            p_r.Dispose();
            p_g.Dispose();
            g.Dispose();

            pictureBox2.Image = cvs;

        }

      
        // マウスドラッグ
        private void pictureBox3_MouseDown(object sender, MouseEventArgs e)
        {
            draw_flag = true;
            mus_dn.X = e.X;
            mus_dn.Y = e.Y;
        }

        // マウスドラッグ中
        private void pictureBox3_MouseMove(object sender, MouseEventArgs e)
        {
            if (!draw_flag) { return; };

            Bitmap tmp_cvs = new Bitmap(pictureBox3.Width, pictureBox3.Height);
            Graphics tmp_g = Graphics.FromImage(tmp_cvs);
            Point tmp_mv = new Point();
            Pen tmp_p = new Pen(Color.FromArgb(255, 0, 0, 0), 1);
            tmp_p.DashStyle = DashStyle.Dot;

 
            if (e.X - mus_dn.X >= 0) { tmp_mv.X = mus_dn.X; } else { tmp_mv.X = e.X; }  // 始点修正(X)
            if (e.Y - mus_dn.Y >= 0) { tmp_mv.Y = mus_dn.Y; } else { tmp_mv.Y = e.Y; }  // 始点修正(Y)

            int tmp_wdt = Math.Abs(e.X - mus_dn.X);                                     // 幅(X)         
            int tmp_hgt = Math.Abs(e.Y - mus_dn.Y);                                     // 幅(Y)

            tmp_g.DrawRectangle(tmp_p, tmp_mv.X, tmp_mv.Y, tmp_wdt, tmp_hgt);
            pictureBox3.Image = tmp_cvs;
            
        }

        // マウスドロップ
        private void pictureBox3_MouseUp(object sender, MouseEventArgs e)
        {
            if (!draw_flag) { return; };
            pictureBox3.Image=null;

            Bitmap tmp_cvs = new Bitmap(pictureBox2.Width, pictureBox2.Height);
            Graphics tmp_g = Graphics.FromImage(tmp_cvs);

            Image img = pictureBox2.Image ;

            Point tmp_mv = new Point();
            Pen tmp_p = new Pen(Color.FromArgb(80, 255, 0, 0), 10);

            if (e.X - mus_dn.X >= 0) { tmp_mv.X = mus_dn.X; } else { tmp_mv.X = e.X; }  // 始点修正(X)
            if (e.Y - mus_dn.Y >= 0) { tmp_mv.Y = mus_dn.Y; } else { tmp_mv.Y = e.Y; }  // 始点修正(Y)

            int tmp_wdt = Math.Abs(e.X - mus_dn.X);                                     // 幅(X)         
            int tmp_hgt = Math.Abs(e.Y - mus_dn.Y);                                     // 幅(Y)

            if (img != null) { tmp_g.DrawImage(img, 0, 0, img.Width, img.Height); }
            tmp_g.DrawEllipse(tmp_p, tmp_mv.X, tmp_mv.Y, tmp_wdt, tmp_hgt);
            pictureBox2.Image = tmp_cvs;

            draw_flag = false;
        }
    }
}

 

まとめ

 次回は引き続き、自由曲線(?)描画を検討する予定です。

「C# マウス操作で基本図形描画」への1件のフィードバック

  1. はじめてお問い合わせさせていただきます。
    C#で、デスクトップ全体を透明のレイヤーでお絵描きをするツールを有料でも構いませんので、開発していただくことは可能でしょうか?多くの公開されているフリーソフトのように、デスクトップをキャプチャしてからその静止画の上に、お絵描きをするのではなく、リアルタイムのビデオ動画を再生しているデスクトップ画面上に、リアルタイムで自由線でお絵描きが出来るツールを作っていただけますでしょうか?

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です