LoginSignup
1
1

More than 1 year has passed since last update.

【C#】マウスで画像範囲を選択して、ドラッグで移動する【ペイント】

Last updated at Posted at 2022-09-25

ペイントツールでよくある範囲選択(切り取り)機能です
前回のプログラムに付け足すような形で追加しています

Animation.gif

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Runtime.Remoting;
using System.Windows.Forms;

namespace ImageEditing
{
    public partial class frmPaintTool : Form
    {
        // 変数
        Bitmap _newBitMap;              // ビットマップ画像
        Bitmap _oldBitMap;              // ビットマップ画像
        Bitmap _selectBitMap;           // ビットマップ画像
        bool _mouseDrug;                // マウスクリック中のフラグ
        bool _moveFirst;                // 初回の画像移動のフラグ
        bool _moveImage;                // 画像移動中のフラグ
        int _prevX;                     // 前のマウスカーソルのX座標
        int _prevY;                     // 前のマウスカーソルのY座標
        int _startX;                    // スタートのマウスカーソルのX座標
        int _startY;                    // スタートのマウスカーソルのY座標
        int _selectX;                   // 選択中の範囲のX座標
        int _selectY;                   // 選択中の範囲のY座標
        int _penType;                   // ペンモード
        Rectangle _selectedRect;        // 選択範囲の記憶

        public frmPaintTool()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // BitMapオブジェクトを生成する
            // 背景色として白で塗りつぶす
            _newBitMap = new Bitmap(DrawingPicBox.Width, DrawingPicBox.Height);
            Graphics objGrp = Graphics.FromImage(_newBitMap);
            SolidBrush objBrush = new SolidBrush(Color.White);
            objGrp.FillRectangle(objBrush, 0, 0, _newBitMap.Width, _newBitMap.Height);
            objGrp.Dispose();
            objBrush.Dispose();

            // ビットマップ画像をコピー
            _oldBitMap = (Bitmap)_newBitMap.Clone();
        }


        private void DrawingPicBox_MouseDown(object sender, MouseEventArgs e)
        {
            // マウスクリック開始判定
            _mouseDrug = true;
            
            if (_penType == 2)
            {
                // 選択ツールが選択されている場合
                // マウスカーソルの位置を取得する
                Point clickPoint = new Point(e.X, e.Y);                 
                if (_selectedRect.Contains(clickPoint) == true)         
                {
                    // マウスカーソルが前回の選択範囲の中でクリックされたとき
                    if (_moveFirst == true)
                    {
                        PixelFormat format = _newBitMap.PixelFormat;
                        // 範囲の画像を切り取る
                        _selectBitMap = _newBitMap.Clone(_selectedRect, format);                  
                    }
                    // 移動モードに移行する
                    _moveImage = true;                                  
                }
                else                                                    
                {
                    // マウスカーソルが範囲の外を選択したとき
                    if (_moveImage == true)                             
                    {
                        // 画像を移動していたとき
                        Graphics objGrp = Graphics.FromImage(_oldBitMap);
                        // 変更を確定する
                        objGrp.DrawImage(_selectBitMap, _selectedRect);    
                        objGrp.Dispose();
                        _selectBitMap.Dispose();
                    }
                    _newBitMap = (Bitmap)_oldBitMap.Clone();
                    _moveFirst = true;
                    _moveImage = false;
                }
                DrawingPicBox.Image = _newBitMap;
            }

            // マウスカーソル位置記憶の初期化
            _prevX = e.Location.X;
            _prevY = e.Location.Y;
            _startX = e.Location.X;
            _startY = e.Location.Y;
        }

        private void DrawingPicBox_MouseUp(object sender, MouseEventArgs e)
        {
            // マウスクリック終了判定
            _mouseDrug = false;

            if (_penType == 2)
            {
                if (_moveImage == false)                                
                {
                    // 選択ツールが選択されている場合
                    // 画像範囲選択中のとき
                    if (_startX <= _prevX)
                    {
                        if (_startY <= _prevY)
                        {
                            _selectedRect = new Rectangle(_startX, _startY, _prevX - _startX, _prevY - _startY);
                            _selectX = _startX;                           // 選択範囲のスタート位置を記憶する
                            _selectY = _startY;
                        }
                        else
                        {
                            _selectedRect = new Rectangle(_startX, _prevY, _prevX - _startX, _startY - _prevY);
                            _selectX = _startX;                           // 選択範囲のスタート位置を記憶する
                            _selectY = _prevY;
                        }
                    }
                    else
                    {
                        if (_startY <= _prevY)
                        {
                            if (_prevY > DrawingPicBox.Height - 1)
                            {
                                _prevY = DrawingPicBox.Height - 1;
                            }
                            _selectedRect = new Rectangle(_prevX, _startY, _startX - _prevX, _prevY - _startY);
                            _selectX = _prevX;                            // 選択範囲のスタート位置を記憶する
                            _selectY = _startY;
                        }
                        else
                        {
                            _selectedRect = new Rectangle(_prevX, _prevY, _startX - _prevX, _startY - _prevY);
                            _selectX = _prevX;                            // 選択範囲のスタート位置を記憶する
                            _selectY = _prevY;
                        }
                    }
                }
                else
                {
                    // 画像移動中だったとき
                    // 移動された後の選択範囲のスタート位置を記憶する
                    _selectX = _selectX + e.Location.X - _startX;           
                    _selectY = _selectY + e.Location.Y - _startY;
                    _selectedRect = new Rectangle(_selectX, _selectY, _selectBitMap.Width, _selectBitMap.Height);
                }
                return;
            }

            // 変更を保存する
            _oldBitMap = (Bitmap)_newBitMap.Clone();
        }

        private void DrawingPicBox_MouseMove(object sender, MouseEventArgs e)
        {
            // マウスクリック中に、BitMapにGraphicsオブジェクトで描画する
            if (_mouseDrug == true)
            {
                // BitMapからGraphicsオブジェクトを生成
                // 選択されているツールの種類によって処理を分ける
                Graphics objGrp = Graphics.FromImage(_newBitMap);
                Pen objPen = null;
                SolidBrush objBrush = null;
                if (_penType == 0)
                {
                    // ペンが選択されている場合
                    objPen = new Pen(Color.Black, 3);
                    objGrp.DrawLine(objPen, _prevX, _prevY, e.Location.X, e.Location.Y);
                    objPen.Dispose();
                }
                else if (_penType == 1)
                {
                    // 四角形が選択されている場合
                    _newBitMap = (Bitmap)_oldBitMap.Clone();
                    objGrp = Graphics.FromImage(_newBitMap);
                    objBrush = new SolidBrush(Color.Black);
                    if (_startX <= e.Location.X)
                    {
                        if (_startY <= e.Location.Y)
                        {
                            objGrp.FillRectangle(objBrush, _startX, _startY, e.Location.X - _startX, e.Location.Y - _startY);
                        }
                        else
                        {
                            objGrp.FillRectangle(objBrush, _startX, e.Location.Y, e.Location.X - _startX, _startY - e.Location.Y);
                        }
                    }
                    else
                    {
                        if (_startY <= e.Location.Y)
                        {
                            objGrp.FillRectangle(objBrush, e.Location.X, _startY, _startX - e.Location.X, e.Location.Y - _startY);
                        }
                        else
                        {
                            objGrp.FillRectangle(objBrush, e.Location.X, e.Location.Y, _startX - e.Location.X, _startY - e.Location.Y);
                        }
                    }
                    objBrush.Dispose();
                }
                else if (_penType == 2)
                {
                    // 選択ツールが選択されている場合
                    // 画像を途中で上書き保存しない
                    _newBitMap = (Bitmap)_oldBitMap.Clone();
                    objGrp = Graphics.FromImage(_newBitMap);
                    if (_moveImage == false)
                    {
                        //画像範囲選択中のとき
                        objPen = new Pen(Color.Black, 1);
                        objPen.DashStyle = DashStyle.Dash;
                        if (_startX <= e.Location.X)
                        {
                            if (_startY <= e.Location.Y)
                            {
                                objGrp.DrawRectangle(objPen, _startX - 1, _startY - 1, e.Location.X - _startX + 1, e.Location.Y - _startY + 1);
                            }
                            else
                            {
                                objGrp.DrawRectangle(objPen, _startX - 1, e.Location.Y - 1, e.Location.X - _startX + 1, _startY - e.Location.Y + 1);
                            }
                        }
                        else
                        {
                            if (_startY <= e.Location.Y)
                            {
                                objGrp.DrawRectangle(objPen, e.Location.X - 1, _startY - 1, _startX - e.Location.X + 1, e.Location.Y - _startY + 1);
                            }
                            else
                            {
                                objGrp.DrawRectangle(objPen, e.Location.X - 1, e.Location.Y - 1, _startX - e.Location.X + 1, _startY - e.Location.Y + 1);
                            }
                        }
                    }
                    else
                    {
                        //画像移動中のとき
                        if (_moveFirst == true)
                        {
                            // 初回の画像移動だった場合
                            // 切り取られた範囲を白で塗り潰す
                            objBrush = new SolidBrush(Color.White);
                            objGrp.FillRectangle(objBrush, _selectedRect);
                            objBrush.Dispose();
                            // 画像を更新する
                            _oldBitMap = (Bitmap)_newBitMap.Clone();        
                            _moveFirst = false;
                        }
                        objPen = new Pen(Color.Black, 1);
                        objPen.DashStyle = DashStyle.Dash;
                        objGrp.DrawImage(_selectBitMap, _selectX + e.Location.X - _startX, _selectY + e.Location.Y - _startY, _selectBitMap.Width, _selectBitMap.Height);
                        objGrp.DrawRectangle(objPen, _selectX + e.Location.X - _startX - 1, _selectY + e.Location.Y - _startY - 1, _selectBitMap.Width + 1, _selectBitMap.Height + 1);
                        objPen.Dispose();
                    }
                }

                // BitMapオブジェクトをPictureBoxに表示する
                objGrp.Dispose();
                _prevX = e.Location.X;
                _prevY = e.Location.Y;
                DrawingPicBox.Image = _newBitMap;
            }
        }

        private void Tools_CheckedChanged(object sender, EventArgs e)
        {
            // 現在の選択されているツールの種類を保存
            if(typePen.Checked == true)
            {
                _penType = 0;
            }
            else if(typeSquare.Checked == true)
            {
                _penType = 1;
            }
            else if (typeSelect.Checked == true)
            {
                _penType = 2;
            }
        }
    }
}

マウスドラッグで範囲を指定し、選択された範囲の画像を_selectBitMapへコピーしています

DrawImage()でコピーされた_selectBitMapをそのまま描画できます(Rectangleで描画する場所を指定する必要がある)

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1