選択領域を拡大したり縮小することができるようにします。また拡大縮小ができることを示すグリッパーも表示させます。
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 partial class UserControlImage : UserControl { const int GriperSize = 8; // 選択されている部分の境界線を描画する Bitmap DrawBoderRectangle(Bitmap bitmap) { Rectangle rect; if(BitmapRectangle == null) { rect = GetRectangle(startPoint, endPoint); } else { rect = BitmapRectangle.Rectangle; } Bitmap newBitmap = new Bitmap(bitmap); Graphics g = Graphics.FromImage(newBitmap); g.DrawRectangle(new Pen(GetBoderBrush()), rect); List<Rectangle> griperRects = new List<Rectangle>(); griperRects.Add(new Rectangle(new Point(rect.X, rect.Y), new Size(GriperSize, GriperSize))); griperRects.Add(new Rectangle(new Point(rect.X + rect.Width / 2 - GriperSize / 2, rect.Y), new Size(GriperSize, GriperSize))); griperRects.Add(new Rectangle(new Point(rect.Right - GriperSize, rect.Y), new Size(GriperSize, GriperSize))); griperRects.Add(new Rectangle(new Point(rect.X, rect.Bottom - GriperSize), new Size(GriperSize, GriperSize))); griperRects.Add(new Rectangle(new Point(rect.X + rect.Width / 2 - GriperSize / 2, rect.Bottom - GriperSize), new Size(GriperSize, GriperSize))); griperRects.Add(new Rectangle(new Point(rect.Right - GriperSize, rect.Bottom - GriperSize), new Size(GriperSize, GriperSize))); griperRects.Add(new Rectangle(new Point(rect.X, rect.Y + rect.Height / 2 - GriperSize / 2), new Size(GriperSize, GriperSize))); griperRects.Add(new Rectangle(new Point(rect.Right - GriperSize, rect.Y + rect.Height / 2 - GriperSize / 2), new Size(GriperSize, GriperSize))); g.FillRectangles(GetBoderBrush(), griperRects.ToArray()); g.Dispose(); return newBitmap; } } |
isMouseDownフラグがfalseのときマウスがクリックされるとIsPointInRectangleメソッドによって選択されている矩形内部でのクリックが判定されます。
矩形内部でのクリックである場合、OnMouseDownInBitmapRectangleメソッドのなかで以下のような処理がおこなわれます。IsMouseOnGriperメソッドはグリッパーがクリックされたかどうかを調べます。
グリッパーがクリックされた場合、フィールド変数dragGriperにその値が格納されます。またOnMouseDownForSizeChangeSelectionメソッドがよばれ、isMouseDownForSizeChangeフラグがセットされます。
列挙体GriperはGriper.Outは選択範囲の外、Griper.Inは選択範囲の内部であるけれどもグリッパーがある場所ではないことを示します。それ以外のときはグリッパーが選択されていることを示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public partial class UserControlImage : UserControl { Griper dragGriper = Griper.Out; isMouseDownForSizeChange = true; void OnMouseDownInBitmapRectangle(Point bitmapPoint) { dragGriper = IsMouseOnGriper(new Point(bitmapPoint.X, bitmapPoint.Y)); if(dragGriper != Griper.In && dragGriper != Griper.Out) { OnMouseDownForSizeChangeSelection(bitmapPoint, dragGriper); } else if(IsMouseOnGriper(new Point(bitmapPoint.X, bitmapPoint.Y)) == Griper.In) { OnMouseDownForMoveSelection(bitmapPoint); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public enum Griper { Out, In, North, East, South, West, NorthEast, NorthWest, SouthEast, SouthWest, } |
IsMouseOnGriperメソッドは以下のようになっています。矩形の隅や各辺の中点であればグリッパーであると判断します。
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 { Griper IsMouseOnGriper(Point bitmapPoint) { if(BitmapRectangle == null) return Griper.Out; Rectangle rect = BitmapRectangle.Rectangle; if(IsPointInRectangle(new Point(bitmapPoint.X, bitmapPoint.Y), rect)) { if(rect.X <= bitmapPoint.X && bitmapPoint.X <= rect.X + GriperSize) { if(rect.Y <= bitmapPoint.Y && bitmapPoint.Y <= rect.Y + GriperSize) return Griper.NorthWest; if(rect.Bottom - GriperSize <= bitmapPoint.Y && bitmapPoint.Y <= rect.Bottom) return Griper.SouthWest; if(rect.Y + rect.Height/2 - GriperSize/2 <= bitmapPoint.Y && bitmapPoint.Y <= rect.Y + rect.Height / 2 + GriperSize/2) return Griper.West; } if(rect.Right - GriperSize <= bitmapPoint.X && bitmapPoint.X <= rect.Right) { if(rect.Y <= bitmapPoint.Y && bitmapPoint.Y <= rect.Y + GriperSize) return Griper.NorthEast; if(rect.Bottom - GriperSize <= bitmapPoint.Y && bitmapPoint.Y <= rect.Bottom) return Griper.SouthEast; if(rect.Y + rect.Height / 2 - GriperSize/2 <= bitmapPoint.Y && bitmapPoint.Y <= rect.Y + rect.Height / 2 + GriperSize/2) return Griper.East; } if(rect.X + rect.Width/2 - GriperSize/2 <= bitmapPoint.X && bitmapPoint.X <= rect.X + rect.Width / 2 + GriperSize/2) { if(rect.Y <= bitmapPoint.Y && bitmapPoint.Y <= rect.Y + GriperSize) return Griper.North; if(rect.Bottom - GriperSize <= bitmapPoint.Y && bitmapPoint.Y <= rect.Bottom) return Griper.South; } return Griper.In; } else return Griper.Out; } } |
マウスが移動したときはisMouseDownForSizeChangeフラグがセットされている場合はBitmapRectangle_MouseMoveForSizeChangeメソッドを呼びます。
まずはイベントハンドラPictureBox1_MouseMoveの追加部分を示します。
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 { 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)); return; } 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)); } else ChangeCursorWhenMouseMoveOnSelection(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); if(isMouseDownForMove) OnMouseMoveForMoveSelection(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); // 追加部分 if(isMouseDownForSizeChange) OnMouseMoveForSizeChangeSelection(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); } } |
OnMouseMoveForSizeChangeSelectionメソッドはisMouseDownForSizeChangeフラグがセットされているとき(=選択範囲のサイズが変更されているとき)に呼び出されます。
注意することとして、どのグリッドをドラッグしているか、どの方向にドラッグしているかによってはBitmapRectangleのサイズがゼロになってしまうことがあります。そこでサイズと位置を変更したときにサイズがゼロにならないことを確認してからサイズ変更をおこなっています。
もしサイズがゼロになってしまう場合はサイズ変更を中止してstartPointとendPointに適切な座標を代入するとともに BitmapRectangle.UpdatePositionメソッドを呼ぶことでBitmapRectangleの位置とサイズを保存しています。
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 |
public partial class UserControlImage : UserControl { void OnMouseMoveForSizeChangeSelection(Point bitmapPoint) { int xMove = bitmapPoint.X - rectangleMoveStartMousePosX; int yMove = bitmapPoint.Y - rectangleMoveStartMousePosY; int x, y, width, height; x = BitmapRectangle.X; y = BitmapRectangle.Y; width = BitmapRectangle.Width; height = BitmapRectangle.Height; if(dragGriper == Griper.East) width = BitmapRectangle.OldWidth + xMove; if(dragGriper == Griper.South) height = BitmapRectangle.OldHeight + yMove; if(dragGriper == Griper.SouthEast) { width = BitmapRectangle.OldWidth + xMove; height = BitmapRectangle.OldHeight + yMove; } if(dragGriper == Griper.North) { y = BitmapRectangle.OldY + yMove; height = BitmapRectangle.OldHeight - yMove; } if(dragGriper == Griper.West) { x = BitmapRectangle.OldX + xMove; width = BitmapRectangle.OldWidth - xMove; } if(dragGriper == Griper.NorthWest) { x = BitmapRectangle.OldX + xMove; width = BitmapRectangle.OldWidth - xMove; y = BitmapRectangle.OldY + yMove; height = BitmapRectangle.OldHeight - yMove; } if(dragGriper == Griper.NorthEast) { width = BitmapRectangle.OldWidth + xMove; y = BitmapRectangle.OldY + yMove; height = BitmapRectangle.OldHeight - yMove; } if(dragGriper == Griper.SouthWest) { x = BitmapRectangle.OldX + xMove; width = BitmapRectangle.OldWidth - xMove; height = BitmapRectangle.OldHeight + yMove; } if(width <= 1 || height <= 1) { isMouseDownForSizeChange = false; startPoint = new Point(BitmapRectangle.Rectangle.Left, BitmapRectangle.Rectangle.Top); endPoint = new Point(BitmapRectangle.Rectangle.Right, BitmapRectangle.Rectangle.Bottom); BitmapRectangle.UpdatePosition(); return; } BitmapRectangle.X = x; BitmapRectangle.Width = width; BitmapRectangle.Y = y; BitmapRectangle.Height = height; ShowBitmap(DrawBoderRectangle(Bitmap)); Bitmap newBitmap = new Bitmap(Bitmap); Graphics g = Graphics.FromImage(newBitmap); if(blankBitmap != null) { g.DrawImage(blankBitmap.Bitmap, blankBitmap.Location); } Rectangle srcRect = new Rectangle(new Point(0, 0), BitmapRectangle.Size); Rectangle destRect = BitmapRectangle.Rectangle; g.DrawImage(BitmapRectangle.Bitmap, destRect, srcRect, GraphicsUnit.Pixel); g.Dispose(); ShowBitmap(DrawBoderRectangle(newBitmap)); } } |
次に選択領域のサイズ変更中にマウスボタンが離されたときの処理です。
このときはOnMouseUpForSizeChangeSelectionメソッドが呼ばれてisMouseDownForSizeChangeフラグがクリアされます。またBitmapRectangle.UpdatePositionが呼ばれてBitmapRectangleの位置とサイズが保存されます。
そして次に選択領域外でクリックされたときにUniteBitmapRectangleメソッドが呼ばれて一体化されます。
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 |
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)); return; } if(isMouseDownForMove) { OnMouseUpForMoveSelection(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); return; } if(isMouseDownForSizeChange) { OnMouseUpForSizeChangeSelection(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); } return; } void OnMouseUpForSizeChangeSelection(Point bitmapPoint) { isMouseDownForSizeChange = false; BitmapRectangle.UpdatePosition(); } } |
これで選択領域を拡大縮小ができるようになりました。しかし表示されている内容は拡大縮小されません。これを可能とするためにはBitmapRectangleクラスに手をいれる必要があります。長くなったので次回に続きます。