■ はじめに
https://blogs.yahoo.co.jp/dk521123/37846450.htmlで、Windows Formで画像比較スライダーを実装したが 今回は、別解として、PictureBox 1つで画像比較スライダーを実装してみる。
■ サンプル
例1
using System; using System.Drawing; using System.Windows.Forms; namespace SampleForm { public partial class Form1 : Form { private const int BorderWidth = 2; private int borderPosition = -1; private Bitmap srcImage = null; private Bitmap destinationImage = null; private Point mousePoint = Point.Empty; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { // 画像ファイルのImageオブジェクトを作成する this.srcImage = new Bitmap(@"C:\20161215052204.gif"); //画像ファイルのImageオブジェクトを作成する this.destinationImage = new Bitmap(@"C:\20161215052204.png"); this.borderPosition = srcImage.Width / 2; this.Draw(this.srcImage, this.destinationImage, this.borderPosition); } private void Form1_Resize(object sender, EventArgs e) { if (this.srcImage != null && this.destinationImage != null) { this.Draw(this.srcImage, this.destinationImage, this.borderPosition); } } private void Draw(Bitmap srcImage, Bitmap destinationImage, int borderPosition) { if (this.pictureBox1.Width <= 0 || this.pictureBox1.Height <= 0) { return; } if (this.pictureBox1.Image != null) { var oldImage = this.pictureBox1.Image; oldImage.Dispose(); this.pictureBox1.Image = null; } var canvas = new Bitmap(this.pictureBox1.Width, this.pictureBox1.Height); // ImageオブジェクトのGraphicsオブジェクトを作成する using (var graphics = Graphics.FromImage(canvas)) { // 画像を描画する graphics.DrawImage(srcImage, 0, 0); // 切り取る部分の範囲を決定 var srcArea = new Rectangle( borderPosition, 0, destinationImage.Width - borderPosition, destinationImage.Height); // 描画する部分の範囲を決定 var destinationArea = new Rectangle(borderPosition, 0, srcArea.Width, srcArea.Height); // 画像の一部を描画する graphics.DrawImage(destinationImage, destinationArea, srcArea, GraphicsUnit.Pixel); // 境界線描画 var pen = new Pen(Color.Pink, 2); graphics.DrawRectangle (pen, borderPosition - (BorderWidth / 2), 0, BorderWidth, srcArea.Height); } // PictureBox1に表示する this.pictureBox1.Image = canvas; } private void pictureBox1_MouseDown(object sender, MouseEventArgs e) { if (this.srcImage == null || this.destinationImage == null || !e.Button.Equals(MouseButtons.Left)) { return; } var mousePoint = e.Location; if (this.IsOnBorderArea( mousePoint, this.borderPosition, this.destinationImage.Height)) { this.mousePoint = mousePoint; } } private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { if (this.srcImage == null || this.destinationImage == null) { return; } var mousePoint = e.Location; if (this.IsOnBorderArea( mousePoint, this.borderPosition, this.destinationImage.Height)) { this.pictureBox1.Cursor = Cursors.VSplit; } else { this.pictureBox1.Cursor = Cursors.Default; } if (!this.mousePoint.IsEmpty) { this.borderPosition = mousePoint.X; this.Draw(this.srcImage, this.destinationImage, this.borderPosition); this.mousePoint = mousePoint; this.pictureBox1.Invalidate(); } } private void pictureBox1_MouseUp(object sender, MouseEventArgs e) { this.mousePoint = Point.Empty; } private bool IsOnBorderArea(Point targetPoint, int borderPosition, int height) { var borderArea = new Rectangle(borderPosition - (BorderWidth / 2), 0, BorderWidth, height); return borderArea.Contains(targetPoint); } } }
例2
全体表示した後に元に戻すと境界線を見失う時があるので、境界線の位置の保持を座標位置から座標位置の割合にするusing System; using System.Drawing; using System.Windows.Forms; namespace SampleForm { public partial class Form1 : Form { private const int BorderWidth = 2; private double borderPositionRate = -1; private Bitmap srcImage = null; private Bitmap destinationImage = null; private Point mousePoint = Point.Empty; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { // 画像ファイルのImageオブジェクトを作成する this.srcImage = new Bitmap(@"C:\temp\20161215052204.gif"); //画像ファイルのImageオブジェクトを作成する this.destinationImage = new Bitmap(@"C:\temp\20161215052204.png"); this.borderPositionRate = 0.5; this.Draw(this.srcImage, this.destinationImage, this.borderPositionRate); } private void Form1_Resize(object sender, EventArgs e) { if (this.srcImage != null && this.destinationImage != null) { this.Draw(this.srcImage, this.destinationImage, this.borderPositionRate); } } private void Draw(Bitmap srcImage, Bitmap destinationImage, double borderPositionRate) { if (this.pictureBox1.Width <= 0 || this.pictureBox1.Height <= 0) { return; } if (this.pictureBox1.Image != null) { var oldImage = this.pictureBox1.Image; oldImage.Dispose(); this.pictureBox1.Image = null; } var canvas = new Bitmap(this.pictureBox1.Width, this.pictureBox1.Height); // ImageオブジェクトのGraphicsオブジェクトを作成する using (var graphics = Graphics.FromImage(canvas)) { // 画像を描画する graphics.DrawImage(srcImage, 0, 0); // 切り取る部分の範囲を決定 int borderPosition = (int)Math.Round( this.pictureBox1.Width * borderPositionRate, MidpointRounding.AwayFromZero); var srcArea = new Rectangle( borderPosition, 0, destinationImage.Width - borderPosition, destinationImage.Height); // 描画する部分の範囲を決定 var destinationArea = new Rectangle(borderPosition, 0, srcArea.Width, srcArea.Height); // 画像の一部を描画する graphics.DrawImage(destinationImage, destinationArea, srcArea, GraphicsUnit.Pixel); // 境界線描画 var pen = new Pen(Color.Pink, 2); graphics.DrawRectangle (pen, borderPosition - (BorderWidth / 2), 0, BorderWidth, srcArea.Height); } // PictureBox1に表示する this.pictureBox1.Image = canvas; } private void pictureBox1_MouseDown(object sender, MouseEventArgs e) { if (this.srcImage == null || this.destinationImage == null || !e.Button.Equals(MouseButtons.Left)) { return; } var mousePoint = e.Location; if (this.IsOnBorderArea( mousePoint, this.borderPositionRate, this.destinationImage.Height)) { this.mousePoint = mousePoint; } } private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { if (this.srcImage == null || this.destinationImage == null) { return; } var mousePoint = e.Location; if (this.IsOnBorderArea( mousePoint, this.borderPositionRate, this.destinationImage.Height)) { this.pictureBox1.Cursor = Cursors.VSplit; } else { this.pictureBox1.Cursor = Cursors.Default; } if (!this.mousePoint.IsEmpty) { var rate = mousePoint.X / (double)this.pictureBox1.Width; double minRate = BorderWidth / (double)this.pictureBox1.Width; double maxRate = (this.pictureBox1.Width - BorderWidth) / (double)this.pictureBox1.Width; if (rate >= minRate && rate < maxRate) { this.borderPositionRate = rate; } else if (rate >= maxRate) { this.borderPositionRate = maxRate; } else { this.borderPositionRate = minRate; } this.Draw(this.srcImage, this.destinationImage, this.borderPositionRate); this.mousePoint = mousePoint; this.pictureBox1.Invalidate(); } } private void pictureBox1_MouseUp(object sender, MouseEventArgs e) { this.mousePoint = Point.Empty; } private bool IsOnBorderArea(Point targetPoint, double borderPositionRate, int height) { int borderPosition = (int)Math.Round( this.pictureBox1.Width * borderPositionRate, MidpointRounding.AwayFromZero); var borderArea = new Rectangle(borderPosition - (BorderWidth / 2), 0, BorderWidth, height); return borderArea.Contains(targetPoint); } } }
■ 補足:ツールチップの実装
* 上記のサンプルに、左側と右側で別のToolTip(ツールチップ)を表示するようには 以下の関連記事を参照のこと。Tooltip [2] ~ 1つのPictureBoxに複数のToolTipを表示するには... ~
https://blogs.yahoo.co.jp/dk521123/38052822.html
参考文献
https://dobon.net/vb/dotnet/graphics/triming.htmlhttps://imagingsolution.net/program/csharp/csharp_image_roi/
https://gya-ia.hatenablog.com/entry/20151201/1448902907
公式サイト
https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/advanced/how-to-crop-and-scale-images関連記事
Windows Form
Windows Form ~ 目次 ~https://blogs.yahoo.co.jp/dk521123/8054245.html
Splitter ~ 画像比較スライダーをWindows Formで実装する ~
https://blogs.yahoo.co.jp/dk521123/37846450.html
Tooltip [2] ~ 1つのPictureBoxに複数のToolTipを表示するには... ~
https://blogs.yahoo.co.jp/dk521123/38052822.html