選択領域のサイズを変更できるだけでなく、編集領域のサイズそのものを変更できるようにします。
これはペイントですが、フィールドのサイズを変更するためのグリッパーが表示されています。そして範囲選択されているときはフィールドのサイズ変更用のグリッパーは非表示になります。
まずフィールドのサイズ変更用のグリッパーを表示させます。BitmapRectangle == nullのときは表示させてそうでないときは表示させません。またグリッパーを表示するのは下辺と右辺の中央と右下隅だけです。
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 |
public partial class UserControlImage : UserControl { public void ShowBitmap(Bitmap bitmap) { OptimizationScrloolBar(bitmap); // スクロールバー位置より元画像をトリミングして表示する Bitmap bitmap1 = GetBitmapDrawPictureBox(bitmap); // BitmapRectangle == nullのときだけサイズ変更用のグリッパーを表示 if(BitmapRectangle == null) { Graphics g = Graphics.FromImage(bitmap1); int x = bitmap.Width - ScrollBarPosX - GriperSize; int y = bitmap.Height - ScrollBarPosY - GriperSize; g.DrawRectangle(new Pen(Color.Red), new Rectangle(x, y, GriperSize, GriperSize)); x = bitmap.Width/2 - ScrollBarPosX - GriperSize/2; y = bitmap.Height - ScrollBarPosY - GriperSize; g.DrawRectangle(new Pen(Color.Black), new Rectangle(x, y, GriperSize, GriperSize)); x = bitmap.Width - ScrollBarPosX - GriperSize; y = bitmap.Height / 2 - ScrollBarPosY - GriperSize / 2; g.DrawRectangle(new Pen(Color.Black), new Rectangle(x, y, GriperSize, GriperSize)); g.DrawRectangle(new Pen(GetBoderBrush()), new Rectangle(-1, -1, bitmap.Width + 1, bitmap.Height + 1)); g.Dispose(); } pictureBox1.Image = bitmap1; } } |
スクロールバーを最適化するためのOptimizationScrloolBarですが、このとき表示させるビットマップはBitmapプロパティから取得されるものとは限らないので引数を追加しました。
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 |
public partial class UserControlImage : UserControl { void OptimizationScrloolBar(Bitmap bitmap) { // 横スクロールバーの初期位置、最小値、最大値を設定 hScrollBar1.Minimum = 0; if(bitmap.Width - pictureBox1.Width >= 0) { int largeChange = pictureBox1.Width * pictureBox1.Width / bitmap.Width; hScrollBar1.LargeChange = largeChange; hScrollBar1.Maximum = bitmap.Width - pictureBox1.Width + largeChange; } else hScrollBar1.Maximum = 0; // 縦スクロールバーと横スクロールバーの初期位置、最小値、最大値を設定する vScrollBar1.Minimum = 0; if(bitmap.Height - pictureBox1.Height >= 0) { int largeChange = pictureBox1.Height * pictureBox1.Height / bitmap.Height; vScrollBar1.LargeChange = largeChange; vScrollBar1.Maximum = bitmap.Height - pictureBox1.Height + largeChange; } else vScrollBar1.Maximum = 0; } } |
フィールドのサイズ変更用のグリッパーが表示されているときにマウスポインタがグリッパーのうえに来たときにマウスポインタを変更します。
どこも選択されていないときにサイズ変更用のグリッパーのうえにマウスポインタがあるかどうか調べてマウスポインタを変更するのはChangeCursorWhenMouseMoveOnSelectionメソッドの役割です。そこでChangeCursorWhenMouseMoveOnSelectionメソッドを修正します。
BitmapRectangle == nullのときはこれまでCursor = Cursors.Default;としていただけですが、今回は処理をおこないます。
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 |
public partial class UserControlImage : UserControl { void ChangeCursorWhenMouseMoveOnSelection(Point bitmapPoint) { if(BitmapRectangle != null) { Griper griper = IsMouseOnGriper(bitmapPoint); if(griper == Griper.Out) Cursor = Cursors.Default; if(griper == Griper.In) Cursor = Cursors.Hand; if(griper == Griper.NorthWest) Cursor = Cursors.SizeNWSE; if(griper == Griper.West) Cursor = Cursors.SizeWE; if(griper == Griper.SouthWest) Cursor = Cursors.SizeNESW; if(griper == Griper.NorthEast) Cursor = Cursors.SizeNESW; if(griper == Griper.East) Cursor = Cursors.SizeWE; if(griper == Griper.SouthEast) Cursor = Cursors.SizeNWSE; if(griper == Griper.North) Cursor = Cursors.SizeNS; if(griper == Griper.South) Cursor = Cursors.SizeNS; } else { // 追加部分 // BitmapRectangle == null のときはサイズ変更用のグリッパーのうえにマウスがあるかもしれない int harfWidth = Bitmap.Width / 2; int harfHeight = Bitmap.Height / 2; if(harfWidth -4 <= bitmapPoint.X && bitmapPoint.X <= harfWidth + 4 && Bitmap.Height -8 <= bitmapPoint.Y && bitmapPoint.Y <= Bitmap.Height ) Cursor = Cursors.SizeNS; else if(harfHeight - 4 <= bitmapPoint.Y && bitmapPoint.Y <= harfHeight + 4 && Bitmap.Width - 8 <= bitmapPoint.X && bitmapPoint.X <= Bitmap.Width ) Cursor = Cursors.SizeWE; else if(Bitmap.Width - 8 <= bitmapPoint.X && bitmapPoint.X <= Bitmap.Width && Bitmap.Height - 8 <= bitmapPoint.Y && bitmapPoint.Y <= Bitmap.Height ) Cursor = Cursors.SizeNWSE; else Cursor = Cursors.Default; } } } |
BitmapRectangle == nullのときにマウスがクリックされたら、サイズ変更用グリッパーのうえでクリックされたかどうか調べます。このときに呼び出されるのが自作メソッドIsMouseOnFirldGriperです。
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 |
public partial class UserControlImage : UserControl { void OnMouseDownForSelectRectangle(Point bitmapPoint) { Griper griper = IsMouseOnFirldGriper(bitmapPoint); // サイズ変更用グリッパーのうえでクリックされたかどうか // そうでないなら通常の範囲選択の開始として処理する if(griper == Griper.South || griper == Griper.East || griper == Griper.SouthEast) { // フラグをセットして、グリッパーの種類とクリックされた場所を保存しておく griperField = griper; isMouseDownForFieldSizeChange = true; bitmapPositionStartFieldSizeChangeX = bitmapPoint.X; bitmapPositionStartFieldSizeChangeY = bitmapPoint.Y; } else isMouseDown = true; pictureBox1.Capture = true; startPoint = new Point(bitmapPoint.X, bitmapPoint.Y); } Griper IsMouseOnFirldGriper(Point bitmapPoint) { if(BitmapRectangle == null) { int harfWidth = Bitmap.Width / 2; int harfHeight = Bitmap.Height / 2; // マウスがあるのはサイズ変更用のグリッパーのうえかどうか? if(harfWidth - GriperSize / 2 <= bitmapPoint.X && bitmapPoint.X <= harfWidth + GriperSize / 2 && Bitmap.Height - GriperSize <= bitmapPoint.Y && bitmapPoint.Y <= Bitmap.Height) return Griper.South; else if(harfHeight - GriperSize / 2 <= bitmapPoint.Y && bitmapPoint.Y <= harfHeight + GriperSize / 2 && Bitmap.Width - GriperSize <= bitmapPoint.X && bitmapPoint.X <= Bitmap.Width) return Griper.East; else if(Bitmap.Width - GriperSize <= bitmapPoint.X && bitmapPoint.X <= Bitmap.Width && Bitmap.Height - GriperSize <= bitmapPoint.Y && bitmapPoint.Y <= Bitmap.Height) return Griper.SouthEast; else return Griper.Out; } return Griper.Out; } } |
isMouseDownForFieldSizeChangeフラグがセットされている状態でマウスが移動しているときはフィールドのサイズが変更されようとしているときです。そのときは自作メソッドOnMouseMoveForSizeChangeFieldを呼び出します。
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 |
public partial class UserControlImage : UserControl { private void PictureBox1_MouseMove(object sender, MouseEventArgs e) { if(Bitmap == null) return; if(isMouseDown) { if(EditMode == EditMode.Selection) OnMouseMoveForSelectRectangle(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); if(EditMode == EditMode.DrawRectangle || EditMode == EditMode.FillRectangle || EditMode == EditMode.DrawEllipse || EditMode == EditMode.FillEllipse) OnMouseMoveForDrawRectangle(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); if(EditMode == EditMode.DrawLine) OnMouseMoveForDrawLine(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); if(EditMode == EditMode.FreeLine) OnMouseMoveForDrawFreeLine(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); if(EditMode == EditMode.SelectionFree) OnMouseMoveForSelectFreeArea(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); } else ChangeCursorWhenMouseMoveOnSelection(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); if(isMouseDownForMove) { if(EditMode == EditMode.SelectionFree) OnMouseMoveForMoveFreeLineSelection(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); else if(EditMode == EditMode.Selection) OnMouseMoveForMoveSelection(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); else if(EditMode == EditMode.DrawRectangle || EditMode == EditMode.FillRectangle || EditMode == EditMode.DrawEllipse || EditMode == EditMode.FillEllipse) OnMouseMoveForMoveSelection(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); } if(isMouseDownForSizeChange) OnMouseMoveForSizeChangeSelection(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); // 追加部分 if(isMouseDownForFieldSizeChange) OnMouseMoveForSizeChangeField(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); } } |
フィールドのサイズが変更されようとしているときは、フィールド変数griperFieldに保存されているデータから新しいビットマップを作成します。
実際にBitmapプロパティを変更するのではなく、新しく作成したビットマップを表示します。
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 |
public partial class UserControlImage : UserControl { void OnMouseMoveForSizeChangeField(Point bitmapPoint) { if(griperField == Griper.South || griperField == Griper.East || griperField == Griper.SouthEast) { int oldWidth = Bitmap.Width; int oldHeight = Bitmap.Height; int moveX = bitmapPoint.X - bitmapPositionStartFieldSizeChangeX; int moveY = bitmapPoint.Y - bitmapPositionStartFieldSizeChangeY; int newWidth = oldWidth + moveX; int newHeight = oldHeight + moveY; if(griperField == Griper.South) newWidth = oldWidth; if(griperField == Griper.East) newHeight = oldHeight; Bitmap bitmap = new Bitmap(newWidth, newHeight); Graphics g = Graphics.FromImage(bitmap); g.DrawImage(Bitmap, new Point(0, 0)); g.Dispose(); ShowBitmap(bitmap); bitmap.Dispose(); } } } |
最後にマウスボタンが離されたときの処理です。isMouseDownForFieldSizeChangeフラグがセットされているときにマウスボタンが離されたら自作メソッドOnMouseUpForSizeChangeFieldを呼び出します。
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 |
public partial class UserControlImage : UserControl { private void PictureBox1_MouseUp(object sender, MouseEventArgs e) { if(Bitmap == null) return; if(isMouseDown) { if(EditMode == EditMode.Selection) OnMouseUpForSelectRectangle(); if(EditMode == EditMode.DrawRectangle || EditMode == EditMode.FillRectangle || EditMode == EditMode.DrawEllipse || EditMode == EditMode.FillEllipse) OnMouseUpForDrawRectangle(); if(EditMode == EditMode.DrawLine) OnMouseUpForDrawLine(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); if(EditMode == EditMode.FreeLine) OnMouseUpForDrawFreeLine(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); if(EditMode == EditMode.SelectionFree) OnMouseUpForSelectFreeArea(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); return; } if(isMouseDownForMove) { if(EditMode == EditMode.SelectionFree) OnMouseUpForMoveFreeLineSelection(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); else OnMouseUpForMoveSelection(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); } if(isMouseDownForSizeChange) OnMouseUpForSizeChangeSelection(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); // 追加部分 if(isMouseDownForFieldSizeChange) OnMouseUpForSizeChangeField(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); return; } void OnMouseUpForSizeChangeField(Point bitmapPoint) { Griper griper = griperField; // フィールド変数をもとに戻す isMouseDownForFieldSizeChange = false; startPoint = new Point(); griperField = Griper.Out; if(griper == Griper.South || griper == Griper.East || griper == Griper.SouthEast) { int oldWidth = Bitmap.Width; int oldHeight = Bitmap.Height; int moveX = bitmapPoint.X - bitmapPositionStartFieldSizeChangeX; int moveY = bitmapPoint.Y - bitmapPositionStartFieldSizeChangeY; int newWidth = oldWidth + moveX; int newHeight = oldHeight + moveY; if(griper == Griper.South) newWidth = oldWidth; if(griper == Griper.East) newHeight = oldHeight; Bitmap newBitmap = new Bitmap(newWidth, newHeight); Graphics g = Graphics.FromImage(newBitmap); g.DrawImage(Bitmap, new Point(0, 0)); g.Dispose(); Bitmap = newBitmap; ShowBitmap(Bitmap); } } } |
それから範囲選択がされた場合はフィールドサイズ変更用のグリッパーを非表示にする必要があります。そのためOnMouseUpForSelectRectangleメソッドを一部修正しています。
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 |
public partial class UserControlImage : UserControl { void OnMouseUpForSelectRectangle() { isMouseDown = false; Rectangle rect = GetRectangle(startPoint, endPoint); if(rect.IsEmpty || rect.Width == 0 || rect.Height == 0) { startPoint = new Point(-1, -1); endPoint = new Point(-1, -1); return; } Bitmap bitmap = new Bitmap(rect.Width, rect.Height); Graphics g = Graphics.FromImage(bitmap); Rectangle destRect = new Rectangle(0, 0, rect.Width, rect.Height); g.DrawImage(Bitmap, destRect, rect, GraphicsUnit.Pixel); g.Dispose(); BitmapRectangle = new BitmapRectangle(new Bitmap(bitmap), rect); g.Dispose(); if(blankBitmap == null) CreateBlankBitmap(BitmapRectangle.Rectangle); } } |