C#自作アプリ【初心者】

# C#自作アプリ

Visual studio2022(.net 6.0)のみでスケジュール表みたいなアプリを作ってみました。
C#は初見でしたが自分なりに頑張って、それなりの出来になったと思います。
苦労した点や使った関数、ツール、考え方などを投稿していこうと思います。


### 初めに
自分はC言語認定試験一級に合格していて、コンソールアプリはある程度作れて仕組みもなんとなく理解出来ています。
しかし、GUIのようなアプリをどうやって作ればいいのかわからなくて途方に暮れました笑
色々調べてたら何故かとある海外のサイトとVisual studio 2022にたどり着き、
そこのyoutubeの内容を見よう見まねで作り始めました。
[参考にしたサイト]↓

https://rjcodeadvance.com/iu-moderno-temas-multicolor-aleatorio-resaltar-boton-form-activo-winform-c/#google_vignette

:::note warn
自分はプログラミングの学習はほとんど独学なので
用語の使い方を間違えてる可能性が高いです:bow_tone1:
:::

### アプリ全体像
きっかけはR5秋期応用情報技術の勉強をしていて、
その勉強計画表をすべて紙で書いていました。
そこで計画表をアプリで管理出来たら便利そうだと思ったので計画表を作ろうと決めました。
これだけではすぐ完成しそうで面白くないのでタイマーと電卓も作ろうと決めました。

【スケジュール】
![スクリーンショット 2023-12-15 135540.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3641815/8bde6863-2f9c-9b39-d01d-af4cab5e93a1.png)

![スクリーンショット 2023-12-15 135734.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3641815/316ad5b8-e745-0a99-d441-ffe15ffd4dc1.png)
【タイマー】
![スクリーンショット 2023-12-15 135751.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3641815/a58b0fe5-5a47-13a9-96a3-1ce60b2d5e39.png)
【電卓】
![スクリーンショット 2023-12-15 140343.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3641815/e1a13df3-9ad3-f2f9-8f09-10df379dac09.png)
【エクスプローラ】
![スクリーンショット 2023-12-15 175424.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3641815/3801f155-bcb1-4356-ce50-9874bcf80b7d.png)


全体の完成したデザインはこんな感じです。
タイマーはカウント中であれば、
アプリを閉じた後もバックグラウンドで起動するようにしました
データはCSVファイルに保存します。

### 手順.1【親フォームの作成】
まず
作成するアプリのフォームが"スクジュール","タイマー","電卓"の3種類なのでこれら
を選択するための"親フォーム"が必要となります。
そこから"子フォーム"(スクジュール,タイマー,電卓)を選択させます。
Windowsフォームアプリ (.net 6.0)で新規作成します


※おそらく最初は設計をするところから入ると思いますが
一人で作成するのと最初はそこまで長いコードになると思ってなかったので
頭の中でイメージしながら作りました。。
![スクリーンショット 2023-12-15 143922.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3641815/1f20b2f1-6fe5-32ef-ad2a-a18ead1303d5.png)

このような形で配置します。
※背面にPANELを配置しDOCkをfillとします→[参考にしたサイト](https://rjcodeadvance.com/iu-moderno-temas-multicolor-aleatorio-resaltar-boton-form-activo-winform-c/)
nameはpanelDesktopPane

【親フォーム】
```c#:Form.cs
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using ABI.Windows.ApplicationModel.Activation;
using System.Diagnostics;
using studyapp.forms;

namespace studyapp
{
    public partial class Form1 : Form
    {


        public Form1()

        {
            InitializeComponent();
            random = new Random();//乱数を生成
            today();
        }
        
        //フィールド
        private Button currentButton; //押されたボタン
        private Random random; //押された後ボタンの背景色をランダムにするための乱数
        private int tempIndex; //ThemeColor.csの背景色リストのインデックス
        private Form activeForm;//起動させる子フォーム
        public Color color;//選択された背景色


        
        private void today()//今日の日付を取得(MM/DD)
        {
           label2.Text = dt.ToString("MM/dd");
        }


        
        private Color SelectThemeColor() //背景色を選択する
        {
            int index = random.Next(ThemeColor.readOnlycolor.Count);
            while (tempIndex == index)
            {
                index = random.Next(ThemeColor.readOnlycolor.Count);
            }
            tempIndex = index;
            string color = ThemeColor.readOnlycolor[index];
            return ColorTranslator.FromHtml(color);
        }


    

        private void ActivateButton(object btnSender)//押されたボタンの背景色を変更する
        {
            if (btnSender is Button button && button != currentButton)
              {
                    DisableButton();
                    color = SelectThemeColor();
                    currentButton = (Button)btnSender;
                    currentButton.BackColor = color;
                    currentButton.ForeColor = Color.White;
                
              }
        }

        private void DisableButton()//別のボタンが押された時,前のボタンの背景色を元に戻す
        {
            foreach (Button previousBtn in panelmenu.Controls.OfType<Button>())
                   {
                    previousBtn.BackColor = Color.FromArgb(47, 79, 79);//(DarkSlateGray)
                    previousBtn.ForeColor = Color.Gainsboro; 
                   }
        }



        private void OpenChildForm(Form childForm, object btnSender)//子フォームを開き、ボタンの背景色を変更
        {
           activeForm?.Close();
           
            ActivateButton(btnSender);
            activeForm = childForm;
            childForm.TopLevel = false;
            childForm.FormBorderStyle = FormBorderStyle.None;
            childForm.Dock = DockStyle.Fill;
            this.panelDesktopPane.Controls.Add(childForm);//親フォームのパネルのコントロールに追加
            this.panelDesktopPane.Tag = childForm;
            childForm.BringToFront();
            childForm.Show();//子フォームを表示


        }




        private void button1_Click(object sender, EventArgs e)//スケジュールフォームを開くボタンのクリック
        {
            if (renda_flag1 == false)
            {

                if (sche==true)
                {
                    return;
                }
                sche = true;
                time = false;
                calc = false;
                renda_flag1 = true;
                renda_flag2 = true;
                renda_flag3 = true;


                OpenChildForm(new forms.schedule(), sender);//new forms.〜に子フォームの名前を追加します。現時点ではここの関数は消しても大丈夫です
               
                timer1.Start();
            }
        }

        private void button2_Click(object sender, EventArgs e)//タイマーフォームを開くボタンのクリック
        {
            if (renda_flag2 == false)
            {
                if (time == true)
                {
                    return;
                }
                sche = false;
                time = true;
                calc = false;
                renda_flag1 = true;
                renda_flag2 = true;
                renda_flag3 = true;

                OpenChildForm(new forms.timer(), sender);//new forms.〜に子フォームの名前を追加します。現時点ではここの関数は消しても大丈夫です

                timer1.Start();
            }

        }

        private void button3_Click(object sender, EventArgs e)//電卓フォームを開くボタンのクリック
        {
            if (renda_flag3 == false)
            {
                if (calc == true)
                {
                    return;
                }
                sche = false;
                time = false;
                calc = true;
                renda_flag1 = true;
                renda_flag2 = true;
                renda_flag3 = true;

                OpenChildForm(new forms.Formcalc(), sender);//new forms.〜に子フォームの名前を追加します。現時点ではここの関数は消しても大丈夫です
                timer1.Start();
            }
        }



        private void timer1_Tick(object sender, EventArgs e)//連打できないように一定時間カウント
        {
            renda_flag1 = false;
            renda_flag2 = false;
            renda_flag3 = false;
            timer1.Stop();
        }
   }
}
```
バックグラウンドタイマーや他の機能を加えるともっとコードがややこしくなるので
順を追ってコードを投稿していきます。

### 手順.2【クラスの追加】
次に、画像の通りにソリューションエクスプローラーで作成したソリューションを右クリックして、クラス(ThemeColor.cs)を追加します。
これでボタン選択後ボタンの背景色を変更することが可能になります。

![スクリーンショット 2023-12-15 165004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3641815/b9ac87d8-6b5a-213a-b18a-220fbdede785.png)

```c#:ThemeColor.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace studyapp
{
    public static  class ThemeColor
    {
        public static Color PrimaryColor { get; set; }
        public static Color SecondaryColor { get; set; }
        public static List<string> ColorList = new List<string>() { "#3F51B5",
                                                                    "#009688",
                                                                    "#FF5722",
                                                                    "#607D8B",
                                                                    "#FF9800",
                                                                    "#9C27B0",
                                                                    "#2196F3",
                                                                    "#EA676C",
                                                                    "#E41A4A",
                                                                    "#5978BB",
                                                                    "#018790",
                                                                    "#0E3441",
                                                                    "#00B0AD",
                                                                    "#721D47",
                                                                    "#EA4833",
                                                                    "#EF937E",
                                                                    "#F37521",
                                                                    "#A12059",
                                                                    "#126881",
                                                                    "#8BC240",
                                                                    "#364D5B",
                                                                    "#C7DC5B",
                                                                    "#0094BC",
                                                                    "#E4126B",
                                                                    "#43B76E",
                                                                    "#7BCFE9",
                                                                    "#B71C46"};

    public static ReadOnlyCollection<string> readOnlycolor =new ReadOnlyCollection<string>(ColorList);//カラーリスト(colorlist)を参照するもの
    }
}
```
※LISTはどうやらその後も追加できてしまうので、
今回のような参照のみの場合はReadOnlyCollection<>を使うのが好ましいようです!
    ご指摘ありがとうございます:bow_tone1:

これで親フォームのベースは作成できました。
【次回】
子フォームを追加しOpenChildForm(new forms.〜〜, sender);
の内容を投稿しようと思います。

### 最後に

https://rjcodeadvance.com/iu-moderno-temas-multicolor-aleatorio-resaltar-boton-form-activo-winform-c/#google_vignette

親フォームの作成はほとんどこのサイトを参考にしています。
プログラミングの学習は誰かが作ったものをコピーして、
それをいじりながら学ぶのがいいと思います。コードはすべてが丸写しではないですが
とても参考になると思います。
間違えてるところやもっと良い書き方があったらご指摘お願いします。
C#初学者の助けになれたら幸いです!
読んでいただきありがとうございました!