前回はレイヤーをつかった画像作成をやりました。今回はレイヤーの上下関係を変更します。レイヤーが重なっている場合は手前にあるレイヤーに描画されているものが表示されます。
ではさっそくやってみましょう。
まずデザイナでレイヤーを管理するためのダイアログを作成します。クラス名はLayerOrderFormです。リストボックスにレイヤーの一覧が表示され、選択するととなりのピクチャーボックスに画像が表示されます。
それから順序はドラッグ&ドロップで入れ替えます。
ではコードをみてみましょう。
ドラッグ&ドロップの操作ができるようにするためにはDragOverイベントとDragDropイベントを処理することになります。また両イベントが発生するようにするためにはListBox.AllowDropプロパティをtrueにする必要があります。
フィールド変数のLayersはレイヤーが格納されたリストをうけとるためのものです。
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 LayerOrderForm : Form { public List<Layer> Layers = null; bool isMouseDown = false; public LayerOrderForm() { InitializeComponent(); pictureBox1.SizeMode = PictureBoxSizeMode.Zoom; listBox1.AllowDrop = true; listBox1.MouseDown += ListBox1_MouseDown; listBox1.MouseMove += ListBox1_MouseMove; listBox1.MouseUp += ListBox1_MouseUp; listBox1.DragOver += ListBox1_DragOver; listBox1.DragDrop += ListBox1_DragDrop; buttonOK.DialogResult = DialogResult.OK; buttonCancel.DialogResult = DialogResult.Cancel; } } |
Loadイベントではフィールド変数Layersの情報から現在存在するレイヤーの名前をリストボックスに表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public partial class LayerOrderForm : Form { private void LayerOrderForm_Load(object sender, EventArgs e) { if(Layers != null) { foreach(Layer layer in Layers) { listBox1.Items.Add(layer.Name); } } } } |
リストボックスの項目のうえでクリックされたら、項目の順番を入れ替えるためのドラッグが開始されたかもしれないことを意味してします。そしてそのままマウスボタンがおされたままMouseMoveイベントが発生したらドラッグの開始です。
ドラッグが開始されたらリストボックスの項目が選択されているかどうか調べて項目のうえであればListBox.DoDragDropメソッドをよびます。
DoDragDropメソッドにはクリックされた場所にある項目のインデックスをわたします。
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 LayerOrderForm : Form { private void ListBox1_MouseDown(object sender, MouseEventArgs e) { isMouseDown = true; } private void ListBox1_MouseUp(object sender, MouseEventArgs e) { isMouseDown = false; } private void ListBox1_MouseMove(object sender, MouseEventArgs e) { if(isMouseDown) { isMouseDown = false; //マウス下のListBoxのインデックスを得る Point p = Control.MousePosition; p = listBox1.PointToClient(p); int index = listBox1.IndexFromPoint(p); if(index > -1) { listBox1.SelectedIndex = index; listBox1.DoDragDrop(index, DragDropEffects.Move); } } } } |
ドラッグがおこなわれているときに e.Data.GetDataPresent(typeof(int)) == true;であれば項目がドラッグされていることになります。ドロップ先が適切な場所であればマウスカーソルの形状を「移動」にします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public partial class LayerOrderForm : Form { private void ListBox1_DragOver(object sender, DragEventArgs e) { if(e.Data.GetDataPresent(typeof(int))) { int i = (int)e.Data.GetData(typeof(int)); Point p = Control.MousePosition; p = checkedListBox1.PointToClient(p); int index = checkedListBox1.IndexFromPoint(p); if(index != -1) e.Effect = DragDropEffects.Move; else e.Effect = DragDropEffects.None; } } } |
ドロップされたら項目の順番を並べ替えます。Layersに格納されている要素の順番を変更したあと、いったんリストボックスの項目を全部削除して再挿入しています。
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 |
public partial class LayerOrderForm : Form { private void ListBox1_DragDrop(object sender, DragEventArgs e) { if(e.Data.GetDataPresent(typeof(int))) { int i = (int)e.Data.GetData(typeof(int)); Point p = Control.MousePosition; p = listBox1.PointToClient(p); int index = listBox1.IndexFromPoint(p); if(index == -1) return; if(i == index) return; if(i < index) { Layer layer = Layers[i]; Layers.RemoveAt(i); Layers.Insert(index - 1, layer); } if(i > index) { Layer layer = Layers[i]; Layers.RemoveAt(i); Layers.Insert(index, layer); } listBox1.Items.Clear(); foreach(Layer layer in Layers) { listBox1.Items.Add(layer.Name); } } } } |
つぎにForm1側の処理を考えます。
メニューの[レイヤーの順番を変更する]が選択されたらLayerOrderFormオブジェクトを作成してForm1.Layersのコピーを渡します。あとはShowDialog()メソッドを呼び出せばダイアログが表示されます。
次にダイアログが[OK]をクリックされることで終了した場合の処理です。LayerOrderFormクラスから順番が変更されたLayersをうけとります。そしてPictureBox.Invalidate()メソッドを呼び出してピクチャーボックスを再描画させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public partial class Form1 : Form { private void LayerOrderMenuItem_Click(object sender, EventArgs e) { LayerOrderForm form = new LayerOrderForm(); form.Layers = Layers.ToList(); if(form.ShowDialog() == DialogResult.OK) { Layers = form.Layers; pictureBox1.Invalidate(); } form.Dispose(); } } |
レイヤーの上下関係から画像を描画します。下にあるレイヤーから描画していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public partial class Form1 : Form { private void pictureBox1_Paint(object sender, PaintEventArgs e) { List<Layer> layers = Layers.ToList(); layers.Reverse(); foreach(Layer layer in layers) { if(layer.Bitmap != null) e.Graphics.DrawImage(layer.Bitmap, new Point(layer.X, layer.Y)); } } } |