ピクチャーボックスにスクロールバーをつけるにはパネルやユーザーコントロールのうえにピクチャーボックスを貼り付け、パネルのAutoScrollプロパティを trueにするとともにPictureBox1.SizeModeプロパティをPictureBoxSizeMode.AutoSizeに設定します。PictureBoxSizeMode.AutoSizeに設定することで大きな画像を表示するときはピクチャーボックスが大きくなるので、パネルのAutoScrollプロパティをtrueにしておくと自動的にスクロールバーが表示されます。
これだけでは面白くないので他の機能も追加します。ピクチャーボックスをドラッグするとその部分に枠を表示させます。そしてその部分をトリミングできるようにします。
ではコードをみてみましょう。
DoesDrawDragedRectangleプロパティとDragedRectangleColorプロパティを独自に追加しました。マウスがドラッグされているとき矩形を描画するか? その場合、どの色を表示するかを設定できあす。
またマウスでピクチャーボックスをクリックしたときやマウスボタンを離したとき、その上を移動したときにもイベントの処理ができるようにしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
public partial class ScrollPictureBox : UserControl { public ScrollPictureBox() { InitializeComponent(); pictureBox1.Location = new Point(0,0); pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize; this.AutoScroll = true; this.BorderStyle = BorderStyle.Fixed3D; pictureBox1.MouseDown += PictureBox1_MouseDown; pictureBox1.MouseUp += PictureBox1_MouseUp; pictureBox1.MouseMove += PictureBox1_MouseMove; pictureBox1.Paint += PictureBox1_Paint; this.AllowDrop = true; } public Bitmap Bitmap { set { pictureBox1.Image = value; } get { return (Bitmap)pictureBox1.Image; } } // マウスがドラッグされているとき矩形を描画するか? public bool DoesDrawDragedRectangle { get; set; } = true; public Color DragedRectangleColor { get; set; } = Color.Black; // 矩形を描画するためにマウスがドラッグされている bool IsDrawingDragRectangle = false; // DragedRectangleクラスは後述 DragedRectangle DragedRectangle = null; public delegate void PictureBoxMouseDownHandler(object sender, MouseEventArgs e); public event PictureBoxMouseDownHandler PictureBoxMouseDown; public event PictureBoxMouseDownHandler PictureBoxMouseMove; public event PictureBoxMouseDownHandler PictureBoxMouseUp; private void PictureBox1_MouseDown(object sender, MouseEventArgs e) { // ピクチャーボックスに画像が表示されていて // DoesDrawDragedRectangleプロパティがtrueのときだけ処理をする if (DoesDrawDragedRectangle && pictureBox1.Image != null) { IsDrawingDragRectangle = true; // ドラッグ開始位置をDragedRectangleオブジェクト内に格納する DragedRectangle = new DragedRectangle(pictureBox1); DragedRectangle.RectangleStart = new Point(e.X, e.Y); } // これとは別にピクチャーボックスがクリックされたときにイベント処理ができるようにする PictureBoxMouseDown?.Invoke(this, e); } private void PictureBox1_MouseMove(object sender, MouseEventArgs e) { if (IsDrawingDragRectangle) { // ドラッグ開始位置と現在のマウスの位置から矩形を表示する DragedRectangle.RectangleEnd = new Point(e.X, e.Y); pictureBox1.Invalidate(); } // これとは別にピクチャーボックス上でマウスが移動したときにイベント処理ができるようにする PictureBoxMouseMove?.Invoke(this, e); } private void PictureBox1_MouseUp(object sender, MouseEventArgs e) { // ドラッグが終了したので終了処理をする IsDrawingDragRectangle = false; OnFinishedDragRectangle(); DragedRectangle = null; // これとは別にピクチャーボックス上でマウスボタンが離されたときのイベント処理ができるようにする PictureBoxMouseUp?.Invoke(this, e); } // ドラッグが終了したイベントを発生させる public delegate void FinishedDragRectangleHandler(object sender, TrimmedBitmapArgs e); public event FinishedDragRectangleHandler FinishedDragRectangle; protected void OnFinishedDragRectangle() { // ここでトリミングされた画像や上下左右の切り捨てられた部分を取得する if (Bitmap != null) FinishedDragRectangle?.Invoke(this, new TrimmedBitmapArgs(Bitmap, DragedRectangle.GetRectangle())); } // ドラッグによって描画された矩形を消去する public void ClearRectangle() { DragedRectangle = null; pictureBox1.Invalidate(); } // ピクチャーボックスでPaintイベントを処理できるようにする public delegate void PaintEventHandler(object sender, PaintEventArgs e); public event PaintEventHandler PictureBoxPaint; private void PictureBox1_Paint(object sender, PaintEventArgs e) { if(DragedRectangle != null) e.Graphics.DrawRectangle(new Pen(DragedRectangleColor), DragedRectangle.GetRectangle()); PictureBoxPaint?.Invoke(this, e); } // ピクチャーボックスの再描画 public void PictureBoxInvalidate() { pictureBox1.Invalidate(); } } |
次にDragedRectangleクラスを示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
public class DragedRectangle { public Point RectangleStart = new Point(); public Point RectangleEnd = new Point(-1, -1); PictureBox PictureBox = null; public DragedRectangle(PictureBox pictureBox) { PictureBox = pictureBox; } public Rectangle GetRectangle() { if (RectangleEnd.X == -1 && RectangleEnd.Y == -1) return new Rectangle(); if (RectangleEnd.X < 0) RectangleEnd.X = 0; if (RectangleEnd.X > PictureBox.Width) RectangleEnd.X = PictureBox.Width; if (RectangleEnd.Y < 0) RectangleEnd.Y = 0; if (RectangleEnd.Y > PictureBox.Height) RectangleEnd.Y = PictureBox.Height; int width = Math.Abs(RectangleEnd.X - RectangleStart.X); int height = Math.Abs(RectangleEnd.Y - RectangleStart.Y); int x = RectangleStart.X; if (x > RectangleEnd.X) x = RectangleEnd.X; int y = RectangleStart.Y; if (y > RectangleEnd.Y) y = RectangleEnd.Y; return new Rectangle(x, y, width, height); } } |
それからイベントハンドラの引数になっているTrimmedBitmapArgsクラスを示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
public class TrimmedBitmapArgs : EventArgs { public TrimmedBitmapArgs(Bitmap bitmap, Rectangle rect) { X = rect.X; Y = rect.Y; Width = rect.Width; Height = rect.Height; MarginTop = rect.Top; MarginLeft = rect.Left; MarginRight = bitmap.Width - rect.Right; MarginBottom = bitmap.Height - rect.Bottom; if (Width <= 0 || Height <= 0) { Bitmap = null; return; } Bitmap = new Bitmap(Width, Height); Graphics g = Graphics.FromImage(Bitmap); g.DrawImage(bitmap, new Rectangle(0, 0, rect.Width, rect.Height), new Rectangle(rect.X, rect.Y, rect.Width, rect.Height), GraphicsUnit.Pixel); g.Dispose(); } public int X { get; protected set; } = 0; public int Y { get; protected set; } = 0; public int Width { get; protected set; } = 0; public int Height { get; protected set; } = 0; public int MarginTop { get; protected set; } = 0; public int MarginLeft { get; protected set; } = 0; public int MarginRight { get; protected set; } = 0; public int MarginBottom { get; protected set; } = 0; public Bitmap Bitmap { get; protected set; } } |
最後に上下左右の切り落とす部分を指定してトリミングされた画像を取得するための静的クラス TrimmedBitmap を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
static public class TrimmedBitmap { static public Bitmap GetTrimmedBitmap(Bitmap bitmap, int marginLeft, int marginTop, int marginRight, int marginBottom) { int rectWidth = bitmap.Width - marginLeft - marginRight; int rectHeight = bitmap.Height - marginTop - marginBottom; Rectangle rect = new Rectangle(marginLeft, marginTop, rectWidth, rectHeight); Bitmap newBitmap = new Bitmap(rect.Width, rect.Height); Graphics g = Graphics.FromImage(newBitmap); g.DrawImage(bitmap, new Rectangle(0, 0, rect.Width, rect.Height), new Rectangle(rect.X, rect.Y, rect.Width, rect.Height), GraphicsUnit.Pixel); g.Dispose(); return newBitmap; } } |
次回はこれをつかってアプリをつくります。