を参考にぬりつぶしの処理をおこないます。
まずメニューを追加します。そして選択されたらチェックマークがつくようにします。
1 2 3 4 5 6 7 8 9 10 11 |
public enum EditMode { Selection, DrawRectangle, FillRectangle, DrawEllipse, FillEllipse, DrawLine, FreeLine, FillColor, // 追加 } |
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 |
public partial class Form1 : Form { private void FillColorMenuItem_Click(object sender, EventArgs e) { CheckMenu1(FillColorMenuItem); userControlImage1.EditMode = EditMode.FillColor; } 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; FillColorMenuItem.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; } else if(menuItem == FillColorMenuItem) { FillColorMenuItem.Checked = true; } } } |
UserControlImageクラス側ではFillColorメソッドを作成します。このメソッドは引数で渡した場所にある点と同じ色でつながった部分を指定した色で塗りつぶします。
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 |
public partial class UserControlImage : UserControl { bool[,] isCheckedFillColor; public void FillColor(Point bitmapPoint, Color newColor) { if(Bitmap == null) return; Color oldColor = Bitmap.GetPixel(bitmapPoint.X, bitmapPoint.Y); Bitmap newBitmap = new Bitmap(Bitmap); isCheckedFillColor = new bool[newBitmap.Width, newBitmap.Height]; if(oldColor.ToArgb() == newColor.ToArgb()) return; var list = FillLine(newBitmap, bitmapPoint.X, bitmapPoint.Y, oldColor, newColor); List<Point> nextPoints = new List<Point>(); while(true) { foreach(var pt in list) nextPoints.AddRange(FillLine(newBitmap, pt.X, pt.Y, oldColor, newColor)); list = nextPoints.ToList(); nextPoints.Clear(); if(list.Count == 0) break; } Bitmap = newBitmap; ShowBitmap(Bitmap); } List<Point> FillLine(Bitmap bitmap, int x, int y, Color oldColor, Color newColor) { isCheckedFillColor[x, y] = true; List<Point> nextPoints = new List<Point>(); if(oldColor.ToArgb() == newColor.ToArgb()) return nextPoints; Color color = bitmap.GetPixel(x, y); if(color == oldColor) { bitmap.SetPixel(x, y, newColor); if(y - 1 >= 0 && !isCheckedFillColor[x, y - 1] && bitmap.GetPixel(x, y - 1) == oldColor) nextPoints.Add(new Point(x, y - 1)); if(y + 1 < bitmap.Height && !isCheckedFillColor[x, y + 1] && bitmap.GetPixel(x, y + 1) == oldColor) nextPoints.Add(new Point(x, y + 1)); } int tempX = x; while(true) { tempX--; if(tempX < 0) break; Color color1 = bitmap.GetPixel(tempX, y); if(color1 == oldColor) { bitmap.SetPixel(tempX, y, newColor); if(y - 1 >= 0 && !isCheckedFillColor[tempX, y - 1] && bitmap.GetPixel(tempX, y - 1) == oldColor) nextPoints.Add(new Point(tempX, y - 1)); if(y + 1 < bitmap.Height && !isCheckedFillColor[tempX, y + 1] && bitmap.GetPixel(tempX, y + 1) == oldColor) nextPoints.Add(new Point(tempX, y + 1)); } else break; } tempX = x; while(true) { tempX++; if(tempX >= bitmap.Width) break; Color color1 = bitmap.GetPixel(tempX, y); if(color1 == oldColor) { bitmap.SetPixel(tempX, y, newColor); if(y - 1 >= 0 && !isCheckedFillColor[tempX, y - 1] && bitmap.GetPixel(tempX, y - 1) == oldColor) nextPoints.Add(new Point(tempX, y - 1)); if(y + 1 < bitmap.Height && !isCheckedFillColor[tempX, y + 1] && bitmap.GetPixel(tempX, y + 1) == oldColor) nextPoints.Add(new Point(tempX, y + 1)); } else break; } if(nextPoints.Count == 0) return nextPoints; if(nextPoints.Count == nextPoints.Max(x1 => x1.X) - nextPoints.Min(x1 => x1.X) + 1) { List<Point> points = new List<Point>(); points.Add(nextPoints[0]); return points; } return nextPoints; } } |
あとはメニューの[同じ色の部分を塗りつぶす]が選択されているときにクリックされたときにFillColorメソッドを呼ぶだけです。ここでは
で作成したPictureBoxMouseDownイベントを利用しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); userControlImage1.PictureBoxMouseDown += UserControlImage1_PictureBoxMouseDown; userControlColorBox1.Anchor = AnchorStyles.Top | AnchorStyles.Right; userControlColorBox2.Anchor = AnchorStyles.Top | AnchorStyles.Right; userControlColorBox3.Anchor = AnchorStyles.Top | AnchorStyles.Right; pictureBoxSetColor.BackColor = userControlImage1.DrawColor; ShowInitBitmap(); } private void UserControlImage1_PictureBoxMouseDown(object sender, UserControlImage.PictureBox1MouseDownArgs e) { if(userControlImage1.EditMode == EditMode.FillColor) userControlImage1.FillColor(new Point(e.X, e.Y), userControlImage1.DrawColor); } } |