[C# Windowsフォームアプリ] 論文中のグラフから値を読み取る

# 本記事の内容
* 論文のグラフから値を読み取る自作アプリを作成することが目標(下図)
* Windowsフォームアプリ(C#)を使用


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368893/bb9e5c01-f533-e83e-1223-13af167f096c.png)
画像を読み込む&rarr;マウスで点をクリックしていく&rarr;画像のピクセル座標をRichTextBoxに表示させる


# 方法(要点まとめ)
### (1) コントロールの配置と設定
1\.Button, Label, TextBox, RichTextBox, Panel, PictureBoxを配置する。PanelはPictureBoxの下に配置する。Panelを使用すると、画像サイズがフォームのウィンドウサイズより大きい場合に、縦方向と横方向のスクロールバーを表示させることができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368893/a4024f68-7067-a1b2-289c-e1b26c529c9d.png)

2\. 画像がはみ出た場合にスクロールして表示させるために、PanelのAutoScrollをTrueにし、PictureBoxのSizeModeをAutoSizeにする。Visual Studioの右下に表示される各コントロールのプロパティから設定してもよいし、コードで直接入力してもよい。`public Form1(){...}`のところに記述する。
~~~c#
// Panelのプロパティ設定
panel1.AutoScroll = true;
// PictureBoxをPanel内に追加
panel1.Controls.Add(pictureBox1);
// PictureBoxのサイズモード設定
pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
~~~


### (2) マウスをクリックしたときに、座標を読み取り、点を描画する。
あらかじめ諸々の変数を定義しておく。`public partial class Form1 : Form{...`の直後に入力する。
~~~c#
private Image originalImage;
private Image temporaryImage;
private List<Point> clickedPoints = new List<Point>();
private int dotCount = 0;
~~~
#### pictureBoxの重要な設定はこんな感じ
1\. MouseClickイベントを使って、クリックしたらその場所の座標をclickedPointsリストに追加していく（点の描画用）。RichTextBoxにもAppendTextで現在の点を追加する。ついでにクリックした総カウント数もdotCount変数に記録していく。
2\. PainイベントでclickedPointsに記録した点をプロットする。
~~~c#
// リスト内のすべての点に赤い円を描画
foreach (Point p in clickedPoints)
{
  e.Graphics.FillEllipse(Brushes.Red, p.X - 5, p.Y - 5, 10, 10);
}
~~~
3\. MouseMoveイベントで、現在のマウスの座標をラベルにリアルタイムで表示する。
~~~c#
label2.Text = e.Location.ToString();
~~~


# コード全体
~~~c#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace Counter
{
    public partial class Form1 : Form
    {
        private Image originalImage;
        private Image temporaryImage;
        private List<Point> clickedPoints = new List<Point>();
        private int dotCount = 0;

        public Form1()
        {
            InitializeComponent();

            // Panelのプロパティ設定
            panel1.AutoScroll = true;
            // PictureBoxをPanel内に追加
            panel1.Controls.Add(pictureBox1);
            // PictureBoxのサイズモード設定
            pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
        }



        private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
        {
            clickedPoints.Add(e.Location); // クリックされた位置をリストに追加
            pictureBox1.Invalidate(); // PictureBoxを再描画

            // RichTextBoxに座標を追加
            Point pointforRT = e.Location;
            richTextBox1.AppendText($"{pointforRT.X}   {pointforRT.Y}\n");

            //カウント
            dotCount++;
            txtBoxCount.Text = dotCount.ToString();

        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            // リスト内のすべての点に赤い円を描画
            foreach (Point p in clickedPoints)
            {
                e.Graphics.FillEllipse(Brushes.Red, p.X - 5, p.Y - 5, 10, 10);
            }

            
        }

        

        private void btnReadImg_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "画像ファイル(*.jpg;*.png;*.bmp;*.tif)|*.jpg;*.png;*.bmp;*.tif";
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    originalImage = Image.FromFile(openFileDialog.FileName);
                    temporaryImage = new Bitmap(originalImage);
                    pictureBox1.Image = new Bitmap(originalImage);
                }
            }
        }

        private void btnReset_Click(object sender, EventArgs e)
        {
            if (originalImage != null)
            {
                pictureBox1.Image = new Bitmap(originalImage);
            }
            clickedPoints.Clear(); // プロットのリストをクリア
            pictureBox1.Invalidate(); // PictureBoxを再描画
            richTextBox1.Clear();
            txtBoxCount.Clear();
            dotCount = 0;
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            label2.Text = e.Location.ToString();
        }
    }
}

~~~