using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Xml; namespace arFrame.Control { public partial class MenuControl : System.Windows.Forms.Control { private int bordersize = 0; private int menubordersize = 1; private int menuwidth = 100; private int menugap = 5; private System.Windows.Forms.Padding padding = new Padding(3, 3, 3, 3); private System.Drawing.Color backcolor = System.Drawing.Color.White; private System.Drawing.Color backcolor2 = System.Drawing.Color.Gainsboro; private System.Drawing.Color bordercolor = System.Drawing.Color.Black; private Boolean enablemenubakcolor = false; private Boolean enablemenuborder = false; private Boolean textattachtoimage = true; [Category("arFrame"), DisplayName("메뉴")] public MenuItem[] menus { get; set; } private Rectangle[] rects = null; [Category("arFrame"), DisplayName("테두리 굵기")] public int BorderSize { get { return bordersize; } set { this.bordersize = value; Invalidate(); } } [Category("arFrame"), DisplayName("메뉴 테두리 굵기")] public int MenuBorderSize { get { return menubordersize; } set { this.menubordersize = value; Invalidate(); } } [Category("arFrame"), DisplayName("메뉴 너비")] public int MenuWidth { get { return menuwidth; } set { this.menuwidth = value; RemakeChartRect(); Invalidate(); } } [Category("arFrame"), DisplayName("메뉴 간격")] public int MenuGap { get { return menugap; } set { this.menugap = value; RemakeChartRect(); Invalidate(); } } [Category("arFrame"), DisplayName("기능-메뉴별 배경색")] public Boolean EnableMenuBackColor { get { return enablemenubakcolor; } set { this.enablemenubakcolor = value; Invalidate(); } } [Category("arFrame"), DisplayName("기능-메뉴별 테두리")] public Boolean EnableMenuBorder { get { return enablemenuborder; } set { this.enablemenuborder = value; Invalidate(); } } [Category("arFrame"), DisplayName("글자를 이미지 다음에 표시"), Description("이미지가 있는 경우 해당 이미지 옆에 글자를 붙입니다")] public Boolean TextAttachToImage { get { return textattachtoimage; } set { this.textattachtoimage = value; Invalidate(); } } [Category("arFrame"), DisplayName("이미지 표시 여백(좌,상)")] public System.Drawing.Point ImagePadding { get; set; } [Category("arFrame"), DisplayName("이미지 표시 크기(너비,높이)")] public System.Drawing.Size ImageSize { get; set; } [Category("arFrame"), DisplayName("색상-테두리")] public System.Drawing.Color BorderColor { get { return bordercolor; } set { this.bordercolor = value; Invalidate(); } } [Category("arFrame"), DisplayName("내부 여백")] public new System.Windows.Forms.Padding Padding { get { return padding; } set { this.padding = value; RemakeChartRect(); Invalidate(); } } [Category("arFrame"), DisplayName("색상-배경1")] public override System.Drawing.Color BackColor { get { return backcolor; } set { this.backcolor = value; Invalidate(); } } [Category("arFrame"), DisplayName("색상-배경2")] public System.Drawing.Color BackColor2 { get { return backcolor2; } set { this.backcolor2 = value; Invalidate(); } } [Category("arFrame"), DisplayName("색상-글자")] public override Color ForeColor { get { return base.ForeColor; } set { base.ForeColor = value; } } private int mouseOverItemIndex = -1; public MenuControl() { InitializeComponent(); // Set Optimized Double Buffer to reduce flickering this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); // Redraw when resized this.SetStyle(ControlStyles.ResizeRedraw, true); ImagePadding = new System.Drawing.Point(0, 0); ImageSize = new System.Drawing.Size(24, 24); if (MinimumSize.Width == 0 || MinimumSize.Height == 0) MinimumSize = new Size(100, 50); } protected override void OnSizeChanged(EventArgs e) { base.OnSizeChanged(e); RemakeChartRect(); } public event EventHandler ItemClick; public class MenuEventArgs : EventArgs { public string Command { get; set; } public int idx { get; set; } public MenuEventArgs(string cmd_, int idx_) { this.Command = cmd_; this.idx = idx_; } } protected override void OnMouseClick(MouseEventArgs e) { // if(DesignMode) // { // if(e.Button == System.Windows.Forms.MouseButtons.Right) // { // System.Windows.Forms.MessageBox.Show("Sdf"); // } // } // else { //마우스클릭시 해당 버튼을 찾아서 반환한다. if (menus == null || menus.Length < 1) return; for (int i = 0; i < menus.Length; i++) { var rect = rects[i]; if (rect.Contains(e.Location)) { var menu = menus[i]; //미사용개체는 이벤트를 아에 발생하지 않는다 if (menu.Enable == true && ItemClick != null) ItemClick(this, new MenuEventArgs(menu.Command, i)); break; } } } } protected override void OnMouseLeave(EventArgs e) { this.mouseOverItemIndex = -1; this.Invalidate(); } protected override void OnMouseMove(MouseEventArgs e) { if (menus == null || menus.Length < 1) { this.mouseOverItemIndex = -1; return; } for (int i = 0; i < menus.Length; i++) { var rect = rects[i]; if (rect.Contains(e.Location)) { if (i != mouseOverItemIndex) { mouseOverItemIndex = i; this.Invalidate(); } break; } } } protected override void OnPaint(PaintEventArgs pe) { // if(DesignMode) // { // pe.Graphics.FillRectangle(Brushes.Red, this.DisplayRectangle); // } //else { //배경그리기 using (var sb = new System.Drawing.Drawing2D.LinearGradientBrush(DisplayRectangle, BackColor, BackColor2, System.Drawing.Drawing2D.LinearGradientMode.Vertical)) pe.Graphics.FillRectangle(sb, DisplayRectangle); } //테두리 그리기 if (BorderSize > 0) { pe.Graphics.DrawRectangle(new Pen(this.BorderColor, BorderSize), this.DisplayRectangle.Left, this.DisplayRectangle.Top, this.DisplayRectangle.Width - 1, this.DisplayRectangle.Height - 1); } //커서모양 if (mouseOverItemIndex == -1) this.Cursor = Cursors.Arrow; else this.Cursor = Cursors.Hand; if (rects == null) RemakeChartRect(); if (rects != null && rects.Length > 0) { StringFormat sf = new StringFormat(StringFormatFlags.NoClip); var items = menus.OrderBy(t => t.No); int i = 0; foreach (var menu in items) { var rect = rects[i]; //배경이 투명이 아니라면 그린다. if (mouseOverItemIndex == i) { //마우스오버된놈이다. using (var sb = new System.Drawing.Drawing2D.LinearGradientBrush(rect, Color.FromArgb(100, Color.LightSkyBlue), Color.FromArgb(100, Color.DeepSkyBlue), System.Drawing.Drawing2D.LinearGradientMode.Vertical)) pe.Graphics.FillRectangle(sb, rect); } else { if (this.enablemenubakcolor == true && menu.BackColor != System.Drawing.Color.Transparent && menu.BackColor2 != System.Drawing.Color.Transparent) { using (var sb = new System.Drawing.Drawing2D.LinearGradientBrush(rect, menu.BackColor, menu.BackColor2, System.Drawing.Drawing2D.LinearGradientMode.Vertical)) pe.Graphics.FillRectangle(sb, rect); } } //이미지표시 int ix, iy, iw, ih; ix = iy = iw = ih = 0; if (menu.Image != null) { ix = rect.Left; iy = rect.Top; iw = ImageSize.Width; ih = ImageSize.Height; if (menu.ImageAlign == ContentAlignment.BottomCenter || menu.ImageAlign == ContentAlignment.BottomLeft || menu.ImageAlign == ContentAlignment.BottomRight) iy += DisplayRectangle.Bottom - ih; else if (menu.ImageAlign == ContentAlignment.MiddleCenter || menu.ImageAlign == ContentAlignment.MiddleLeft || menu.ImageAlign == ContentAlignment.MiddleRight) iy += (int)(DisplayRectangle.Top + ((rect.Height - ih) / 2.0)); else if (menu.ImageAlign == ContentAlignment.TopCenter || menu.ImageAlign == ContentAlignment.TopLeft || menu.ImageAlign == ContentAlignment.TopRight) iy += DisplayRectangle.Top; if (menu.ImageAlign == ContentAlignment.BottomCenter || menu.ImageAlign == ContentAlignment.MiddleCenter || menu.ImageAlign == ContentAlignment.TopCenter) ix += (int)(DisplayRectangle.Left + ((rect.Width - iw) / 2.0)); else if (menu.ImageAlign == ContentAlignment.BottomLeft || menu.ImageAlign == ContentAlignment.MiddleLeft || menu.ImageAlign == ContentAlignment.TopLeft) ix += DisplayRectangle.Left; else if (menu.ImageAlign == ContentAlignment.BottomRight || menu.ImageAlign == ContentAlignment.MiddleRight || menu.ImageAlign == ContentAlignment.TopRight) ix += DisplayRectangle.Right - iw; if (menu.ImagePadding.X != 0 || menu.ImagePadding.Y != 0) { ix += menu.ImagePadding.X; iy += menu.ImagePadding.Y; } else { ix += ImagePadding.X; iy += ImagePadding.Y; } if (menu.ImageSize.Width != 0 && menu.ImageSize.Height != 0) { iw = menu.ImageSize.Width; ih = menu.ImageSize.Height; } pe.Graphics.DrawImage(menu.Image, new Rectangle(ix, iy, iw, ih)); } //테두리를 그리는 속성과 트기가 설정된 경우에만 표시 if (mouseOverItemIndex == i) { pe.Graphics.DrawRectangle(new Pen(Color.DeepSkyBlue), rect); } else { if (EnableMenuBorder && MenuBorderSize > 0) { using (var p = new Pen(menu.BorderColor, MenuBorderSize)) pe.Graphics.DrawRectangle(p, rect); } } //글자를 텍스트 이후에 붙이는 거라면? if (menu.Image != null && TextAttachToImage) { var fsize = pe.Graphics.MeasureString(menu.Text, this.Font); pe.Graphics.DrawString(menu.Text, this.Font, new SolidBrush(menu.ForeColor), (float)(ix + iw + 1), (float)(iy + ((ih - fsize.Height) / 2.0))); } else { if (menu.TextAlign == ContentAlignment.BottomCenter || menu.TextAlign == ContentAlignment.BottomLeft || menu.TextAlign == ContentAlignment.BottomRight) sf.LineAlignment = StringAlignment.Far; else if (menu.TextAlign == ContentAlignment.MiddleCenter || menu.TextAlign == ContentAlignment.MiddleLeft || menu.TextAlign == ContentAlignment.MiddleRight) sf.LineAlignment = StringAlignment.Center; else if (menu.TextAlign == ContentAlignment.TopCenter || menu.TextAlign == ContentAlignment.TopLeft || menu.TextAlign == ContentAlignment.TopRight) sf.LineAlignment = StringAlignment.Near; if (menu.TextAlign == ContentAlignment.BottomCenter || menu.TextAlign == ContentAlignment.MiddleCenter || menu.TextAlign == ContentAlignment.TopCenter) sf.Alignment = StringAlignment.Center; else if (menu.TextAlign == ContentAlignment.BottomLeft || menu.TextAlign == ContentAlignment.MiddleLeft || menu.TextAlign == ContentAlignment.TopLeft) sf.Alignment = StringAlignment.Near; else if (menu.TextAlign == ContentAlignment.BottomRight || menu.TextAlign == ContentAlignment.MiddleRight || menu.TextAlign == ContentAlignment.TopRight) sf.Alignment = StringAlignment.Far; pe.Graphics.DrawString(menu.Text, this.Font, new SolidBrush(menu.ForeColor), rect, sf); } i += 1; } sf.Dispose(); } //if(DesignMode) //{ // pe.Graphics.DrawString("deisgn", this.Font, Brushes.Red, 1, 1); //} } /// /// arFrame 전용 속성값을 복사 합니다 /// /// public void copyTo(MenuControl ctl) { ctl.backcolor = this.backcolor; ctl.backcolor2 = this.BackColor2; ctl.MenuWidth = this.menuwidth; ctl.menugap = this.menugap; ctl.menus = this.menus; ctl.menubordersize = this.menubordersize; ctl.padding = this.padding; ctl.ForeColor = this.ForeColor; ctl.Font = this.Font; ctl.EnableMenuBackColor = this.EnableMenuBackColor; ctl.EnableMenuBorder = this.EnableMenuBorder; ctl.ImagePadding = this.ImagePadding; ctl.ImageSize = this.ImageSize; ctl.TextAttachToImage = this.TextAttachToImage; ctl.bordercolor = this.bordercolor; ctl.bordersize = this.bordersize; } public void Save(string File) { //xml로 데이터를 저장자 System.Text.StringBuilder NewXml = new System.Text.StringBuilder(); NewXml.AppendLine(""); NewXml.AppendLine(" "); NewXml.AppendLine(""); if (System.IO.File.Exists(File)) System.IO.File.Delete(File); System.IO.File.WriteAllText(File, NewXml.ToString().Replace('\'', '\"'), System.Text.Encoding.UTF8); var vDocu = new XmlDocument(); vDocu.Load(File); //var nsmgr = new XmlNamespaceManager(new System.Xml.NameTable()); //nsmgr.AddNamespace("x", "http://tindevil.com"); var Root = vDocu.DocumentElement; //저장하려는 속성목록을 먼저 생성한다 //미사용 목록이 너무 많아서 그렇게 함 foreach (var m in this.GetType().GetMethods()) { var mName = m.Name.ToLower(); if (mName.StartsWith("get_") == false || mName == "get_menus") continue; var pt = this.GetType().GetProperty(m.Name.Substring(4)); if (pt != null) { var categoryName = GetCategoryName(pt); if (categoryName.ToLower() != "arframe") continue; //자료형에따라서 그값을 변경한다 var value = m.Invoke(this, null); var newNode = vDocu.CreateElement(pt.Name);// m.Name.Substring(4)); newNode.InnerText = getValueString(m, value); Root.AppendChild(newNode); } } foreach (var item in this.menus.OrderBy(t => t.No)) { var node = vDocu.CreateElement("Item"); var attNo = vDocu.CreateAttribute("No"); attNo.Value = item.No.ToString(); node.Attributes.Append(attNo); foreach (var m in item.GetType().GetMethods()) { var mName = m.Name.ToLower(); if (mName.StartsWith("get_") == false || mName == "get_no") continue; var value = m.Invoke(item, null); var sNode = vDocu.CreateElement(m.Name.Substring(4)); sNode.InnerText = getValueString(m, value); node.AppendChild(sNode); } Root.AppendChild(node); } vDocu.Save(File); } public void Load(string File) { if (System.IO.File.Exists(File) == false) return; List NewMenu = new List(); var vDocu = new XmlDocument(); vDocu.Load(File); var Root = vDocu.DocumentElement; //루트요소(Tindevil) //저장하려는 속성목록을 먼저 생성한다 //미사용 목록이 너무 많아서 그렇게 함 foreach (var m in this.GetType().GetMethods()) { var mName = m.Name.ToLower(); if (mName.StartsWith("get_") == false || mName == "get_menus") continue; var methodName = m.Name.Substring(4); var pt = this.GetType().GetProperty(methodName); if (pt != null) { var categoryName = GetCategoryName(pt); if (categoryName.ToLower() != "arframe") continue; //SEt명령이 있어야 사용이 가능하다 var setMethod = this.GetType().GetMethod("set_" + methodName); if (setMethod == null) continue; //값을 읽어온다 var Node = Root.SelectSingleNode(methodName); if (Node != null) { var strValue = Node.InnerText; var value = getValueFromString(m.ReturnType, strValue); // setValueString(m.ReturnType, setMethod, strValue); setMethod.Invoke(this, new object[] { value }); } } } //foreach (var item in this.menus.OrderBy(t => t.No)) //{ // var node = vDocu.CreateElement("Item"); // var attNo = vDocu.CreateAttribute("No"); // attNo.Value = item.No.ToString(); // node.Attributes.Append(attNo); // foreach (var m in item.GetType().GetMethods()) // { // var mName = m.Name.ToLower(); // if (mName.StartsWith("get_") == false || mName == "get_no") continue; // var value = m.Invoke(item, null); // var sNode = vDocu.CreateElement(m.Name.Substring(4)); // sNode.InnerText = getValueString(m, value); // node.AppendChild(sNode); // } // Root.AppendChild(node); //} } private string getValueString(System.Reflection.MethodInfo m, object value) { var strValue = ""; string valuetype = m.ReturnType.Name.ToLower(); if (m.ReturnType == typeof(System.Drawing.Color)) strValue = ((System.Drawing.Color)value).ToArgb().ToString(); else if (m.ReturnType == typeof(System.Drawing.Rectangle)) { var rect = (System.Drawing.Rectangle)value; strValue = string.Format("{0};{1};{2};{3}", rect.Left, rect.Top, rect.Width, rect.Height); } else if (m.ReturnType == typeof(System.Drawing.RectangleF)) { var rectf = (System.Drawing.RectangleF)value; strValue = string.Format("{0};{1};{2};{3}", rectf.Left, rectf.Top, rectf.Width, rectf.Height); } else if (m.ReturnType == typeof(Boolean)) { strValue = ((Boolean)value) ? "1" : "0"; } else if (m.ReturnType == typeof(System.Drawing.Point)) { var pt1 = (Point)value; strValue = string.Format("{0};{1}", pt1.X, pt1.Y); } else if (m.ReturnType == typeof(System.Drawing.PointF)) { var ptf = (PointF)value; strValue = string.Format("{0};{1}", ptf.X, ptf.Y); } else if (m.ReturnType == typeof(System.Drawing.Size)) { var sz = (Size)value; strValue = string.Format("{0};{1}", sz.Width, sz.Height); } else if (m.ReturnType == typeof(System.Drawing.SizeF)) { var szf = (SizeF)value; strValue = string.Format("{0};{1}", szf.Width, szf.Height); } else if (m.ReturnType == typeof(System.Drawing.Bitmap)) { var bitmap = (Bitmap)value; // Convert the image to byte[] System.IO.MemoryStream stream = new System.IO.MemoryStream(); bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); byte[] imageBytes = stream.ToArray(); strValue = Convert.ToBase64String(imageBytes); } else if (m.ReturnType == typeof(System.Windows.Forms.Padding)) { var pd = (System.Windows.Forms.Padding)value; strValue = string.Format("{0};{1};{2};{3}", pd.Left, pd.Top, pd.Right, pd.Bottom); } else strValue = value.ToString(); return strValue; } private object getValueFromString(Type ReturnType, string strValue) { if (ReturnType == typeof(System.Drawing.Color)) { var cint = int.Parse(strValue); return System.Drawing.Color.FromArgb(cint); } else if (ReturnType == typeof(System.Drawing.Rectangle)) { var buf = strValue.Split(';'); var x = int.Parse(buf[0]); var y = int.Parse(buf[1]); var w = int.Parse(buf[2]); var h = int.Parse(buf[3]); return new Rectangle(x, y, w, h); } else if (ReturnType == typeof(System.Drawing.RectangleF)) { var buf = strValue.Split(';'); var x = float.Parse(buf[0]); var y = float.Parse(buf[1]); var w = float.Parse(buf[2]); var h = float.Parse(buf[3]); return new RectangleF(x, y, w, h); } else if (ReturnType == typeof(Boolean)) { return strValue == "1"; } else if (ReturnType == typeof(System.Drawing.Point)) { var buf = strValue.Split(';'); var x = int.Parse(buf[0]); var y = int.Parse(buf[1]); return new Point(x, y); } else if (ReturnType == typeof(System.Drawing.PointF)) { var buf = strValue.Split(';'); var x = float.Parse(buf[0]); var y = float.Parse(buf[1]); return new PointF(x, y); } else if (ReturnType == typeof(System.Drawing.Size)) { var buf = strValue.Split(';'); var x = int.Parse(buf[0]); var y = int.Parse(buf[1]); return new Size(x, y); } else if (ReturnType == typeof(System.Drawing.SizeF)) { var buf = strValue.Split(';'); var x = float.Parse(buf[0]); var y = float.Parse(buf[1]); return new SizeF(x, y); } else if (ReturnType == typeof(System.Drawing.Bitmap)) { //문자을을 바이트로 전환다 byte[] imageBytes = Convert.FromBase64String(strValue); Bitmap retval = null; using (System.IO.MemoryStream stream = new System.IO.MemoryStream(imageBytes)) retval = new Bitmap(stream); return retval; } else if (ReturnType == typeof(System.Windows.Forms.Padding)) { var buf = strValue.Split(';'); var x = int.Parse(buf[0]); var y = int.Parse(buf[1]); var w = int.Parse(buf[2]); var h = int.Parse(buf[3]); return new Padding(x, y, w, h); } else if (ReturnType == typeof(Int16)) return Int16.Parse(strValue); else if (ReturnType == typeof(Int32)) return Int32.Parse(strValue); else if (ReturnType == typeof(Int64)) return Int64.Parse(strValue); else if (ReturnType == typeof(UInt16)) return UInt16.Parse(strValue); else if (ReturnType == typeof(UInt32)) return UInt32.Parse(strValue); else return strValue; } public string GetCategoryName(System.Reflection.PropertyInfo m) { var displayName = m .GetCustomAttributes(typeof(CategoryAttribute), true) .FirstOrDefault() as CategoryAttribute; if (displayName != null) return displayName.Category; return ""; } public string GetDisplayName(System.Reflection.MethodInfo m) { var displayName = m .GetCustomAttributes(typeof(DisplayNameAttribute), true) .FirstOrDefault() as DisplayNameAttribute; if (displayName != null) return displayName.DisplayName; return ""; } public void RemakeChartRect() { if (rects != null) rects = null; if (menus == null || menus.Length < 1) return; rects = new Rectangle[menus.Length]; int leftIdx = 0; int rightIdx = 0; int leftAcc = 0; int rightAcc = 0; int i = 0; var menuList = this.menus.OrderBy(t => t.No).ToArray(); foreach (var menu in menuList) { int x, y, w, h; // var menu = menus[i]; var mWidth = menuwidth; if (menu.MenuWidth > 0) mWidth = menu.MenuWidth; w = mWidth; h = DisplayRectangle.Height - Padding.Top - Padding.Bottom; if (menu.isRightMenu) { x = DisplayRectangle.Right - Padding.Right - (rightAcc) - (MenuGap * rightIdx); y = DisplayRectangle.Top + Padding.Top; rightAcc += 0;// = 0;// x; rightIdx += 1; } else { x = DisplayRectangle.Left + Padding.Left + leftAcc + (MenuGap * leftIdx); y = DisplayRectangle.Top + Padding.Top; leftAcc += mWidth; leftIdx += 1; } rects[i] = new Rectangle(x, y, w, h); i += 1; } } } }