C#ピクチャボックスの画像をマウスで拡大縮小移動する

C#コンピュータ
C#

マウスホイールで画像を拡大縮小

左クリック→ドラックで画像の移動

右クリックで、元のサイズに画像をリセット

//
// 拡大機能付きピクチャーボックス
//
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Text.RegularExpressions;
using System.Drawing.Drawing2D;


// コンパイル
// csc /t:winexe PictureBoxZoom2.cs

class Form1 : Form
{
    // 表示するBitmap 
    Bitmap _srcBmp = null;
    
    // 描画用Graphicsオブジェクト
    Graphics _g = null;
    
    // アフィン変換行列  
    Matrix _mat = null;

    // マウス移動中フラグ
    bool _isMouseMoving = false;
    
    // マウス座標(マウスをクリックした位置の保持用)
    PointF _oldPoint;
    

    // ピクチャボックス
    PictureBox picbox1 = new PictureBox
    {
        Dock = DockStyle.Fill,
    };

    // コンストラクタ
    Form1()
    {
        // イベント関連
        Resize += Form1_Resize;
        picbox1.MouseDown += picbox1_MouseDown;
        picbox1.MouseMove += picbox1_MouseMove;
        picbox1.MouseUp += picbox1_MouseUp;
        picbox1.MouseWheel += picbox1_MouseWheel;
        
        // コントロールの登録
        Controls.Add(picbox1);

        // 表示画像の読み込み
        _srcBmp = new Bitmap(@"H:\Pictures\202010021053.png");

        // 初期化の為リサイズイベントを強制的に実行
        Form1_Resize(null, null);  
    }

    // Form1リサイズイベント
    void Form1_Resize(Object sender, EventArgs e)
    {
        /*
            フォームのウィンドウサイズが変更されると、フォーム上のPictureBoxのサイズも変更される。
            PictreuBoxのサイズ一杯に画像表示領域を確保する場合、サイズ変更のイベントと合わせて、
            表示領域用ビットマップオブジェクトの再作成が必要になる。
        */

        // Graphicsオブジェクトが取得済みの場合
        if (_g != null)
        {
            // Graphicsオブジェクトからアフィン変換行列を取得し退避
            _mat = _g.Transform;
            
            // Graphicsオブジェクトの解放  
            _g.Dispose(); _g = null;  
        }
        else
        {
            _mat = new Matrix();
        }


        // Imageを破棄
        if (picbox1.Image != null) picbox1.Image.Dispose();

        // PictureBoxに描画領域用の空のビットマップを割り当てる。
        picbox1.Image = new Bitmap(picbox1.Width, picbox1.Height);

        // PictureBoxから新たなGraphicsオブジェクトを取得し退避  
        _g = Graphics.FromImage(picbox1.Image);
        
        // 補間モードの設定(NearestNeighbor)  
        _g.InterpolationMode = InterpolationMode.NearestNeighbor;

        // 画像の描画  
        DrawImage();          
    }

    // ビットマップの描画  
    void DrawImage()
    {
        // ビットマップが未設定の場合戻る
        if (_srcBmp == null) return;  

        // アフィン変換行列をセット
        if (_mat != null)
        {  
            _g.Transform = _mat;  
        }  

        // ピクチャボックスを背景色でクリア  
        _g.Clear(picbox1.BackColor);  
        
        // 描画
        _g.DrawImage(_srcBmp, 0, 0);  
        
        // ピクチャボックスをリフレッシュし再描画  
        picbox1.Refresh();  
    }

    // マウスダウンイベント
    void picbox1_MouseDown(object sender, MouseEventArgs e)
    {  
        // ビットマップが未設定の場合戻る
        if (_srcBmp == null) return;  

        // 右ボタンがクリックされたとき元に戻す 
        if (e.Button == MouseButtons.Right)
        {
            // アフィン変換行列をリセット 
            _mat.Reset();  
            
            // 画像の描画  
            DrawImage();  

            // 戻る
            return;
        }  

        // フォーカスの設定(おまじない)
        picbox1.Focus();

        // マウスをクリックした位置の記録  
        _oldPoint.X = e.X;  
        _oldPoint.Y = e.Y;

        // マウス移動フラグを立てる  
        _isMouseMoving = true;  
    }

    // マウス移動イベント
    void picbox1_MouseMove(object sender, MouseEventArgs e)  
    {  
        // ビットマップが未設定の場合戻る
        if (_srcBmp == null) return;

        // マウスをクリックしながら移動中のとき  
        if (_isMouseMoving == true)
        {
            // 以前の座標から移動量を算出
            var xx = e.X - _oldPoint.X;
            var yy = e.Y - _oldPoint.Y;

            // 画像の移動  
            _mat.Translate(xx, yy, MatrixOrder.Append);  
            
            // 画像の描画  
            DrawImage();  

            // ポインタ位置の保持  
            _oldPoint.X = e.X;  
            _oldPoint.Y = e.Y;  
        }  
    }

    // マウスアップイベント
    void picbox1_MouseUp(object sender, MouseEventArgs e)  
    {
        // ビットマップが未設定の場合戻る
        if (_srcBmp == null) return;

        // マウス移動フラグを解放  
        _isMouseMoving = false;  
    }

    // マウスホイールイベント  
    void picbox1_MouseWheel(object sender, MouseEventArgs e)  
    {
        // ビットマップが未設定の場合戻る
        if (_srcBmp == null) return;

        // 一旦ポインタの位置→原点へ移動  
        _mat.Translate(-e.X, -e.Y, MatrixOrder.Append);

        // ホイールの回転回数が、
        if (e.Delta > 0)
        {
            // 正の場合拡大
            if (_mat.Elements[0] < 100)
            {
                // 最大倍率以内の場合、1.5拡大  
                _mat.Scale(1.5f, 1.5f, MatrixOrder.Append);  
            }  
        } else {  
            // 負の場合縮小  
            if (_mat.Elements[0] > 0.01)
            {
                // 最小倍率以内の場合、1.0/1.5縮小
                _mat.Scale(1.0f / 1.5f, 1.0f / 1.5f, MatrixOrder.Append);  
            }  
        }

        // 原点→ポインタの位置へ移動(元の位置へ戻す)  
        _mat.Translate(e.X, e.Y, MatrixOrder.Append);

        // 画像の描画  
        DrawImage();  
    }  

    // エントリーポイント
    [STAThread]
    static void Main()
    {
        Application.Run(new Form1());
    }
}

コメント