////////////////////
//C# PictureBox.cs
////////////////////
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Reflection;				//Assemblyを使う為
using Atelier;							//Atelier.dllを使う

namespace WindowsFormsApp
{
	public partial class AppForm : Form
	{
		Panel panel;						//ピクチャー（ボックス）の枠となるPanel
		PictureBox picBox;					//ピクチャーボックスコントロール
		Button btn1, btn2, btn3, extbtn;	//ボタンコントロール
		Easel easel;						//描画を行うEaselオブジェクト

		[STAThread]
		public static void Main()
		{
			AppForm ap = new AppForm();
			Application.Run(ap);
		}

		public AppForm()
		{
			Assembly myOwn = Assembly.GetEntryAssembly();
			this.Icon = Icon.ExtractAssociatedIcon(myOwn.Location);	//プログラムアイコンをフォームにつける
			this.Size = new Size(640, 540);
			this.MinimumSize = new Size(320, 190);
			this.Text = "PictureBox";
			this.Load += AppForm_Load;
		}

		private void AppForm_Load(object sender, EventArgs e)
		{
			//ボタン1
			btn1 = new Button();
			btn1.Location = new Point(ClientSize.Width - btn1.Width - 10, 10);
			btn1.Text = "葉模様";
			btn1.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
			btn1.Click += Button1_Click;
			this.Controls.Add(btn1);

			//ボタン2ボタン
			btn2 = new Button();
			btn2.Location = new Point(ClientSize.Width - btn2.Width - 10, btn1.Height + 20);
			btn2.Text = "多様な曲線";
			btn2.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
			btn2.Click += Button2_Click;
			this.Controls.Add(btn2);

			//ボタン3ボタン
			btn3 = new Button();
			btn3.Location = new Point(ClientSize.Width - btn3.Width - 10, btn1.Height + btn2.Height + 30);
			btn3.Text = "ベジエ曲線";
			btn3.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
			btn3.Click += Button3_Click;
			this.Controls.Add(btn3);

			//終了ボタン
			extbtn = new Button();
			extbtn.Location = new Point(ClientSize.Width - extbtn.Width - 10, ClientSize.Height - extbtn.Height - 20);
			extbtn.Text = "終了";
			extbtn.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right);
			extbtn.Click += Button4_Click;
			this.Controls.Add(extbtn);

			//描画先とするEaselオブジェクトを作成する（同時にGraphics、Pen、Brushオブジェクトも作成する）
			easel = new Easel();
			//ピクチャーボックスコントロール in パネル
			panel = new Panel();		//フレームとなるPanelオブジェクトの作成
			panel.BorderStyle = BorderStyle.Fixed3D;
			panel.Location = new Point(10, 10);
			panel.Width = ClientSize.Width - btn1.Width - 30;
			panel.Height = ClientSize.Height - 20;
			panel.AutoScroll = true;	//スクロールバー付
			panel.Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right);
			picBox = new PictureBox();	//枠の中のPictureオブジェクトの作成
			picBox.Location = new Point(0, 0);				//枠内の位置
			picBox.SizeMode = PictureBoxSizeMode.AutoSize;	//画像サイズでPictureBoxの大きさが変更される
			picBox.Image = easel.Canvas;					//easelのCanvasを貼る
			picBox.Click += Panel_Click;
			panel.Controls.Add(picBox);						//picBoxをpanelの子にする
			//FormにTPictureBox入りのPanelを追加
			this.Controls.Add(panel);

			MessageBox.Show("画面を消去するにはマウスでクリックしてください。", "画面消去");
		}

		//終了処理
		protected override void OnFormClosing(FormClosingEventArgs e)
		{
			base.OnFormClosing(e);
			DialogResult dr = MessageBox.Show("終了しますか？", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
			if(dr == DialogResult.No)
			{
				e.Cancel = true;
			}
			else
				//PictureBoxのマネージド リソースとアンマネージド リソースを解放
				picBox.Dispose();
		}

		private void Button1_Click(object sender, EventArgs e)
		{
			//ボタン1
			//ランダムな色を作成する
			Random r = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);	//毎回異なるシードで乱数を発生させる
			double X = 0, Y = 0, Xp, Yp, xx, yy;
			int n, i;
			for(i = 1; i <= 100000; i++)
			{
				n = r.Next(0, 100);
				if(n < 1)
				{
					Xp = 0;
					Yp = 0.16 * Y;
				}
				else if(n >= 1 && n <= 8)
				{
					Xp = 0.2 * X - 0.26 * Y;
					Yp = 0.23 * X + 0.22 * Y + 1.6;
				}
				else if(n >= 8 && n <= 15)
				{
					Xp = -0.15 * X + 0.28 * Y;
					Yp = 0.26 * X + 0.24 * Y + 0.44;
				}
				else
				{
					Xp = 0.85 * X + 0.04 * Y;
					Yp = -0.04 * X + 0.85 * Y + 1.6;
				}
				X = Xp;
				Y = Yp;
				xx = X * 45;
				yy = Y * 45 -225;
				easel.gFtColor = Color.FromArgb(r.Next(0, 256), r.Next(0, 256), r.Next(0, 256));
				easel.Dot((int)(xx + 240), (int)(-yy + 240));
			}
			//PictureBoxに表示する
			picBox.Image = easel.Canvas;
		}

		private void Button2_Click(object sender, EventArgs e)
		{
			//ボタン2 - Phase 1
			//ランダムな4点を作成する
			Random r = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);	//毎回異なるシードで乱数を発生させる
			Point[] pts = {	new Point(0 + r.Next(0, picBox.ClientSize.Width / 4), 0 + r.Next(0, picBox.ClientSize.Height / 4)),
							new Point(100 + r.Next(0, picBox.ClientSize.Width / 4), 200 + r.Next(0, picBox.ClientSize.Height / 4)),
							new Point(200 + r.Next(0, picBox.ClientSize.Width / 4), 50 + r.Next(0, picBox.ClientSize.Height / 4)),
							new Point(300 + r.Next(0, picBox.ClientSize.Width / 4), 100 + r.Next(0, picBox.ClientSize.Height / 4)),
			};
			//ペンの作成
			Pen pen = new Pen(Color.Black, 1);
			//easel.gHandleを使ったGDI+による曲線描画
			easel.gHandle.DrawCurve(pen, pts, 0F);
			pen.Color = Color.Blue;
			easel.gHandle.DrawCurve(pen, pts, 0.5F);
			pen.Color = Color.Green;
			easel.gHandle.DrawCurve(pen, pts, 1F);
			pen.Color = Color.Red;
			easel.gHandle.DrawCurve(pen, pts, 2F);
			//ペンの解放
			pen.Dispose();
			//PictureBoxに表示する
			picBox.Image = easel.Canvas;
			//ボタン2 - Phase 2
			//曲線が通過するランダムな5点の配列を作成する（最低でも3つ以上必要）
			Point[] curvePoints = new Point[5];
			for(int i = 0; i < 5; i++)
			{
				curvePoints[i] = new Point(r.Next(0, panel.ClientSize.Width), r.Next(0, panel.ClientSize.Height));
			}
			//曲線が通過する点の配列を作成する。最低でも3つ以上の点が必要。
			//Point point1 = new Point(30, 20);
			//Point point2 = new Point(60, 150);
			//Point point3 = new Point(120, 30);
			//Point point4 = new Point(200, 140);
			//Point point5 = new Point(220, 100);
			//Point point6 = new Point(190, 60);
			//Point[] curvePoints = { point1, point2, point3, point4, point5, point6 };
			//幅3の青色のPenオブジェクトを作成
			Pen bluePen = new Pen(Color.Blue, 3);
			//テンション0.5（既定値）のカーディナルスプラインを描画
			easel.gHandle.DrawCurve(bluePen, curvePoints, 0.5F);
			//幅3の赤色のPenオブジェクトを作成
			Pen redPen = new Pen(Color.Red, 3);
			//テンション1のカーディナルスプラインを描画
			easel.gHandle.DrawCurve(redPen, curvePoints, 1);
			//幅3の緑色のPenオブジェクトを作成
			Pen greenPen = new Pen(Color.Green, 3);
			//テンション0のカーディナルスプライン（直線となる）を描画
			easel.gHandle.DrawCurve(greenPen, curvePoints, 0);
			//幅1の黄色のPenオブジェクトを作成
			Pen yellowPen = new Pen(Color.Yellow, 1);
			//2番目の点から5番目の点までを通過するカーディナルスプラインを描画
			easel.gHandle.DrawCurve(yellowPen, curvePoints, 1, 3, 0.5F);
			//幅1の黒色のPenオブジェクトを作成
			Pen blackPen = new Pen(Color.Black, 1);
			//テンション1の閉じたカーディナルスプラインを描画
			easel.gHandle.DrawClosedCurve(blackPen, curvePoints, 1, FillMode.Alternate);
			//リソースを解放する
			bluePen.Dispose();
			redPen.Dispose();
			greenPen.Dispose();
			yellowPen.Dispose();
			blackPen.Dispose();
			//PictureBoxに表示する
			picBox.Image = easel.Canvas;
		}

		private void Button3_Click(object sender, EventArgs e)
		{
			//ボタン3
			//曲線が通過するランダムな5点の配列を作成する（最低でも3つ以上必要）
			Random r = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);	//毎回異なるシードで乱数を発生させる
			Point[] bezierPoints = new Point[7];
			for(int i = 0; i < 7; i++)
			{
				bezierPoints[i] = new Point(r.Next(0, panel.ClientSize.Width), r.Next(0, panel.ClientSize.Height));
			}
			//ベジエ曲線の形状を決定する点
			//Point start = new Point(10, 70);
			//Point control1 = new Point(50, 10);
			//Point control2 = new Point(80, 30);
			//Point end1 = new Point(130, 60);
			//Point control3 = new Point(190, 70);
			//Point control4 = new Point(200, 120);
			//Point end2 = new Point(170, 160);
			//Point[] bezierPoints = { start, control1, control2, end1, control3, control4, end2 };
			//幅1の黒色のPenオブジェクトを作成
			Pen blackPen = new Pen(Color.Black, 1);
			//矢印をつける
			blackPen.EndCap = LineCap.ArrowAnchor;
			//ベジエ曲線に接する直線を描画
			easel.gHandle.DrawLine(blackPen, bezierPoints[0], bezierPoints[1]);
			easel.gHandle.DrawLine(blackPen, bezierPoints[2], bezierPoints[3]);
			easel.gHandle.DrawLine(blackPen, bezierPoints[3], bezierPoints[4]);
			easel.gHandle.DrawLine(blackPen, bezierPoints[5], bezierPoints[6]);
			//幅1の青色のPenオブジェクトを作成
			Pen bluePen = new Pen(Color.Blue, 1);
			//ベジエスプラインを描画する
			easel.gHandle.DrawBeziers(bluePen, bezierPoints);
			//リソースを解放する
			blackPen.Dispose();
			bluePen.Dispose();
			//PictureBoxに表示する
			picBox.Image = easel.Canvas;
		}

		private void Button4_Click(object sender, EventArgs e)
		{
			//終了処理
			Close();
		}

		private void Panel_Click(object sender, EventArgs e)
		{
			MouseEventArgs mouseArgs = e as MouseEventArgs;
			Point p = panel.PointToClient(Cursor.Position);
			string str = String.Format("MouseClick at (x = {0}, y = {1})", p.X.ToString(), p.Y.ToString());
			string title = "";
			if(mouseArgs.Button == MouseButtons.Left)
				title = "Mouse Left Click Position in Client Area";
			else if(mouseArgs.Button == MouseButtons.Right)
				title = "Mouse Right Click Position in Client Area";
			else
				title = "Mouse Click Position in Client Area";
			MessageBox.Show(str, title);
			easel.Clear();
			//PictureBoxに表示する
			picBox.Image = easel.Canvas;
		}
	}
}
