Windows のアプリケーションの作成方法の例を紹介してみる part1

今回は
「画像の入ったフォルダを入れるとピンボケしている画像のみ Bad フォルダに入れる」
という Windows アプリケーションの作成手順を紹介しようと思います。

***

１. VisualStudio をインストールして WindowsForm のプロジェクトを新規作成する

まずは VisualStudio をインストールして
WindowsForm のプロジェクトを新規作成します。

記事が長くなるため
この項目の細かい説明は省略します。

***

２. フォルダをドラッグ＆ドロップするためのパネルをデザイン上に置く

次にフォルダをドラッグ＆ドロップするための
パネルをツールボックスからドラッグ＆ドロップして
画面全体に広げます。

その後 label を中央に配置して
label を選択した状態で
右下のプロパティの Text を
「ここに仕分けしたいフォルダをドラッグ＆ドロップして下さい」
に変更します。
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752886/d196d778-1b72-78e4-acae-5bd5f0555fb6.png)

***

３. panel1_DragDrop と panel1_DragEnter を設定する

次にパネルに panel1_DragDrop と panel1_DragEnter を設定します。
パネルを選択した状態で
DragDrop と DragEnter の項目の
右の空白をダブルクリックして
panel1_DragDrop と panel1_DragEnter を設定します。
![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752886/87c13f59-35af-1a2b-e652-c3051a7f8399.png)

***

４. OpenCvSharp.dll を導入する

次に OpenCvSharp.dll を導入します。
OpenCvSharp.dll は画像処理のための
プラグインです。

[参考サイト](https://frailleaves.com/programming/opencvsharp4_howtouse/)

***

５. panel1_DragDrop と panel1_DragEnter を実装する

最後に panel1_DragDrop と panel1_DragEnter を実装します。

```csharp:using の記述
using OpenCvSharp;
```

を宣言して

panel1_DragDrop と panel1_DragEnter を実装します。

```csharp:実装例
        private void panel1_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data == null)
            {
                return;
            }
            object? data = e.Data.GetData(DataFormats.FileDrop, false);
            if (data == null)
            {
                return;
            }

            List<string> rootList = new List<string>();
            List<string> targetList = new List<string>();

            this.Activate();

            foreach (string rootFolderName in (string[])data)
            {
                if (!System.IO.Directory.Exists(rootFolderName))
                {
                    continue;
                }

                if (rootFolderName.Substring(rootFolderName.LastIndexOf("\\") + 1) == "Bad")
                {
                    continue;
                }

                foreach (string oneTargetFileName in Directory.GetFiles(rootFolderName, "*", System.IO.SearchOption.AllDirectories))
                {
                    if (!oneTargetFileName.EndsWith("png") && !oneTargetFileName.EndsWith("jpg"))
                    {
                        continue;
                    }

                    if (oneTargetFileName.Substring(0, oneTargetFileName.LastIndexOf("\\")).EndsWith("\\Bad"))
                    {
                        continue;
                    }

                    bool isBad = false;

                    using (Mat mat = new Mat(oneTargetFileName))
                    {
                        using (Mat Edge_Canny = new Mat())
                        {
                            Cv2.Canny(mat, Edge_Canny, 10, 410, 3);
                            int total = 0;
                            foreach (OpenCvSharp.Point[] one in Cv2.FindContoursAsArray(Edge_Canny, RetrievalModes.External, ContourApproximationModes.ApproxSimple))
                            {
                                total += one.Length;
                            }


                            isBad = total < 1000;
                        }
                    }

                    if (isBad)
                    {
                        string targetFolderName = oneTargetFileName.Substring(0, oneTargetFileName.LastIndexOf("\\") + 1) + "Bad";

                        if (!System.IO.Directory.Exists(targetFolderName))
                        {
                            System.IO.Directory.CreateDirectory(targetFolderName);
                        }

                        rootList.Add(oneTargetFileName);
                        targetList.Add(targetFolderName + "\\" + oneTargetFileName.Substring(oneTargetFileName.LastIndexOf("\\") + 1));
                    }
                }
            }

            if (rootList.Count != targetList.Count)
            {
                MessageBox.Show(
                        "エラー1が発生したため、安全性を考慮して何も処理を行わずに終了しました。", "確認",
                        MessageBoxButtons.OK, MessageBoxIcon.Question
                        );
                return;
            }

            for (int i = 0; i < targetList.Count; i++)
            {
                if (System.IO.File.Exists(targetList[i]))
                {
                    MessageBox.Show(
                            "移動しようとしているファイルが既に存在しているため、安全性を考慮して何も処理を行わずに終了しました。", "確認",
                            MessageBoxButtons.OK, MessageBoxIcon.Question
                            );
                    return;
                }
            }

            for (int i = 0; i < targetList.Count; i++)
            {
                for (int j = i + 1; j < targetList.Count; j++)
                {
                    if (targetList[i] == targetList[j])
                    {
                        MessageBox.Show(
                                "エラー2が発生したため、安全性を考慮して何も処理を行わずに終了しました。", "確認",
                                MessageBoxButtons.OK, MessageBoxIcon.Question
                                );
                        return;
                    }
                }
            }

            for (int i = 0; i < rootList.Count; i++)
            {
                if (!System.IO.Directory.Exists(rootList[i].Substring(0, rootList[i].LastIndexOf("\\"))))
                {
                    MessageBox.Show(
                            "エラー3が発生したため、安全性を考慮して何も処理を行わずに終了しました。", "確認",
                            MessageBoxButtons.OK, MessageBoxIcon.Question
                            );
                    return;
                }
            }

            for (int i = 0; i < targetList.Count; i++)
            {
                if (!System.IO.Directory.Exists(targetList[i].Substring(0, targetList[i].LastIndexOf("\\"))))
                {
                    MessageBox.Show(
                            "エラー4が発生したため、安全性を考慮して何も処理を行わずに終了しました。", "確認",
                            MessageBoxButtons.OK, MessageBoxIcon.Question
                            );
                    return;
                }
            }

            for (int i = 0; i < targetList.Count; i++)
            {
                System.IO.File.Move(rootList[i], targetList[i]);
            }

            MessageBox.Show(
                    "仕分けが完了しました。", "確認",
                    MessageBoxButtons.OK, MessageBoxIcon.Question
                    );

            return;
        }

        private void panel1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data == null)
            {
                return;
            }
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.All;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }
    }
```

上記の実装は
情報量の少ない画像を
Bad フォルダに移動しています。

作成後は上の再生ボタンで実行します。すると
プロジェクトのフォルダ ＞ bin ＞ Debug ＞ net8.0-windows
フォルダが成果物になります。
net8.0-windows フォルダをデスクトップにコピーして
net8.0-windows という名称を変更すれば
全ての作業が完了です。

Windows のアプリケーションの作り方は
様々な方法がありますが
例えばこのような手順で作成出来るのです。

***

以上 Windows のアプリケーションの
作り方の一例を紹介しました。

VisualStudio の WindowsForm は
オブジェクトを配置して
そのオブジェクトの OnClick を実装するといった
手順だけでアプリケーションを作る事ができます。

私が今まで作成してきた
Windows アプリケーションの
プロジェクトファイルは
今まで公開してきた記事で公開しています。

是非参考にして頂けると幸いです。

私も愛用している
[ファイルが更新される度に自動でバックアップを保存する Windows アプリケーションを公開してみる](https://qiita.com/uni928/items/ab9a03a666477f502658)
は特に便利なアプリケーションである自信があります。

皆さんも是非 Windows アプリケーションを
作成頂けたら嬉しいです。

閲覧ありがとうございました。