【C#】画面上に線を引きたい #4(完成)

スポンサーリンク

知人に作ってほしいと言われたソフトもとうとう完成させたいと思います。
やり方は人それぞれなので、1つの参考としてみてもらえればと思います。
コードも公開しているので少し長くなると思いますが、よろしくお願いいたします。
前回の記事が気になる方は、下記パスから確認してください。
頑張りましょう!

【C#】画面上に線を引きたい #3(モニタサイズの取得) | 育児パパの人生備忘録 (t19488sns.com)

要望の整理

簡単ですが要望をまとめたいと思います。
1.画面の中心線を引く
2.画面の背景は透明
3.線の色は選択可能

この要望から、必要な知識は、下記になります。
★線の引き方
★中心線の計算方法
★画面を透明にする方法
★線の色の指定方法
★画面の大きさの取得

フォームを作成する

必要なフォームとしては2つです。
①表示/非表示をコントロールするフォーム(frmMain)
②ラインを表示するフォーム(frmScreen)

frmMain

【frmMain】プロパティ  デフォルト設定からの変更点
TopMost → True(とりあえず常に手前にいてほしい)
MaximizeBox → False(最大化のボタン非表示)
MinimizaBox → False(最小化のボタン非表示)

3つのボタンと1つのコンボボックスを設置します。
btnShow → frmScreenを表示させるボタン
btnLineHide → frmScreenを非表示にさせるボタン(今回はフラグを立てるだけ)
btnClose → アプリケーション終了ボタン
cmbColor → 線の色を選択できるコンボボックス

frmScreen

【frmMain】プロパティ  デフォルト設定からの変更点
FormBorderStyle → None
MaximizeBox → False(最大化のボタン非表示)
MinimizaBox → False(最小化のボタン非表示)
TransparencyKey → Transparent

1つのピクチャボックスを設置します。(このピクチャボックスに線を表示させます)
picLine → 線を表示する為のピクチャーボックス
  ※BackColorはTransparent
  ※DockはFill(親コンテナにドッキング)

frmMainのイベントを作成していく

デザイン上のコントロールをダブルクリックすると自動生成されるイベントなので、デザイン上のコントロールをダブルクリックしてください。

frmMainのLoad処理

ロード処理では、コンボボックスの選択肢を作る。

        private void frmMain_Load(object sender, EventArgs e)
        {

            cmbColor.Items.Clear();
            foreach (eColor clr in Enum.GetValues(typeof(eColor)))
            {
                cmbColor.Items.Add(clr.ToString());
            }
            cmbColor.SelectedIndex = 0;
        }

のちのち、色が追加できるようにと、色の設定は、enum(列挙体)で定義しました。

        enum eColor
        {
            black = 0x000000,
            white = 0xFFFFFF,
            red = 0xFF0000,
            blue = 0x0000FF,
            green = 0x008000,
            yellow = 0xFFFF00,
        }

btnColose クリックイベント

クリックしたら終了するようにします。
本当はメッセージボックスとか表示して、確認してからとかしたいけど、面倒なのでしませんw

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

btnLineHide クリックイベント

クリックした場合、frmScreenを閉じる処理でもいいですが、今回はフラグを立てます。
その為、このfrmMain内で共通のフラグも定義ます。

        private bool IsfrmLineClose = true;
        private void btnLineHide_Click(object sender, EventArgs e)
        {
            IsfrmLineClose = true;
        }

btnShow クリックイベント

frmScreenを表示させます。いろいろと処理が入ってきます。

        private void btnShow_Click(object sender, EventArgs e)
        {
            //コントロール操作不可
            btnShow.Enabled = false;
            cmbColor.Enabled = false;

            //フラグ初期化
            IsfrmLineClose = false;

            //現在選択されている色を取得する。
            GetSelectColor(out Color clr);

            //frmScreenのインスタンス作成(引数に色を渡す)
            using (frmScreen frm = new frmScreen(clr))
            {
                //表示
                frm.Show();

                //frmScreenが閉じる or フラグがたったら、frmScreenを閉じる
                do
                {
                    Application.DoEvents();
                    System.Threading.Thread.Sleep(10);
                } while (frm.IsDisposed == false && IsfrmLineClose == false);
            }

            //コントロール操作可能
            btnShow.Enabled = true;
            cmbColor.Enabled = true;
        }

コンボボックスで選択されている色を取得するための関数を作りました( GetSelectColor )
中身は下記の通り

        private void GetSelectColor(out Color clr)
        {
            //コンボボックスの文字をenumに変換
            eColor tmp = (eColor)Enum.Parse(typeof(eColor), cmbColor.Text, true);
            clr = ChangeColor(tmp);
        }

コンボボックスの表示している文字列をenumに変換します。
これはフォームロード時にコンボボックスの選択をeColor(enum)から作成しているので、確実に変換可能です。心配なときはtry-catchを入れることをオススメします。

最後にenumから色に変換するようにします。(ChangeColor())

        private Color ChangeColor(eColor clr)
        {
            Color res = Color.Black;
            if (clr == eColor.black) res = Color.Black;
            else if (clr == eColor.blue) res = Color.Blue;
            else if (clr == eColor.green) res = Color.Green;
            else if (clr == eColor.red) res = Color.Red;
            else if (clr == eColor.white) res = Color.White;
            else if (clr == eColor.yellow) res = Color.Yellow;

            return res;
        }

もっと美しくしたかったのですが、とりあえずで。。。こういう人ほど修正しませんがw

frmScreenのイベントを作成していく

コンストラクタ

コンストラクタという言葉がわからない人は、newされた時に動作する関数だと思ってください。
クラスの初期化処理なので、基本的にはエラーが出ない処理をするのがオススメです。

        public frmScreen(Color clr)
        {
            InitializeComponent();

            //モニタを取得し、配置と大きさを指定する
            SetFormLocationAndSize();

            //線を引く
            DrawCenterLine(clr);

            //こっちでも設定
            this.TransparencyKey = this.BackColor;
        }

※プロパティで設定してますが、ここで書いていないとうまくいきませんでした。
 Transparentだからなのか・・・

関数: SetFormLocationAndSize()

表示しているモニタの位置を取得し、モニタの原点(左上)からモニタサイズのフォームサイズに設定します。

        private void SetFormLocationAndSize()
        {
            foreach (Screen scr in Screen.AllScreens)
            {
                if (scr.WorkingArea.Contains(this.Location) == true)
                {
                    //Windowの大きさは画面の大きさ
                    this.Size = scr.Bounds.Size;

                    //位置はここ
                    this.Location = new Point(scr.Bounds.X, scr.Bounds.Y);
                }
            }
        }

関数: DrawCenterLine(Color)

指定された色でモニタに中心線を表示する関数です。

        public void DrawCenterLine(Color clr)
        {
            //1.Bitmapクラスを作成(大きさはwindowサイズ)
            Bitmap btmp = new Bitmap(picLine.Width, picLine.Height);

            //2.Graphicクラスを生成する(先ほどのBitmap(Imageオフジェクト)クラスを使う)
            Graphics grph = Graphics.FromImage(btmp);

            //3.Penオブジェクト生成(今回は黒の太さ1)
            Pen pen = new Pen(clr, 1);

            //4.始点と終点を設定する
            Point stPt = new Point(picLine.Width / 2, 0);
            Point edPt = new Point(picLine.Width / 2, picLine.Height);

            //5.線を引く
            grph.DrawLine(pen, stPt, edPt);

            //4.始点と終点を設定する
            Point stPt2 = new Point(0, picLine.Height / 2);
            Point edPt2 = new Point(picLine.Width, picLine.Height/2);

            //5.線を引く
            grph.DrawLine(pen, stPt2, edPt2);

            //6.解放する
            pen.Dispose();
            grph.Dispose();

            //7.表示する
            picLine.Image = btmp;
        }

まとめ

今回は知人に頼まれたソフトの備忘録です。
やりたい事を分類し、1つ1つの機能として作っていき、最後のつなげる流れで作りました。
1つのソフト(アプリケーション)を作ると言っても、機能的には作る(関数)ことが多いですね。
どんだけ言葉がアバウトな事なのか思い知りますw

今回の方法は自分が自分なりに作った方法なので、これが正解とかではありません。
相手の要望を叶うのであれば、自由に考えて、自由に書いていいと思っています。

次回も何か作った時に紹介していきたいと思います。

コメント

タイトルとURLをコピーしました