マウスホイールで画像を拡大縮小
左クリック→ドラックで画像の移動
右クリックで、元のサイズに画像をリセット
//
// 拡大機能付きピクチャーボックス
//
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());
}
}
コメント