複数のレイヤーをグループ化する方法を考えます。グループ化することでまとめて移動させたりサイズ変更をすることができます。
新しいクラスをつくります。ひとつにまとめたいレイヤーをここに格納します。LayerGroupもLayerと同じように扱いたいのでLayerクラスを継承します。
1 2 3 4 |
public class LayerGroup : Layer { public List<Layer> Layers = new List<Layer>(); } |
またLayerクラスを扱いやすくするために新しいプロパティを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public class Layer { public int Top { get { return Y; } } public int Left { get { return X; } } public int Right { get { return X + Width; } } public int Bottom { get { return Y + Height; } } } |
FormManagementGroupクラスを作成します。
最初にダイアログが表示されたときに存在するLayerのリストを表示します。
FormManagementGroup_LoadのなかでツリービューにLayerGroupとLayerを表示させます。
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 FormManagementGroup : Form { public FormManagementGroup() { InitializeComponent(); treeView1.AfterSelect += TreeView1_AfterSelect; treeView1.BeforeCheck += TreeView1_BeforeCheck; buttonOK.DialogResult = DialogResult.OK; buttonCancel.DialogResult = DialogResult.Cancel; } public List<Layer> Layers { get; set; } = null; private void FormManagementGroup_Load(object sender, EventArgs e) { if(Layers == null) return; foreach(Layer layer in Layers) { if(layer.GetType() == typeof(Layer)) { TreeNode node = new TreeNode(layer.Name); node.Tag = layer; treeView1.Nodes.Add(node); } if(layer.GetType() == typeof(LayerGroup)) { LayerGroup group = (LayerGroup)layer; TreeNode node = new TreeNode(group.Name); node.Tag = group; treeView1.Nodes.Add(node); SetLayers(node, group); } } } int groupCount = 0; void SetLayers(TreeNode node, LayerGroup group) { groupCount++; foreach(Layer layer in group.Layers) { TreeNode node1 = new TreeNode(layer.Name); node1.Tag = layer; node.Nodes.Add(node1); if(layer.GetType() == typeof(LayerGroup)) { SetLayers(node1, (LayerGroup)layer); } } } } |
そして複数のチェックボックスにチェックがはいっている状態で[グループ化]を選択するとチェックされているレイヤーをひとつのグループにまとめます。またチェックをいれることができるのは最上位の階層のものだけです。
[グループ化]が選択されたときはチェックされているアイテムをあつめます。そして2つ以上チェックされている場合はレイヤーのビットマップを合成して新しいビットマップを生成します。そしてツリービューにも新しく生成されたグループを表示させます。
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 |
public partial class FormManagementGroup : Form { // 最上位のアイテムでなければチェックできない private void TreeView1_BeforeCheck(object sender, TreeViewCancelEventArgs e) { if(e.Node.Level != 0) e.Cancel = true; } private void buttonGroup_Click(object sender, EventArgs e) { List<TreeNode> treeNodes = new List<TreeNode>(); foreach(TreeNode node in treeView1.Nodes) { if(node.Checked && node.Level == 0) { treeNodes.Add(node); } } if(treeNodes.Count > 1) { int pos = treeView1.Nodes.IndexOf(treeNodes[0]); LayerGroup group = new LayerGroup(); foreach(TreeNode node in treeNodes) { Layer layer = (Layer)node.Tag; group.Layers.Add(layer); Layers.Remove(layer); } groupCount++; group.Name = "グループ " + groupCount.ToString(); Layers.Insert(pos, group); group.Bitmap = CreateBitmap(group); int minX = group.Layers.Min(x => x.X); int minY = group.Layers.Min(x => x.Y); group.X = minX; group.Y = minY; if(group.Bitmap != null) { group.Width = group.Bitmap.Width; group.Height = group.Bitmap.Height; } else { group.Width = 0; group.Height = 0; } TreeNode newNode = new TreeNode(group.Name); treeView1.Nodes.Insert(pos, newNode); newNode.Tag = group; foreach(TreeNode node in treeNodes) { node.Checked = false; node.Remove(); newNode.Nodes.Add(node); } } } } |
CreateBitmap(LayerGroup group)メソッドは新しく生成されたレイヤーのグループからビットマップを生成するためのものです。各レイヤーのX,Y座標、Rightプロパティ、Bottomプロパティから新しいビットマップの大きさを求め、そこに合成されたビットマップを生成します。
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 |
public partial class FormManagementGroup : Form { Bitmap CreateBitmap(LayerGroup group) { int minX = group.Layers.Min(x => x.X); int minY = group.Layers.Min(x => x.Y); int maxRight = group.Layers.Max(x => x.Right); int maxBottom = group.Layers.Max(x => x.Bottom); if(maxRight - minX == 0 || maxBottom - minY == 0) return null; Bitmap bmp = new Bitmap(maxRight - minX, maxBottom - minY); Graphics g = Graphics.FromImage(bmp); List<Layer> layers = group.Layers.ToList(); layers.Reverse(); foreach(Layer layer in layers) { Bitmap bitmap = new Bitmap(layer.Width, layer.Height); { Graphics g1 = Graphics.FromImage(bitmap); if(layer.Bitmap != null) g1.DrawImage(layer.Bitmap, new Rectangle(0, 0, layer.Width, layer.Height)); g1.Dispose(); } g.DrawImage(bitmap, layer.X- minX, layer.Y- minY); } return bmp; } } |
グループ化ができるならグループ化の解除もできるようにしたいものです。buttonUnGroup_Clickメソッドはグループ化されたレイヤーを分解するとともにツリービューに表示されているアイテムもこれにあわせて変化させます。
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 FormManagementGroup : Form { private void buttonUnGroup_Click(object sender, EventArgs e) { List<TreeNode> treeNodes = new List<TreeNode>(); foreach(TreeNode node in treeView1.Nodes) { if(node.Checked && node.Level == 0) { treeNodes.Add(node); } } if(treeNodes.Count == 1) { if(treeNodes[0].Tag.GetType() != typeof(LayerGroup)) return; LayerGroup group1 = (LayerGroup)treeNodes[0].Tag; int pos = Layers.IndexOf(group1); Layers.RemoveAt(pos); List<Layer> layers = group1.Layers; layers.Reverse(); foreach(Layer layer in layers) { Layers.Insert(pos, layer); } List<TreeNode> treeNodes1 = new List<TreeNode>(); int index = treeView1.Nodes.IndexOf(treeNodes[0]); foreach(TreeNode node in treeNodes[0].Nodes) { treeNodes1.Add(node); } treeNodes1.Reverse(); foreach(TreeNode node in treeNodes1) { node.Remove(); treeView1.Nodes.Insert(index, node); } treeNodes[0].Remove(); } } } |