前回は範囲選択ができるようにしました。それだけでは不十分です。範囲選択された部分を移動できるようにする必要があります。
移動させるだけなら簡単なのですが、範囲選択された部分が通過した場合は以前の色を復元する必要があります。そこで移動したブロックが通過する前に各パネルがそのときの色を保存して通過後に復元できるようにしました。
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 { // 範囲選択されているブロックが左に移動する void MoveSelectionLeft() { if(SelectionXYs.Count == 0) return; var oldSelectionXYs = SelectionXYs.ToList(); int minX = SelectionXYs.Min(x => x.X); int maxX = SelectionXYs.Max(x => x.X); int minY = SelectionXYs.Min(x => x.Y); int maxY = SelectionXYs.Max(x => x.Y); ClearSelectionXYs(); // 通過前に保存 for(int row = minY; row <= maxY; row++) { if(minX - 1 >= 0) panels[minX - 1, row].oldColor = panels[minX - 1, row].BackColor; } // 変更 for(int colum = minX; colum <= maxX; colum++) { for(int row = minY; row <= maxY; row++) { if(colum - 1 >= 0) panels[colum - 1, row].BackColor = panels[colum, row].BackColor; } } // 通過後に復元 for(int row = minY; row <= maxY; row++) { if(panels[maxX, row].oldColor == Color.Empty) panels[maxX, row].BackColor = Color.Empty; else panels[maxX, row].BackColor = panels[maxX, row].oldColor; } SelectionXYs = oldSelectionXYs.Select(x => { x.X--; return x; }).ToList(); foreach(var o in SelectionXYs) { // 0~31の範囲内でない場合は調整が必要 int newX = o.X; int newY = o.Y; if(newX < 0) o.X = 0; if(newX > 31) o.X = 31; if(newY < 0) o.Y = 0; if(newY > 31) o.Y = 31; o.oldColor = panels[o.X, o.Y].BackColor; panels[o.X, o.Y].BackColor = Color.Tan; } // 調整によってダブりができるので除去する SelectionXYs = SelectionXYs.Distinct().ToList(); } } |
選択範囲が0~31を超えてしまった場合に調整をしていますが、これによってダブりがでるのでDistinct()で除去しています。Distinctメソッドがうまく機能するようにXYクラスに以下を追加します。
1 2 3 4 5 6 7 8 9 10 11 |
public class XY { public override bool Equals(object obj) { var p = obj as XY; if(p == null) return false; return (this.X == p.X && this.Y == p.Y); } public override int GetHashCode() => X.GetHashCode() ^ Y.GetHashCode(); } |
範囲選択されているブロックは左だけでなく上下左右に移動するので、対応できるように以下のメソッドを追加します。
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 |
public partial class Form1 : Form { void MoveSelectionUp() { if(SelectionXYs.Count == 0) return; var oldSelectionXYs = SelectionXYs.ToList(); int minX = SelectionXYs.Min(x => x.X); int maxX = SelectionXYs.Max(x => x.X); int minY = SelectionXYs.Min(x => x.Y); int maxY = SelectionXYs.Max(x => x.Y); ClearSelectionXYs(); for(int colum = minX; colum <= maxX; colum++) { if(minY - 1 >= 0) panels[colum, minY - 1].oldColor = panels[colum, minY - 1].BackColor; } for(int row = minY; row <= maxY; row++) { for(int colum = minX; colum <= maxX; colum++) { if(row - 1 >= 0) panels[colum, row - 1].BackColor = panels[colum, row].BackColor; } } for(int colum = minX; colum <= maxX; colum++) { if(panels[colum, maxY].oldColor == Color.Empty) panels[colum, maxY].BackColor = Color.Empty; else panels[colum, maxY].BackColor = panels[colum, maxY].oldColor; } SelectionXYs = oldSelectionXYs.Select(x => { x.Y--; return x; }).ToList(); foreach(var o in SelectionXYs) { int newX = o.X; int newY = o.Y; if(newX < 0) o.X = 0; if(newX > 31) o.X = 31; if(newY < 0) o.Y = 0; if(newY > 31) o.Y = 31; o.oldColor = panels[o.X, o.Y].BackColor; panels[o.X, o.Y].BackColor = Color.Tan; } SelectionXYs = SelectionXYs.Distinct().ToList(); } } |
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 |
public partial class Form1 : Form { void MoveSelectionDown() { if(SelectionXYs.Count == 0) return; var oldSelectionXYs = SelectionXYs.ToList(); int minX = SelectionXYs.Min(x => x.X); int maxX = SelectionXYs.Max(x => x.X); int minY = SelectionXYs.Min(x => x.Y); int maxY = SelectionXYs.Max(x => x.Y); ClearSelectionXYs(); for(int colum = minX; colum <= maxX; colum++) { if(maxY + 1 < 32) panels[colum, maxY + 1].oldColor = panels[colum, maxY + 1].BackColor; } for(int row = maxY; row >= minY; row--) { for(int colum = minX; colum <= maxX; colum++) { if(row + 1 < 32) panels[colum, row + 1].BackColor = panels[colum, row].BackColor; } } for(int colum = minX; colum <= maxX; colum++) { if(panels[colum, minY].oldColor == Color.Empty) panels[colum, minY].BackColor = Color.Empty; else panels[colum, minY].BackColor = panels[colum, minY].oldColor; } SelectionXYs = oldSelectionXYs.Select(x => { x.Y++; return x; }).ToList(); foreach(var o in SelectionXYs) { int newX = o.X; int newY = o.Y; if(newX < 0) o.X = 0; if(newX > 31) o.X = 31; if(newY < 0) o.Y = 0; if(newY > 31) o.Y = 31; o.oldColor = panels[o.X, o.Y].BackColor; panels[o.X, o.Y].BackColor = Color.Tan; } SelectionXYs = SelectionXYs.Distinct().ToList(); } } |
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 |
public partial class Form1 : Form { void MoveSelectionRight() { if(SelectionXYs.Count == 0) return; var oldSelectionXYs = SelectionXYs.ToList(); int minX = SelectionXYs.Min(x => x.X); int maxX = SelectionXYs.Max(x => x.X); int minY = SelectionXYs.Min(x => x.Y); int maxY = SelectionXYs.Max(x => x.Y); ClearSelectionXYs(); for(int row = minY; row <= maxY; row++) { if(maxX + 1 < 32) panels[maxX + 1, row].oldColor = panels[maxX + 1, row].BackColor; } for(int colum = maxX; colum >= minX; colum--) { for(int row = minY; row <= maxY; row++) { if(colum + 1 < 32) panels[colum + 1, row].BackColor = panels[colum, row].BackColor; } } for(int row = minY; row <= maxY; row++) { if(panels[minX, row].oldColor == Color.Empty) panels[minX, row].BackColor = Color.Empty; else panels[minX, row].BackColor = panels[minX, row].oldColor; } SelectionXYs = oldSelectionXYs.Select(x => { x.X++; return x; }).ToList(); foreach(var o in SelectionXYs) { int newX = o.X; int newY = o.Y; if(newX < 0) o.X = 0; if(newX > 31) o.X = 31; if(newY < 0) o.Y = 0; if(newY > 31) o.Y = 31; o.oldColor = panels[o.X, o.Y].BackColor; panels[o.X, o.Y].BackColor = Color.Tan; } SelectionXYs = SelectionXYs.Distinct().ToList(); } } |
範囲選択されているブロックが移動されるのはどのようなときでしょうか?
ラジオボタンで[範囲選択]が選択されている場合で、
実際に範囲選択がされた状態で、
範囲選択されている内部がクリックされてドロップが完了するまで
です。
まずは
ラジオボタンで[範囲選択]が選択されている場合で、
実際に範囲選択がされた状態で、
範囲選択されている内部がクリックされた
ときの処理です。
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 |
public partial class Form1 : Form { int SelectionMoveStartX = -1; int SelectionMoveStartY = -1; private void Box_BeginSelection(object sender, XY e) { if(SelectionXYs.Count != 0) { int minX = SelectionXYs.Min(x => x.X); int maxX = SelectionXYs.Max(x => x.X); int minY = SelectionXYs.Min(x => x.Y); int maxY = SelectionXYs.Max(x => x.Y); if(minX <= e.X && e.X <= maxX && minY <= e.Y && e.Y <= maxY) { // ラジオボタンで[範囲選択]が選択されている場合で、 // 実際に範囲選択がされた状態で、 // 範囲選択されている内部がクリックされた SelectionMoveStartX = e.X; SelectionMoveStartY = e.Y; return; } } // それ以外の場合は新しい範囲選択が開始された場合である startX = e.X; startY = e.Y; SelectionX = e.X; SelectionY = e.Y; // 保存されている色に関する情報はクリアする ClearSelectionXYs(); AllClearOldColors(); } void AllClearOldColors() { for(int row = 0; row < 32; row++) { for(int column = 0; column < 32; column++) panels[column, row].oldColor = Color.Empty; } } } |
これは範囲選択された状態でドラッグされているときの処理です。このときに選択されている部分を移動させます。
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 |
public partial class Form1 : Form { private void Box_DragOverPanel(object sender, XY e) { if(GetCheckedRadioButton() == CheckedRadioButton.Free) return; if(SelectionMoveStartX != -1) { int moveX = e.X - SelectionMoveStartX; int moveY = e.Y - SelectionMoveStartY; // 移動させる if(moveX > 0) MoveSelectionRight(); if(moveX < 0) MoveSelectionLeft(); if(moveY > 0) MoveSelectionDown(); if(moveY < 0) MoveSelectionUp(); SelectionMoveStartX = e.X; SelectionMoveStartY = e.Y; return; } // その他の場合は前回と同じなので省略 } } |
ドロップが完了したときが範囲選択された部分を移動させる処理を終了させるときです。SelectionMoveStartXを不適切な値に設定して処理を完了させます。
1 2 3 4 5 6 7 8 |
public partial class Form1 : Form { private void Box_EndSelection(object sender, XY e) { SelectionMoveStartX = -1; AllClearOldColors(); } } |