| 基本図形の描画 |
先ずは基本図形を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#で、デスクトップ全体を透明のレイヤーでお絵描きをするツールを有料でも構いませんので、開発していただくことは可能でしょうか?多くの公開されているフリーソフトのように、デスクトップをキャプチャしてからその静止画の上に、お絵描きをするのではなく、リアルタイムのビデオ動画を再生しているデスクトップ画面上に、リアルタイムで自由線でお絵描きが出来るツールを作っていただけますでしょうか?