マウスをドラッグすることで直線や曲線を引くことができるようにします。
まずメニューを追加します。
そしてEditMode列挙体にDrawLineとFreeLineを追加します。
1 2 3 4 5 6 7 8 9 10 |
public enum EditMode { Selection, DrawRectangle, FillRectangle, DrawEllipse, FillEllipse, DrawLine, FreeLine, } |
メニューが選択されたらメニューのチェックのOn、offをおこないます。
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 |
public partial class Form1 : Form { private void DrawLineMenuItem_Click(object sender, EventArgs e) { CheckMenu1(DrawLineMenuItem); userControlImage1.EditMode = EditMode.DrawLine; } private void FreeLineMenuItem_Click(object sender, EventArgs e) { CheckMenu1(FreeLineMenuItem); userControlImage1.EditMode = EditMode.FreeLine; } void CheckMenu1(ToolStripMenuItem menuItem) { SelectionMenuItem.Checked = false; DrawFigureMenuItem.Checked = false; DrawRectangleMenuItem.Checked = false; FillRectangleMenuItem.Checked = false; DrawEllipseMenuItem.Checked = false; FillEllipseMenuItem.Checked = false; DrawLineMenuItem.Checked = false; FreeLineMenuItem.Checked = false; if(menuItem == SelectionMenuItem) SelectionMenuItem.Checked = true; else if(menuItem == DrawRectangleMenuItem) { DrawFigureMenuItem.Checked = true; DrawRectangleMenuItem.Checked = true; } else if(menuItem == FillRectangleMenuItem) { DrawFigureMenuItem.Checked = true; FillRectangleMenuItem.Checked = true; } else if(menuItem == DrawEllipseMenuItem) { DrawFigureMenuItem.Checked = true; DrawEllipseMenuItem.Checked = true; } else if(menuItem == FillEllipseMenuItem) { DrawFigureMenuItem.Checked = true; FillEllipseMenuItem.Checked = true; } else if(menuItem == DrawLineMenuItem) { DrawFigureMenuItem.Checked = true; DrawLineMenuItem.Checked = true; } else if(menuItem == FreeLineMenuItem) { DrawFigureMenuItem.Checked = true; FreeLineMenuItem.Checked = true; } } } |
直線や自由直線を描画するためにマウスクリックに関するイベントハンドラを修正します。直線を描画するときにマウスがクリックされたらOnMouseDownForDrawLineメソッドを、曲線を描画するときにマウスがクリックされたらOnMouseDownForDrawFreeLineメソッドが呼ぶようにします。
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 |
public partial class UserControlImage : UserControl { List<Point> linePoints = null; private void PictureBox1_MouseDown(object sender, MouseEventArgs e) { if(Bitmap == null) return; // 範囲外におけるクリック if(e.X + ScrollBarPosX >= Bitmap.Width || e.Y + ScrollBarPosY >= Bitmap.Height) { OnMouseDownOutOfBitmap(); return; } // クリックされた場所の色を通知する if(PictureBoxMouseDown != null) { Color color = Bitmap.GetPixel(e.X + ScrollBarPosX, e.Y + ScrollBarPosY); PictureBoxMouseDown(this, new PictureBox1MouseDownArgs(e.X + ScrollBarPosX, e.Y + ScrollBarPosY, color)); } if(BitmapRectangle == null) { if(EditMode == EditMode.Selection) OnMouseDownForSelectRectangle(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); if(EditMode == EditMode.DrawRectangle || EditMode == EditMode.FillRectangle || EditMode == EditMode.DrawEllipse || EditMode == EditMode.FillEllipse) OnMouseDownForDrawRectangle(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); // 追加部分(直線) if(EditMode == EditMode.DrawLine) OnMouseDownForDrawLine(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); // 追加部分(自由曲線) if(EditMode == EditMode.FreeLine) OnMouseDownForDrawFreeLine(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); } else { if(IsPointInRectangle(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY), BitmapRectangle.Rectangle)) OnMouseDownInBitmapRectangle(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); else OnMouseDownOutOfSelection(new Point(e.X + ScrollBarPosX, e.Y + ScrollBarPosY)); } } } |
メニューで[直線]が選択されているときマウスがクリックされたときの処理を示します。
1 2 3 4 5 6 7 8 9 |
public partial class UserControlImage : UserControl { void OnMouseDownForDrawLine(Point bitmapPoint) { isMouseDown = true; pictureBox1.Capture = true; startPoint = new Point(bitmapPoint.X, bitmapPoint.Y); } } |
メニューで[自由曲線]が選択されているときマウスがクリックされたときの処理を示します。
1 2 3 4 5 6 7 8 9 10 11 12 |
public partial class UserControlImage : UserControl { void OnMouseDownForDrawFreeLine(Point bitmapPoint) { isMouseDown = true; pictureBox1.Capture = true; startPoint = new Point(bitmapPoint.X, bitmapPoint.Y); linePoints = new List<Point>(); linePoints.Add(bitmapPoint); } } |
次にドラッグされているときのイベントハンドラを修正します。
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 { 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)); return; } // 追加部分 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)); } } } |
メニューで[直線]が選択されているときマウスがドラッグされているときの処理を示します。
startPointとendPointを調べて直線を描画しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public partial class UserControlImage : UserControl { void OnMouseMoveForDrawLine(Point bitmapPoint) { endPoint = bitmapPoint; Bitmap newBitmap = new Bitmap(Bitmap); Graphics g = Graphics.FromImage(newBitmap); if(EditMode == EditMode.DrawLine) g.DrawLine(new Pen(DrawColor), startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); g.Dispose(); ShowBitmap(newBitmap); } } |
メニューで[自由曲線]が選択されているときマウスがドラッグされているときの処理を示します。
マウスが動くたびにendPointをリストにいれていき、各点を結ぶ直線を描画して曲線を描画しているようにみせかけています。
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 OnMouseMoveForDrawFreeLine(Point bitmapPoint) { endPoint = bitmapPoint; Bitmap newBitmap = new Bitmap(Bitmap); linePoints.Add(bitmapPoint); if(linePoints.Count < 2) return; Point fromPoint = linePoints[0]; Point[] points = linePoints.Skip(1).ToArray(); Graphics g = Graphics.FromImage(newBitmap); if(EditMode == EditMode.FreeLine) { foreach(Point toPoint in points) { g.DrawLine(new Pen(DrawColor), fromPoint.X, fromPoint.Y, toPoint.X, toPoint.Y); fromPoint = toPoint; } } g.Dispose(); ShowBitmap(newBitmap); } } |
マウスボタンが離されたらイベントを発生させます。
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 |
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; } } } |
メニューで[直線]が選択されているとき、マウスボタンが離されたときの処理を示します。
startPointとendPointのあいだに直線を描画して、startPointとendPointに不適切な値を代入しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public partial class UserControlImage : UserControl { void OnMouseUpForDrawLine(Point bitmapPoint) { isMouseDown = false; endPoint = bitmapPoint; Bitmap newBitmap = new Bitmap(Bitmap); Graphics g = Graphics.FromImage(newBitmap); if(EditMode == EditMode.DrawLine) g.DrawLine(new Pen(DrawColor), startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); g.Dispose(); Bitmap = newBitmap; ShowBitmap(newBitmap); startPoint = new Point(-1, -1); endPoint = new Point(-1, -1); } } |
メニューで[自由曲線]が選択されているとき、マウスボタンが離されたときの処理を示します。
linePointsに格納した点をとりだし、これらを結ぶ直線を描画して自由曲線を描画しています。おわったらstartPointとendPointに不適切な値を代入しています。
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 |
public partial class UserControlImage : UserControl { void OnMouseUpForDrawFreeLine(Point bitmapPoint) { isMouseDown = false; endPoint = bitmapPoint; Bitmap newBitmap = new Bitmap(Bitmap); linePoints.Add(bitmapPoint); if(linePoints.Count < 2) return; Point fromPoint = linePoints[0]; Point[] points = linePoints.Skip(1).ToArray(); Graphics g = Graphics.FromImage(newBitmap); if(EditMode == EditMode.FreeLine) { foreach(Point toPoint in points) { g.DrawLine(new Pen(DrawColor), fromPoint.X, fromPoint.Y, toPoint.X, toPoint.Y); fromPoint = toPoint; } } g.Dispose(); Bitmap = newBitmap; ShowBitmap(newBitmap); startPoint = new Point(-1, -1); endPoint = new Point(-1, -1); } } |