マウスホイールで画像を拡大縮小表示する

WPF ではマウスホイールによる画像の拡大縮小表示が標準で実装されておりますが、WindowsForms では標準で実装されていません。

画像の拡大縮小表示は、ビットマップをピクチャボックスのサイズに応じて DrawImage してやればいいので、マウスホイールを使ってピクチャボックスのサイズを動的に変更してやれば所望の動作が実現できます。

Fig. 1 起動時
Fig. 2 モニタ側にホイールして拡大
Fig. 3 自分側にホイールして縮小

面倒ですが、マウスホイールのイベントをコントロールに自分で関連付けて、そこで取得できるイベントハンドラの引数を使ってピクチャボックスのサイズを動的に変更しましょう。

具体的には、イベントハンドラの引数で MouseEventArgs 型の e という変数が参照できます。このメンバの Delta を使って、マウスホイールをモニタ側に回したときか、自分側に回したときかを判断します。

private void Form1_Load( object sender, EventArgs e )
{

	// フォーム上でマウスホイールしたときのイベントを登録する.
	this.MouseWheel += new MouseEventHandler( this.Form1_MouseWheel );

}

// このコードブロックはメソッドの宣言からすべて自分で記述する.
private void Form1_MouseWheel( object sender, MouseEventArgs e )
{

	if ( e.Delta >= 0 )
	{
		// モニタ側にホイールをまわしたとき.

	}
	else
	{
		// 自分側にホイールをまわしたとき.

	}

}

全体コード

73行目でマウスホイールイベントを関連付けます。

86行目から132行目がマウスホイールによって実行したいコードを書きます。

ここではズーム率を複数格納したリストをあらかじめ作成しておきます。そのリストを参照するインデックスをマウスホイールによって増減させてズーム率を取り出し、同時にピクチャボックスの Width と Height の値を変更します。

ピクチャボックスのサイズを変更すると同時に再描画も実行されますが、念のため Invalidate( true ) や Update() といったピクチャボックスの再描画要求コードを明示しておくのがよいでしょう。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace aaa
{
	public partial class Form1 : Form
	{

		const int DEFAULT_W = 256;
		const int DEFAULT_H = 256;

		Bitmap Bmp;

		int IndexZoomRate = 0;
		List<double> ZoomRate;

		public Form1()
		{
			InitializeComponent();
		}

		private void Form1_Load( object sender, EventArgs e )
		{

			// 必要な場合は自動でスクロールバーを表示する.
			this.AutoScroll = true;

			// ピクチャボックスに描画するビットマップを生成する.
			Bmp = new Bitmap( DEFAULT_W, DEFAULT_H );

			int w = Bmp.Width;
			int h = Bmp.Height;

			// ビットマップに青のグラデーションをしこむ.
			for ( int j = 0; j < h; j++ )
			{
				for ( int i = 0; i < w; i++ )
				{
					Color c = Color.FromArgb( 0, 0, j );
					Bmp.SetPixel( i, j, c );
				}
			}

			// ズーム率が格納されているリストを生成する.
			ZoomRate = new List<double>();
			ZoomRate.Add( 0.2 ); // 0.
			ZoomRate.Add( 0.4 ); // 1.
			ZoomRate.Add( 0.6 ); // 2.
			ZoomRate.Add( 0.8 ); // 3.
			ZoomRate.Add( 1.0 ); // 4.
			ZoomRate.Add( 1.2 ); // 5.
			ZoomRate.Add( 1.4 ); // 6.
			ZoomRate.Add( 1.6 ); // 7.
			ZoomRate.Add( 1.8 ); // 8.
			ZoomRate.Add( 2.0 ); // 9.

			// 初期値は 1.0 とする.
			IndexZoomRate = 4;

			// ズーム率を取り出す.
			double zr = ZoomRate[IndexZoomRate];

			// ピクチャボックスのサイズを決定する.
			int px = 0;
			int py = 0;
			int pw = (int)( Math.Round( w * zr ));
			int ph = (int)( Math.Round( h * zr ));
			pictureBox1.SetBounds( px, py, pw, ph );

			// フォーム上でマウスホイールしたときのイベントを登録する.
			this.MouseWheel += new MouseEventHandler( this.Form1_MouseWheel );

		}

		private void Form1_FormClosed( object sender, FormClosedEventArgs e )
		{
			// パブリックなビットマップはアプリ終了時に破棄する決まり.
			if ( Bmp != null )
			{
				Bmp.Dispose();
			}
		}

		// -----------------------------------------------------------------
		// このコードブロックは自分で記述する, ここから.
		private void Form1_MouseWheel( object sender, MouseEventArgs e )
		{

			if ( e.Delta >= 0 )
			{
				// モニタ側にホイールをまわしたとき.

				IndexZoomRate++;

				// 配列の領域外をアクセスしないように調整する.
				if ( IndexZoomRate >= ZoomRate.Count )
				{
					IndexZoomRate = ZoomRate.Count - 1;
				}

			}
			else
			{
				// 自分側にホイールをまわしたとき.

				IndexZoomRate--;

				// 配列の領域外をアクセスしないように調整する.
				if ( IndexZoomRate < 0 )
				{
					IndexZoomRate = 0;
				}

			}

			// ズーム率を取得する.
			double zr = ZoomRate[ IndexZoomRate ];

			// ピクチャボックスのサイズを変更する.
			int w = Bmp.Width;
			int h = Bmp.Height;
			pictureBox1.Width  = (int)( Math.Round( w * zr ));
			pictureBox1.Height = (int)( Math.Round( h * zr ));

			// ピクチャボックスの再描画要求をする.
			pictureBox1.Invalidate( true );

		}
		// このコードブロックは自分で記述する, ここまで.
		// -----------------------------------------------------------------

		private void pictureBox1_Paint( object sender, PaintEventArgs e )
		{

			const String FMT = "ZoomRate[{0}]: {1:f1}";
			this.Text = String.Format( FMT, IndexZoomRate, ZoomRate[IndexZoomRate] );

			// ビットマップをピクチャボックスのサイズにあわせて描画する.
			if ( Bmp != null )
			{
				int pw = pictureBox1.Width;
				int ph = pictureBox1.Height;
				e.Graphics.DrawImage( Bmp, 0, 0, pw, ph ); 
			}

		}
	}
}