using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.Windows.Forms; namespace HotelPms.Share.Windows.Component.Design { /// /// 設計Frame:2015/05/13 /// public class DesignPanel : Panel { #region ★★★★★ Declartions ★★★★★ public enum ItemType : int { Normal = 0, Line, } public enum HitDownSquare : int { None = 0, TopLeft, TopCenter, TopRight, MiddleLeft, MiddleRight, BottomLeft, BottomCenter, BottomRight, Body, } public sealed class HitTestInfo { public static readonly HitTestInfo Nowhere; internal int y; internal int x; internal HitDownSquare type; internal int index; internal int itemY; internal int itemX; static HitTestInfo() { HitTestInfo.Nowhere = new HitTestInfo(); } internal HitTestInfo() { this.type = HitDownSquare.None; this.x = -1; this.y = -1; this.index = -1; } public int X { get { return this.x; } } public int Y { get { return this.y; } } public int ItemY { get { return this.itemY; } } public int ItemX { get { return this.itemX; } } public int Index { get { return this.index; } } public HitDownSquare Type { get { return this.type; } } public override int GetHashCode() { return this.x << 16 | this.y << 8 | (int)this.type; } public override bool Equals(object obj) { HitTestInfo hi = obj as HitTestInfo; return (this.type == hi.type && this.x == hi.x && this.x == hi.x); } public override string ToString() { return string.Concat(new string[7] { "{ ", this.type.ToString(), ",", this.x.ToString(), ",", this.y.ToString(), "}" }); } } private bool isMouseDown = false; private HitTestInfo curHitTestInfo = null; //public bool isSelected = false; private int m_SelectIndex = -1; public bool m_MouseFocused = false; public event EventHandler StyleChange; private float m_Zoom = 1; #endregion #region ★★★★★ Property ★★★★★ private DesignItemCollection m_Items = null; [Category("Item Setting")] [DefaultValue(null)] [Description("Item")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public DesignItemCollection Items { get { return m_Items; } set { m_Items = value; } } [Category("Item Setting")] [DefaultValue(1F)] [Description("Zoom")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public float Zoom { get { return m_Zoom; } set { m_Zoom = value <= 0 ? 1 : value; Invalidate(); } } [Category("Item Setting")] [DefaultValue(-1)] [Description("SelectIndex")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public int SelectIndex { get { return m_SelectIndex; } set { m_SelectIndex = value; Invalidate(); } } public DesignItem CurrentItem { get { if(m_SelectIndex == -1) { return null; } return Items[m_SelectIndex]; } } #endregion #region ★★★★★ Class Event ★★★★★ public DesignPanel() { //SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.DoubleBuffer, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.ResizeRedraw, true); this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); //SetStyle(ControlStyles.SupportsTransparentBackColor, true); //SetStyle(ControlStyles.Opaque, true); //透明 //this.BackColor = Color.Transparent; m_Items = new DesignItemCollection(this); } #endregion #region ★★★★★ Control Event ★★★★★ protected override void OnEnter(EventArgs e) { base.OnEnter(e); //isSelected = true; Invalidate(); } protected override void OnLeave(EventArgs e) { base.OnLeave(e); //isSelected = false; Invalidate(); } protected override void OnMouseEnter(EventArgs e) { base.OnMouseEnter(e); m_MouseFocused = true; Invalidate(); } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); m_MouseFocused = false; Invalidate(); } protected override void OnMouseDown(MouseEventArgs e) { this.Focus(); //e.X, e.Yとは実際画面の位置ではなく、ヒットされる該当コントロールに対する相対位置 isMouseDown = true; curHitTestInfo = HitTest(e.X, e.Y); SetCursor(curHitTestInfo); m_SelectIndex = curHitTestInfo.index; Invalidate(); System.Diagnostics.Debug.WriteLine(string.Format("OnMouseDown X:{0} Y:{1}", e.X, e.Y)); base.OnMouseDown(e); } protected override void OnMouseUp(MouseEventArgs e) { this.Cursor = Cursors.Default; isMouseDown = false; System.Diagnostics.Debug.WriteLine(string.Format("OnMouseUp X:{0} Y:{1}", e.X, e.Y)); base.OnMouseUp(e); } protected override void OnMouseMove(MouseEventArgs e) { if (!isMouseDown) { System.Diagnostics.Debug.WriteLine(string.Format("OnMouseMove X:{0} Y:{1}", e.X, e.Y)); HitTestInfo hit = HitTest(e.X, e.Y); SetCursor(hit); } else { int offsetX = 0; int offsetY = 0; System.Diagnostics.Debug.WriteLine(string.Format("X:{0} Y:{1}", e.X, e.Y)); if (m_SelectIndex >= 0) { int x = (int)(e.X / m_Zoom); int y = (int)(e.Y / m_Zoom); DesignItem item = Items[m_SelectIndex]; switch (curHitTestInfo.Type) { case HitDownSquare.TopCenter: offsetY = item.ClientRectangle.Y + item.ClientRectangle.Height - DesignItem.Square.Height * 3; if (y < offsetY) { item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.Location.X, y), new Size(item.ClientRectangle.Width, item.ClientRectangle.Y + item.ClientRectangle.Height - y)); } break; case HitDownSquare.TopRight: offsetX = item.ClientRectangle.X + DesignItem.Square.Width * 3; offsetY = item.ClientRectangle.Y + item.ClientRectangle.Height - DesignItem.Square.Height * 3; if (x > offsetX) { item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.X, item.ClientRectangle.Location.Y), new Size(x - item.ClientRectangle.X, item.ClientRectangle.Height)); } if (y < offsetY) { item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.Location.X, y), new Size(item.ClientRectangle.Width, item.ClientRectangle.Y + item.ClientRectangle.Height - y)); } break; case HitDownSquare.TopLeft: offsetX = item.ClientRectangle.X + item.ClientRectangle.Width - DesignItem.Square.Width * 3; offsetY = item.ClientRectangle.Y + item.ClientRectangle.Height - DesignItem.Square.Height * 3; if (x < offsetX) { item.ClientRectangle = new Rectangle(new Point(x, item.ClientRectangle.Y), new Size(item.ClientRectangle.X + item.ClientRectangle.Width - x, item.ClientRectangle.Height)); } if (y < offsetY) { item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.X, y), new Size(item.ClientRectangle.Width, item.ClientRectangle.Y + item.ClientRectangle.Height - y)); } break; case HitDownSquare.MiddleLeft: offsetX = item.ClientRectangle.X + item.ClientRectangle.Width - DesignItem.Square.Width * 3; if (x < offsetX) { item.ClientRectangle = new Rectangle(new Point(x, item.ClientRectangle.Y), new Size(item.ClientRectangle.X + item.ClientRectangle.Width - x, item.ClientRectangle.Height)); } break; case HitDownSquare.BottomCenter: offsetY = item.ClientRectangle.Y + DesignItem.Square.Height * 3; if (y > offsetY) { item.ClientRectangle = new Rectangle(item.ClientRectangle.Location, new Size(item.ClientRectangle.Width, y - item.ClientRectangle.Y)); } break; case HitDownSquare.BottomLeft: offsetX = item.ClientRectangle.X + item.ClientRectangle.Width - DesignItem.Square.Width * 3; offsetY = item.ClientRectangle.Y + DesignItem.Square.Height * 3; if (x < offsetX) { item.ClientRectangle = new Rectangle(new Point(x, item.ClientRectangle.Y), new Size(item.ClientRectangle.X + item.ClientRectangle.Width - x, item.ClientRectangle.Height)); } if (y > offsetY) { item.ClientRectangle = new Rectangle(item.ClientRectangle.Location, new Size(item.ClientRectangle.Width, y - item.ClientRectangle.Y)); } break; case HitDownSquare.BottomRight: offsetX = item.ClientRectangle.X + DesignItem.Square.Width * 3; offsetY = item.ClientRectangle.Y + DesignItem.Square.Height * 3; if (x > offsetX) { item.ClientRectangle = new Rectangle(item.ClientRectangle.Location, new Size(x - item.ClientRectangle.X, item.ClientRectangle.Height)); } if (y > offsetY) { item.ClientRectangle = new Rectangle(item.ClientRectangle.Location, new Size(item.ClientRectangle.Width, y - item.ClientRectangle.Y)); } break; case HitDownSquare.MiddleRight: offsetX = item.ClientRectangle.X + DesignItem.Square.Width * 3; if (x > offsetX) { item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.X, item.ClientRectangle.Location.Y), new Size(x - item.ClientRectangle.X, item.ClientRectangle.Height)); } break; case HitDownSquare.Body: offsetX = x - (int)(curHitTestInfo.X / m_Zoom); offsetY = y - (int)(curHitTestInfo.Y / m_Zoom); item.ClientRectangle = new Rectangle(new Point(curHitTestInfo.ItemX + offsetX, curHitTestInfo.ItemY + offsetY), item.ClientRectangle.Size); break; } } //RefreshBackground(); Invalidate(); if (StyleChange != null) { StyleChange(this, new EventArgs()); } } base.OnMouseMove(e); } protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e) { DesignItem item = null; switch (e.KeyCode) { case Keys.Up: if (m_SelectIndex >= 0) { item = Items[m_SelectIndex]; if (e.Shift) { if (item.ClientRectangle.Size.Height > DesignItem.Square.Height * 3) { item.ClientRectangle = new Rectangle(item.ClientRectangle.Location, new Size(item.ClientRectangle.Size.Width, item.ClientRectangle.Size.Height - 1)); } } else { item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.X, item.ClientRectangle.Y - 1), item.ClientRectangle.Size); } if (StyleChange != null) { StyleChange(this, new EventArgs()); } } break; case Keys.Down: if (m_SelectIndex >= 0) { item = Items[m_SelectIndex]; if (e.Shift) { item.ClientRectangle = new Rectangle(item.ClientRectangle.Location, new Size(item.ClientRectangle.Size.Width, item.ClientRectangle.Size.Height + 1)); } else { item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.X, item.ClientRectangle.Y + 1), item.ClientRectangle.Size); } if (StyleChange != null) { StyleChange(this, new EventArgs()); } } break; case Keys.Left: if (m_SelectIndex >= 0) { item = Items[m_SelectIndex]; if (e.Shift) { if (item.ClientRectangle.Size.Width > DesignItem.Square.Width * 3) { item.ClientRectangle = new Rectangle(item.ClientRectangle.Location, new Size(item.ClientRectangle.Size.Width - 1, item.ClientRectangle.Size.Height)); } } else { item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.X - 1, item.ClientRectangle.Y), item.ClientRectangle.Size); } if (StyleChange != null) { StyleChange(this, new EventArgs()); } } break; case Keys.Right: if (m_SelectIndex >= 0) { item = Items[m_SelectIndex]; if (e.Shift) { item.ClientRectangle = new Rectangle(item.ClientRectangle.Location, new Size(item.ClientRectangle.Size.Width + 1, item.ClientRectangle.Size.Height)); } else { item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.X + 1, item.ClientRectangle.Y), item.ClientRectangle.Size); } if (StyleChange != null) { StyleChange(this, new EventArgs()); } } break; default: base.OnPreviewKeyDown(e); return; } e.IsInputKey = true; //RefreshBackground(); Invalidate(); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e);//コントロールのプロパティで設定した部分の描画 GraphicsState state = e.Graphics.Save(); e.Graphics.ScaleTransform((float)m_Zoom, (float)m_Zoom); //選択枠 int i = 0; foreach (DesignItem item in m_Items) { System.Diagnostics.Debug.WriteLine(m_SelectIndex.ToString()); item.DesignMode = (i == m_SelectIndex); item.Draw(e.Graphics); i++; } e.Graphics.Restore(state); } #endregion #region ★★★★★ Private Function ★★★★★ private void SetCursor(HitTestInfo hit) { switch (hit.type) { case HitDownSquare.BottomRight: case HitDownSquare.TopLeft: this.Cursor = Cursors.SizeNWSE; break; case HitDownSquare.BottomCenter: case HitDownSquare.TopCenter: this.Cursor = Cursors.SizeNS; break; case HitDownSquare.BottomLeft: case HitDownSquare.TopRight: this.Cursor = Cursors.SizeNESW; break; case HitDownSquare.MiddleLeft: case HitDownSquare.MiddleRight: this.Cursor = Cursors.SizeWE; break; case HitDownSquare.Body: this.Cursor = Cursors.SizeAll; break; default: this.Cursor = Cursors.Default; break; } } #endregion #region ★★★★★ Public Function ★★★★★ private bool InRectangle(Rectangle r, int x, int y) { return (r.X * m_Zoom <= x && x <= (r.X + r.Width) * m_Zoom) && (r.Y * m_Zoom <= y && y <= (r.Y + r.Height) * m_Zoom); } public HitTestInfo HitTest(int x, int y) { HitTestInfo hit = new HitTestInfo(); hit.x = x; hit.y = y; for (int idx = Items.Count - 1; idx >= 0; idx--) { DesignItem item = Items[idx]; for (int i = 0; i < item.SmallRect.Length; i++) { //if (item.SmallRect[i].Contains(x, y)) if (InRectangle(item.SmallRect[i], x, y)) { hit.type = (HitDownSquare)(i + 1); hit.index = idx; return hit; } } for (int i = 0; i < item.BoundRect.Length; i++) { //if (item.BoundRect[i].Contains(x, y)) if (InRectangle(item.BoundRect[i], x, y)) { switch (i) { case 0: hit.type = HitDownSquare.TopCenter; break; case 1: hit.type = HitDownSquare.MiddleLeft; break; case 2: hit.type = HitDownSquare.BottomCenter; break; case 3: hit.type = HitDownSquare.MiddleRight; break; } if (item.Appearance == ItemType.Line) { hit.type = HitDownSquare.Body; hit.itemX = item.ClientRectangle.X; hit.itemY = item.ClientRectangle.Y; } hit.index = idx; return hit; } } Rectangle bodyR = item.ClientRectangle; if (item.Appearance == ItemType.Line) { if (item.X1 == item.X2) { bodyR = new Rectangle(bodyR.Location, new Size((int)item.LineWidth < DesignItem.Square.Width ? DesignItem.Square.Width : (int)item.LineWidth, item.ClientRectangle.Height)); } else if (item.Y1 == item.Y2) { bodyR = new Rectangle(bodyR.Location, new Size(item.ClientRectangle.Width, (int)item.LineWidth < DesignItem.Square.Height ? DesignItem.Square.Height : (int)item.LineWidth)); } } //if (bodyR.Contains(x, y)) if (InRectangle(bodyR, x, y)) { hit.type = HitDownSquare.Body; hit.index = idx; hit.itemX = item.ClientRectangle.X; hit.itemY = item.ClientRectangle.Y; return hit; } } return HitTestInfo.Nowhere; } public void RemoveItem() { if (m_SelectIndex == -1) { return; } this.Items.RemoveAt(m_SelectIndex); if (this.Items.Count == 0) { m_SelectIndex = -1; } else if (m_SelectIndex >= this.Items.Count) { m_SelectIndex = this.Items.Count - 1; } Invalidate(); } public DesignItem SelectItem(string name) { for (int i = 0; i < Items.Count; i++) { if(Items[i].Name == name) { m_SelectIndex = i; Invalidate(); return CurrentItem; } } return null; } public void BringItemToFront() { if (m_SelectIndex == -1 || Items.Count == 1) { return; } DesignItem item = CurrentItem; Items.Remove(item); Items.Add(item); m_SelectIndex = Items.Count - 1; Invalidate(); } public void SendItemToBack() { if (m_SelectIndex == -1 || Items.Count == 1) { return; } DesignItem item = CurrentItem; Items.Remove(item); Items.Insert(item, 0); m_SelectIndex = 0; Invalidate(); } #endregion } }