基本図形の描画 |
先ずは基本図形を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; } } }
まとめ |
次回は引き続き、自由曲線(?)描画を検討する予定です。