レイヤーをドラッグすることでサイズ変更できるようにします。まずコンテキストメニューを表示するクラスの追加部分を示します。右クリックされると[レイヤー XXX のサイズを変更する]という項目が表示されます。そしてクリックするとItem_Click4が実行され、フィールド変数 SizeChangingLayerにそのレイヤーが格納され、そのレイヤーがある部分がグリッパー付きの枠で囲われます。
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 |
class ContextMenuEx1 { Form1 _form; public ContextMenuEx1(Form1 form, Layer layer) { _form = form; ContextMenuStrip contextMenuStrip = CreateContextMenuStrip(layer); contextMenuStrip.Show(Control.MousePosition); } ContextMenuStrip CreateContextMenuStrip(Layer layer) { ContextMenuStrip menuStrip = new ContextMenuStrip(); AddMenuEdit(menuStrip, layer); AddMenuBackOne(menuStrip, layer); AddMenuMove(menuStrip, layer); AddMenuSizeChange(menuStrip, layer); return menuStrip; } public Layer SizeChangingLayer = null; public LayerSizeChange LayerSizeChange = null; void AddMenuSizeChange(ContextMenuStrip menuStrip, Layer layer) { ToolStripMenuItem item = new ToolStripMenuItem(); item.Text = String.Format("レイヤー「{0}」のサイズを変更する", layer.Name); item.Tag = layer; item.Click += Item_Click4; menuStrip.Items.Add(item); } void Item_Click4(object sender, EventArgs e) { ToolStripMenuItem mi = (ToolStripMenuItem)sender; Layer layer = (Layer)mi.Tag; SizeChangingLayer = layer; _form.ShowLayers(layer); // サイズ変更の対象になるレイヤーをグリップのついた枠で囲う } } |
これはグリッパ付きの枠を表示するためのクラスです。レイヤーを引数にしてグリッパー付きの枠のBitmapと、グリッパーの位置を取得することができます。
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 |
public class GriperRectangle { int GriperSize = 8; Layer _layer = null; public GriperRectangle(Layer layer) { _layer = layer; Rectangle rect = new Rectangle(layer.X, layer.Y, layer.Width, layer.Height); griperRects.Add(new Rectangle(new Point(rect.X, rect.Y), new Size(GriperSize, GriperSize))); griperRects.Add(new Rectangle(new Point(rect.X + rect.Width / 2 - GriperSize / 2, rect.Y), new Size(GriperSize, GriperSize))); griperRects.Add(new Rectangle(new Point(rect.Right - GriperSize, rect.Y), new Size(GriperSize, GriperSize))); griperRects.Add(new Rectangle(new Point(rect.X, rect.Bottom - GriperSize), new Size(GriperSize, GriperSize))); griperRects.Add(new Rectangle(new Point(rect.X + rect.Width / 2 - GriperSize / 2, rect.Bottom - GriperSize), new Size(GriperSize, GriperSize))); griperRects.Add(new Rectangle(new Point(rect.Right - GriperSize, rect.Bottom - GriperSize), new Size(GriperSize, GriperSize))); griperRects.Add(new Rectangle(new Point(rect.X, rect.Y + rect.Height / 2 - GriperSize / 2), new Size(GriperSize, GriperSize))); griperRects.Add(new Rectangle(new Point(rect.Right - GriperSize, rect.Y + rect.Height / 2 - GriperSize / 2), new Size(GriperSize, GriperSize))); } List<Rectangle> griperRects = new List<Rectangle>(); public Bitmap GetBitmapGriperRectangle() { Bitmap bitmap = new Bitmap(_layer.X + _layer.Width + 1, _layer.Y + _layer.Height + 1); Graphics g = Graphics.FromImage(bitmap); g.DrawRectangle(new Pen(Color.Black), _layer.X, _layer.Y, _layer.Width, _layer.Height); g.FillRectangles(new SolidBrush(Color.Black), griperRects.ToArray()); g.Dispose(); return bitmap; } public Rectangle GetGriperNW() { Rectangle rect = new Rectangle(_layer.X, _layer.Y, _layer.Width, _layer.Height); return new Rectangle(new Point(rect.X, rect.Y), new Size(GriperSize, GriperSize)); } public Rectangle GetGriperN() { Rectangle rect = new Rectangle(_layer.X, _layer.Y, _layer.Width, _layer.Height); return new Rectangle(new Point(rect.X + rect.Width / 2 - GriperSize / 2, rect.Y), new Size(GriperSize, GriperSize)); } public Rectangle GetGriperNE() { Rectangle rect = new Rectangle(_layer.X, _layer.Y, _layer.Width, _layer.Height); return new Rectangle(new Point(rect.Right - GriperSize, rect.Y), new Size(GriperSize, GriperSize)); } public Rectangle GetGriperSW() { Rectangle rect = new Rectangle(_layer.X, _layer.Y, _layer.Width, _layer.Height); return new Rectangle(new Point(rect.X, rect.Bottom - GriperSize), new Size(GriperSize, GriperSize)); } public Rectangle GetGriperSE() { Rectangle rect = new Rectangle(_layer.X, _layer.Y, _layer.Width, _layer.Height); return new Rectangle(new Point(rect.Right - GriperSize, rect.Bottom - GriperSize), new Size(GriperSize, GriperSize)); } public Rectangle GetGriperS() { Rectangle rect = new Rectangle(_layer.X, _layer.Y, _layer.Width, _layer.Height); return new Rectangle(new Point(rect.X + rect.Width / 2 - GriperSize / 2, rect.Bottom - GriperSize), new Size(GriperSize, GriperSize)); } public Rectangle GetGriperW() { Rectangle rect = new Rectangle(_layer.X, _layer.Y, _layer.Width, _layer.Height); return new Rectangle(new Point(rect.X, rect.Y + rect.Height / 2 - GriperSize / 2), new Size(GriperSize, GriperSize)); } public Rectangle GetGriperE() { Rectangle rect = new Rectangle(_layer.X, _layer.Y, _layer.Width, _layer.Height); return new Rectangle(new Point(rect.Right - GriperSize, rect.Y + rect.Height / 2 - GriperSize / 2), new Size(GriperSize, GriperSize)); } } |
1 2 3 4 5 6 7 8 9 10 11 12 |
public enum Griper { North, South, East, West, NorthEast, NorthWest, SouthEast, SouthWest, None, } |
Form1クラス内でサイズ変更が可能なときにクリックすると、レイヤーのどの部分でクリックされたかを調べます。レイヤーの外ならサイズ変更の処理は終わりです。グリッパーの上であればサイズ変更の準備をします。グリッパーによってどのほうこうに拡大縮小するのかが違ってきます。そのような情報をLayerSizeChangeオブジェクト内に格納して、これをcontextMenuEx1のフィールド変数LayerSizeChangeにセットします。
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 |
public partial class Form1 : Form { private void ScroolPictureBox1_PictureBoxMouseDown(object sender, MouseEventArgs e) { ShowLayers(); if (e.Button == MouseButtons.Right) { // コンテキストメニューを表示させる Layer layer = GetLayerFromPoint(new Point(e.X, e.Y)); if (layer != null) contextMenuEx1 = new ContextMenuEx1(this, layer); else contextMenuEx1 = null; } if (e.Button == MouseButtons.Left) { if (contextMenuEx1 == null) return; if (contextMenuEx1.MovingLayer != null) LayerMoveStart(contextMenuEx1.MovingLayer, new Point(e.X, e.Y)); else if (contextMenuEx1.SizeChangingLayer != null) LayerSizeChangeStart(contextMenuEx1.SizeChangingLayer, new Point(e.X, e.Y)); } } void LayerSizeChangeStart(Layer layer, Point clickPoint) { // レイヤーの外でクリックされたらサイズ変更の処理は中止、または完了したと見なす if (clickPoint.X < layer.Left || layer.Right < clickPoint.X || clickPoint.Y < layer.Top || layer.Bottom < clickPoint.Y) { contextMenuEx1 = null; Text = "レーヤー拡大縮小は中止"; ShowLayers(); return; } Text = "レーヤーのサイズ変更"; Capture = true; if (contextMenuEx1.SizeChangingLayer == null) return; GriperRectangle griper = new GriperRectangle(contextMenuEx1.SizeChangingLayer); if (IsPointInRectangle(clickPoint, griper.GetGriperSE())) contextMenuEx1.LayerSizeChange = new LayerSizeChange(this, layer, Control.MousePosition, Griper.SouthEast); else if (IsPointInRectangle(clickPoint, griper.GetGriperS())) contextMenuEx1.LayerSizeChange = new LayerSizeChange(this, layer, Control.MousePosition, Griper.South); else if (IsPointInRectangle(clickPoint, griper.GetGriperE())) contextMenuEx1.LayerSizeChange = new LayerSizeChange(this, layer, Control.MousePosition, Griper.East); else if (IsPointInRectangle(clickPoint, griper.GetGriperN())) contextMenuEx1.LayerSizeChange = new LayerSizeChange(this, layer, Control.MousePosition, Griper.North); else if (IsPointInRectangle(clickPoint, griper.GetGriperW())) contextMenuEx1.LayerSizeChange = new LayerSizeChange(this, layer, Control.MousePosition, Griper.West); else if (IsPointInRectangle(clickPoint, griper.GetGriperNE())) contextMenuEx1.LayerSizeChange = new LayerSizeChange(this, layer, Control.MousePosition, Griper.NorthEast); else if (IsPointInRectangle(clickPoint, griper.GetGriperNW())) contextMenuEx1.LayerSizeChange = new LayerSizeChange(this, layer, Control.MousePosition, Griper.NorthWest); else if (IsPointInRectangle(clickPoint, griper.GetGriperSW())) contextMenuEx1.LayerSizeChange = new LayerSizeChange(this, layer, Control.MousePosition, Griper.SouthWest); else contextMenuEx1.LayerSizeChange = new LayerSizeChange(this, layer, Control.MousePosition, Griper.None); } bool IsPointInRectangle(Point pt, Rectangle rect) { if (pt.X < rect.Left) return false; if (pt.X > rect.Right) return false; if (pt.Y < rect.Top) return false; if (pt.Y > rect.Bottom) return false; return true; } } |
LayerSizeChangeクラスはこのようになっています。コンストラクタでレイヤーやクリックされたグリッパー、ドラッグが開始された座標などをフィールド変数に格納することで拡大縮小ができるようにしています。またグリッパーがクリックされずにドラッグされた場合は通常の移動になります。では昨日の作業はなんだのか?
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 |
public class LayerSizeChange { public Point MoveStartScreenPos = new Point(); public Layer Layer = null; public int LayerOldPosX = 0; public int LayerOldPosY = 0; public int LayerOldWidth = 0; public int LayerOldHeight = 0; public Griper Griper = Griper.None; public Form1 _form1 = null; public LayerSizeChange(Form1 form1, Layer layer, Point moveStartScreenPos, Griper griper) { _form1 = form1; Layer = layer; MoveStartScreenPos = moveStartScreenPos; LayerOldPosX = Layer.X; LayerOldPosY = Layer.Y; LayerOldWidth = Layer.Width; LayerOldHeight = Layer.Height; Griper = griper; } public void SizeChangeLayer() { // クリックされた座標との差を利用して、元の座標から移動させる int dx = Control.MousePosition.X - MoveStartScreenPos.X; int dy = Control.MousePosition.Y - MoveStartScreenPos.Y; if(Griper == Griper.South) { Layer.Height = LayerOldHeight + dy; } if (Griper == Griper.East) { Layer.Width = LayerOldWidth + dx; } if (Griper == Griper.SouthEast) { Layer.Width = LayerOldWidth + dx; Layer.Height = LayerOldHeight + dy; } if (Griper == Griper.North) { Layer.Y = LayerOldPosY + dy; Layer.Height = LayerOldHeight - dy; } if (Griper == Griper.West) { Layer.X = LayerOldPosX + dx; Layer.Width = LayerOldWidth - dx; } if (Griper == Griper.NorthWest) { Layer.X = LayerOldPosX + dx; Layer.Width = LayerOldWidth - dx; Layer.Y = LayerOldPosY + dy; Layer.Height = LayerOldHeight - dy; } if (Griper == Griper.NorthEast) { Layer.Width = LayerOldWidth + dx; Layer.Height = LayerOldHeight + dy; Layer.Y = LayerOldPosY + dy; Layer.Height = LayerOldHeight - dy; } if (Griper == Griper.SouthWest) { Layer.X = LayerOldPosX + dx; Layer.Width = LayerOldWidth - dx; Layer.Height = LayerOldHeight + dy; } // グリッパーがクリックされていない場合は通常の移動 if (Griper == Griper.None) { Layer.X = LayerOldPosX + dx; Layer.Y = LayerOldPosY + dy; } if (Layer.Height <= 0) Layer.Height = 1; if (Layer.Width <= 0) Layer.Width = 1; _form1.ShowLayers(Layer); } } |
contextMenuEx1のフィールド変数にLayerSizeChangeオブジェクトが格納されている状態でマウスをドラッグするとサイズ変更が行なわれます。マウスボタンを離したあとであっても、レイヤーのない部分をクリックしたり、右クリックしない限り、同じであればレイヤーのサイズ変更ができます。
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 { private void Form1_MouseMove(object sender, MouseEventArgs e) { if (contextMenuEx1 != null && contextMenuEx1.LayerMove != null) contextMenuEx1.LayerMove.MoveLayer(); if (contextMenuEx1 != null && contextMenuEx1.LayerSizeChange != null) contextMenuEx1.LayerSizeChange.SizeChangeLayer(); } private void Form1_MouseUp(object sender, MouseEventArgs e) { if (contextMenuEx1 != null && contextMenuEx1.LayerMove != null) contextMenuEx1.LayerMove.MoveLayer(); if (contextMenuEx1 != null && contextMenuEx1.LayerSizeChange != null) contextMenuEx1.LayerSizeChange.SizeChangeLayer(); } } |
サイズ変更がおこなわれるとLayerSizeChange.SizeChangeLayer()メソッドによってScroolPictureBoxの再描画が行なわれます。
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 |
public partial class Form1 : Form { private void scroolPictureBox1_PicturePaint(object sender, PaintEventArgs e) { if (contextMenuEx1 != null && contextMenuEx1.MovingLayer != null) { ShowLayersOnMoving(e.Graphics); } else if (contextMenuEx1 != null && contextMenuEx1.SizeChangingLayer != null) { ShowLayersOnSizeChanging(e.Graphics); } } void ShowLayersOnSizeChanging(Graphics g) { int newWidth = 0; int newHeight = 0; if (Layers.Count > 0) { newWidth = Layers.Max(x => x.Right); newHeight = Layers.Max(x => x.Bottom); } // なにもないBitmapをつくる Bitmap bitmap = new Bitmap(newWidth, newHeight); scroolPictureBox1.Bitmap = bitmap; foreach (Layer layer in Layers) { g.DrawImage(layer.Bitmap, new Rectangle(layer.X, layer.Y, layer.Width, layer.Height)); } if (contextMenuEx1.SizeChangingLayer == null) return; Layer layer1 = contextMenuEx1.SizeChangingLayer; GriperRectangle griper = new GriperRectangle(layer1); g.DrawImage(griper.GetBitmapGriperRectangle(), new Rectangle(0, 0, layer1.X + layer1.Width, layer1.Y + layer1.Height)); } } |