これはちょっと不便なので、ドラッグしたら連続して色を設定できるようにできないかと考え、PictureBoxExクラスを以下のように変更しました。マウスがクリックされたらisMouseDownをtrueにし、isMouseDown==trueのときにマウス動くとそこにあるピクチャーボックスの背景色が連続で設定できる? ・・・と思ったらうまくいきませんでした。
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 class PictureBoxEx : PictureBox { static bool isMouseDown = false; public PictureBoxEx() { this.MouseDown += PictureBoxEx_MouseDown; this.MouseUp += PictureBoxEx_MouseUp; this.MouseMove += PictureBoxEx_MouseMove; } private void PictureBoxEx_MouseUp(object sender, MouseEventArgs e) { isMouseDown = false; } private void PictureBoxEx_MouseDown(object sender, MouseEventArgs e) { Form1 f = (Form1)FindForm(); this.BackColor = f.CurColor; isMouseDown = true; } private void PictureBoxEx_MouseMove(object sender, MouseEventArgs e) { if(isMouseDown) { Form1 f = (Form1)FindForm(); this.BackColor = f.CurColor; } } } |
PictureBoxEx_MouseMoveを以下のように変更すると、マウスを普通に動かすと背景色が設定されますが、マウスを押しているときは反応しません。
1 2 3 4 5 6 7 |
private void PictureBoxEx_MouseMove(object sender, MouseEventArgs e) { Form1 f = (Form1)FindForm(); this.BackColor = f.CurColor; } |
ということで、ピクチャーボックスを使ったやり方はうまくいかないので、以下のように変更しました。Panelに変更しました。あと後のことを考えてコンストラクタを変更しました。
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 class PanelEx : Panel { int Column = 0; int Row = 0; public PanelEx(int column, int row) { Column = column; Row = row; this.MouseDown += PanelEx_MouseDown; this.DragOver += PanelEx_DragOver; this.DragDrop += PanelEx_DragDrop; this.GiveFeedback += PanelEx_GiveFeedback; this.AllowDrop = true; } private void PanelEx_MouseDown(object sender, MouseEventArgs e) { Form1 f = (Form1)FindForm(); this.BackColor = f.CurColor; DoDragDrop(0, DragDropEffects.All); } private void PanelEx_DragOver(object sender, DragEventArgs e) { e.Effect = DragDropEffects.All; Form1 f = (Form1)FindForm(); this.BackColor = f.CurColor; } private void PanelEx_GiveFeedback(object sender, GiveFeedbackEventArgs e) { e.UseDefaultCursors = false; Cursor = Cursors.Arrow; } } |
Form1内はPictureBoxではなくPanelを使っているので、フィールド変数名とメソッドの名前を変えました。
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 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); } PanelEx[,] panels = new PanelEx[32,32]; private void Form1_Load(object sender, EventArgs e) { for(int row = 0; row < 32; row++) { for(int column = 0; column < 32; column++) { var box = CreateColorPanel(column, row); panels[column, row] = box; } } CurColor = Color.Black; } PanelEx CreateColorPanel(int i, int j) { int size = 14; PanelEx box = new PanelEx(i, j); box.Size = new Size(size, size); box.Location = new Point(size * i, size * j); box.Parent = panel1; box.BorderStyle = BorderStyle.FixedSingle; return box; } private void button1_Click(object sender, EventArgs e) { Bitmap bmp = new Bitmap(32, 32); for(int row = 0; row < 32; row++) { for(int column = 0; column < 32; column++) { bmp.SetPixel(column, row, panels[column, row].BackColor); } } SaveFileDialog dlg = new SaveFileDialog(); dlg.Filter = "アイコン| *.ico"; if(dlg.ShowDialog() != DialogResult.OK) return; //ビットマップをアイコンへ変換 Icon icon = Icon.FromHandle(bmp.GetHicon()); Stream outStream = new FileStream(dlg.FileName, FileMode.Create, FileAccess.Write); icon.Save(outStream); outStream.Dispose(); bmp.Dispose(); icon.Dispose(); } Color curColor = new Color(); public Color CurColor { get { return curColor; } set { curColor = value; pictureBox1.BackColor = value; } } private void buttonColor_Click(object sender, EventArgs e) { if(colorDialog1.ShowDialog() == DialogResult.OK) CurColor = colorDialog1.Color; } } |
あと四角形も描画できるようにしました。
フリーと四角形の描画の選択ができるようにしています。GetCheckedRadioButtonメソッドはラジオボタンがチェックされているのかを知るためのものです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public partial class Form1 : Form { public CheckedRadioButton GetCheckedRadioButton() { if(radioButtonFree.Checked) return CheckedRadioButton.Free; else if(radioButtonRectangle.Checked) return CheckedRadioButton.Rectangle; else return CheckedRadioButton.Free; } public enum CheckedRadioButton { Free = 0, Rectangle = 1, } } |
四角形を描画するにはドラッグがはじまった場所と終わった場所を知る必要があります。そこでBeginRectangleとEndRectangleというイベントでこれを取得しています。
ドロップされた場所がPanelExのうえであればいいのですが、そうでない場合もあります。それを検出するためにDoDragDropのあとにもEndRectangleが発生するようにしています。
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 |
public class PanelEx : Panel { int Column = 0; int Row = 0; public delegate void XYHandler(object sender, XY e); public event XYHandler BeginRectangle; public event XYHandler EndRectangle; public PanelEx(int column, int row) { Column = column; Row = row; this.MouseDown += PanelEx_MouseDown; this.DragOver += PanelEx_DragOver; this.DragDrop += PanelEx_DragDrop; this.GiveFeedback += PanelEx_GiveFeedback; this.AllowDrop = true; } private void PanelEx_MouseDown(object sender, MouseEventArgs e) { Form1 f = (Form1)FindForm(); this.BackColor = f.CurColor; if(f.GetCheckedRadioButton() == Form1.CheckedRadioButton.Rectangle) { BeginRectangle?.Invoke(this, new XY(Column, Row)); DoDragDrop(0, DragDropEffects.All); EndRectangle?.Invoke(this, new XY(-1, -1)); // Panel以外の部分でドロップされるかもしれないので } } private void PanelEx_DragOver(object sender, DragEventArgs e) { e.Effect = DragDropEffects.All; Form1 f = (Form1)FindForm(); if(f.GetCheckedRadioButton() == Form1.CheckedRadioButton.Free) { this.BackColor = f.CurColor; } } private void PanelEx_DragDrop(object sender, DragEventArgs e) { Form1 f = (Form1)FindForm(); if(f.GetCheckedRadioButton() == Form1.CheckedRadioButton.Rectangle) { EndRectangle?.Invoke(this, new XY(Column, Row)); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 |
public class XY { public XY(int x, int y) { X = x; Y = y; } public int X = 0; public int Y = 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public partial class Form1 : Form { PanelEx CreateColorPanel(int i, int j) { int size = 14; PanelEx box = new PanelEx(i, j); box.Size = new Size(size, size); box.Location = new Point(size * i, size * j); box.Parent = panel1; box.BorderStyle = BorderStyle.FixedSingle; box.BeginRectangle += Box_BeginRectangle; // ドラッグの開始 box.EndRectangle += Box_EndRectangle; // ドラッグの終了 return box; } } |
BeginRectangleイベントとEndRectangleイベントが発生した場合、どうすればいいのでしょうか? イベントハンドラに渡される引数を調べて、開始位置と終了位置を調べます。
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 |
public partial class Form1 : Form { int startX = -1, startY = -1; private void Box_BeginRectangle(object sender, XY e) { startX = e.X; startY = e.Y; } private void Box_EndRectangle(object sender, XY e) { // startX,startY、XYオブジェクトに格納されている値が適切である場合だけ処理をする if(startX != -1 && e.X != -1) { if(startX < e.X) { for(int i = startX; i <= e.X; i++) { panels[i, e.Y].BackColor = curColor; panels[i, startY].BackColor = curColor; } } else { for(int i = startX; i >= e.X; i--) { panels[i, e.Y].BackColor = curColor; panels[i, startY].BackColor = curColor; } } if(startY < e.Y) { for(int i = startY; i <= e.Y; i++) { panels[e.X, i].BackColor = curColor; panels[startX, i].BackColor = curColor; } } else { for(int i = startY; i >= e.Y; i--) { panels[e.X, i].BackColor = curColor; panels[startX, i].BackColor = curColor; } } } // 処理が終わったらstartX,startYに不適切な値をセットする。 startX = -1; startY = -1; } // その他のメソッドは前回と同じ } |
本当は円や直線、文字もやってみたいのだが、できるだろうか・・・