WinFormsお絵描きアプリ 応用編

~色・線幅変更と保存機能を追加する~

前回制作したWinFormsで実装するシンプルなお絵描きアプリの続編になります

追加機能

  • ペン色の変更(Button + ColorDialog)
  • 線の太さ変更(TrackBar)
  • 描いた画像をPNG保存(SaveFileDialog)

コード例

Form1.cs

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace SimplePaintAdvanced
{
    public partial class Form1 : Form
    {
        private readonly PictureBox _view = new() { Dock = DockStyle.Fill, BackColor = Color.White };
        private readonly Button _btnColor = new() { Text = "色変更", Dock = DockStyle.Left, Width = 80 };
        private readonly TrackBar _trackWidth = new() { Dock = DockStyle.Left, Minimum = 1, Maximum = 20, Value = 3, TickFrequency = 1, Width = 120 };
        private readonly Button _btnSave = new() { Text = "保存", Dock = DockStyle.Left, Width = 80 };

        private Bitmap _canvas;
        private bool _drawing;
        private Point _last;

        private Color _penColor = Color.Black;
        private float _penWidth = 3f;

        public Form1()
        {
            Text = "Simple Paint Advanced";
            ClientSize = new Size(900, 600);
            DoubleBuffered = true;

            var panel = new FlowLayoutPanel { Dock = DockStyle.Top, Height = 40 };
            panel.Controls.AddRange(new Control[] { _btnColor, _trackWidth, _btnSave });

            Controls.Add(_view);
            Controls.Add(panel);

            // 起動時とリサイズ時にキャンバス確保
            Load += (_, __) => CreateCanvas();
            _view.Resize += (_, __) => CreateCanvas(preserve: true);

            // マウス描画
            _view.MouseDown += (s, e) =>
            {
                if (e.Button == MouseButtons.Left)
                {
                    _drawing = true;
                    _last = e.Location;
                }
                else if (e.Button == MouseButtons.Right)
                {
                    ClearCanvas();
                }
            };

            _view.MouseMove += (s, e) =>
            {
                if (!_drawing) return;

                using (var g = Graphics.FromImage(_canvas))
                using (var pen = new Pen(_penColor, _penWidth)
                {
                    StartCap = LineCap.Round,
                    EndCap = LineCap.Round,
                    LineJoin = LineJoin.Round
                })
                {
                    g.SmoothingMode = SmoothingMode.AntiAlias;
                    g.DrawLine(pen, _last, e.Location);
                }

                _last = e.Location;
                _view.Invalidate();
            };

            _view.MouseUp += (s, e) => _drawing = false;

            _view.Paint += (s, e) =>
            {
                if (_canvas != null)
                    e.Graphics.DrawImageUnscaled(_canvas, Point.Empty);
            };

            // 色変更ボタン
            _btnColor.Click += (_, __) =>
            {
                using var cd = new ColorDialog();
                if (cd.ShowDialog() == DialogResult.OK)
                {
                    _penColor = cd.Color;
                }
            };

            // 線幅変更トラックバー
            _trackWidth.Scroll += (_, __) =>
            {
                _penWidth = _trackWidth.Value;
            };

            // 保存ボタン
            _btnSave.Click += (_, __) =>
            {
                using var sfd = new SaveFileDialog
                {
                    Filter = "PNGファイル|*.png",
                    FileName = "drawing.png"
                };
                if (sfd.ShowDialog() == DialogResult.OK)
                {
                    _canvas.Save(sfd.FileName, System.Drawing.Imaging.ImageFormat.Png);
                    MessageBox.Show("保存しました: " + sfd.FileName);
                }
            };
        }

        private void CreateCanvas(bool preserve = false)
        {
            if (_view.Width <= 0 || _view.Height <= 0) return;

            var newBmp = new Bitmap(_view.Width, _view.Height);
            using (var g = Graphics.FromImage(newBmp))
            {
                g.Clear(Color.White);

                if (preserve && _canvas != null)
                    g.DrawImageUnscaled(_canvas, Point.Empty);
            }

            _canvas?.Dispose();
            _canvas = newBmp;
            _view.Invalidate();
        }

        private void ClearCanvas()
        {
            if (_canvas == null) return;
            using (var g = Graphics.FromImage(_canvas))
                g.Clear(Color.White);

            _view.Invalidate();
        }
    }
}

実行イメージ

  • 上部に ツールバー があり、
    • 「色変更」→ カラーダイアログでペン色を変更
    • 「スライダー」→ 線幅を 1~20px で調整
    • 「保存」→ PNG形式で保存
  • メインの PictureBox に描いた内容が表示されます。

まとめ

基本版に少しUIを追加するだけで、お絵描きアプリらしい操作感が出ます。

次のステップとしては:

  • 消しゴムモード(背景色で線を描く)
  • Undo / Redo 機能(履歴を保持)
  • レイヤー管理(透明画像を重ねる)

といった発展も可能です。

訪問数 5 回, 今日の訪問数 1回

C#

Posted by hidepon