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; namespace arFrame.Control { public partial class GridView : System.Windows.Forms.Control { private int bordersize = 0; private int menubordersize = 1; 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 bordercolor = System.Drawing.Color.Black; private Boolean textattachtoimage = true; private Boolean _showIndexString = true; private System.Drawing.Color _shadowColor = System.Drawing.Color.Transparent; private System.Drawing.Color foreColorPin = System.Drawing.Color.WhiteSmoke; private System.Drawing.Font fontPin = new Font("Consolas", 8, FontStyle.Bold); private Point _matrixsize = new Point(8, 2); public Point MatrixSize { get { return _matrixsize; } set { _matrixsize = value; ResetArray(); RemakeChartRect(); } } public Boolean arVeriticalDraw { get; set; } [Browsable(false)] public int ColumnCount { get { return _matrixsize.X; } } [Browsable(false)] public int RowCount { get { return _matrixsize.Y; } } public int ItemCount { get { return ColumnCount * RowCount; } } private GridViewItem[] Items; private UInt16[] _values; private string[] _titles; private string[] _tags; private string[] _names; private ColorListItem[] _colorlist; public ColorListItem[] ColorList { get { return _colorlist; } set { _colorlist = value; this.Invalidate(); } } public string[] Names { get { return _names; } set { _names = value; Invalidate(); } } public string[] Titles { get { return _titles; } set { _titles = value; Invalidate(); } } public UInt16[] Values { get { return _values; } set { _values = value; Invalidate(); } } public string[] Tags { get { return _tags; } set { _tags = value; } } private bool _showdebuginfo = false; public Boolean showDebugInfo { get { return _showdebuginfo; } set { _showdebuginfo = value; Invalidate(); } } public void setNames(string[] value) { _names = value; } public void setTitle(string[] value) { List titlerows = new List(); List tagrows = new List(); for (int i = 0; i < value.Length; i++) { var r = (int)(Math.Floor((double)(i / ColumnCount))); var c = i % ColumnCount; //세로 그리기 였을때에는 다르게 처리해야함 201215 if(arVeriticalDraw) { c = (int)(Math.Floor((double)(i / ColumnCount))); r = i % ColumnCount; } if (titlerows.Count < r + 1) titlerows.Add(string.Empty); if (tagrows.Count < r + 1) tagrows.Add(string.Empty); var prestr = titlerows[r]; if (c > 0 ) prestr += "|"; titlerows[r] = prestr + value[i]; var prestr_t = tagrows[r]; if (prestr_t != "") prestr_t += "|"; tagrows[r] = prestr_t + ""; if (i < itemCount) this.Items[i].Enable = true; } this._titles = titlerows.ToArray(); this._tags = tagrows.ToArray(); } public void setTags(string[] value) { List titlerows = new List(); for (int i = 0; i < value.Length; i++) { var r = (int)(Math.Floor((double)(i / ColumnCount))); var c = i % ColumnCount; if (titlerows.Count < r + 1) titlerows.Add(string.Empty); var prestr = titlerows[r]; if (c > 0 ) prestr += "|"; titlerows[r] = prestr + value[i]; if (i < itemCount) this.Items[i].Enable = true; } this._tags = titlerows.ToArray(); } public Boolean setTitle(int row, int col, string value, string itemtag = "") { if (_titles == null) _titles = new string[0]; if (_tags == null) _tags = new string[0]; if (row >= _titles.Length) Array.Resize(ref _titles, row + 1); if (row >= _tags.Length) Array.Resize(ref _tags, row + 1); if (_titles[row] == null) _titles[row] = string.Empty; if (_tags[row] == null) _tags[row] = string.Empty; var linebuf = _titles[row].Split('|'); var linebuf_t = _tags[row].Split('|'); if (col >= linebuf.Length) Array.Resize(ref linebuf, col + 1); if (col >= linebuf_t.Length) Array.Resize(ref linebuf_t, col + 1); linebuf[col] = value; linebuf_t[col] = itemtag; _titles[row] = string.Join("|", linebuf); _tags[row] = string.Join("|", linebuf_t); return true; //var idx = row * this.ColumnCount + col; //return setTitle(idx, value); } public Boolean setTitle(int idx, string value) { if (idx < ColumnCount) return setTitle(0, idx, value); else { //줄값이 필요하다 var row = (int)(Math.Floor((double)(idx / ColumnCount))); var col = idx % ColumnCount; return setTitle(row, col, value); } } public void setValue(bool[] value) { var v = new UInt16[value.Length]; for (int i = 0; i < value.Length; i++) v[i] = (UInt16)(value[i] ? 1 : 0); _values = v; //값이 잇으니 enable 한다 for (int i = 0; i < value.Length; i++) { if (i < Items.Length) this.Items[i].Enable = true; } } public void setValue(UInt16[] value) { _values = value; for (int i = 0; i < value.Length; i++) { if (i < Items.Length) this.Items[i].Enable = true; } } public Boolean setValue(int idx, ushort value) { if (idx >= _values.Length || idx >= this.Items.Length) return false; this._values[idx] = value; this.Items[idx].Enable = true; return true; } public void ClearValue(ushort defaultValue = 0) { if (_values != null) for (int i = 0; i < _values.Length; i++) _values[i] = defaultValue; } public void ClearTitle(string defaultValue = "") { if (_values != null) for (int i = 0; i < _titles.Length; i++) _titles[i] = defaultValue; } public void setValue(ushort value) { for (int i = 0; i < _values.Length; i++) this._values[i] = value; } public void setItemEnable(int idx, bool value) { if (idx >= _values.Length || idx >= this.Items.Length) return; this.Items[idx].Enable = value; } /// /// 지정된 컬러태그값을 입력한다. /// /// /// /// public Boolean setValue(int idx, string tagString) { //동일태그값을 찾는다 if (idx >= _values.Length) return false; int value = -1; for (int i = 0; i < ColorList.Length; i++) if (ColorList[i].Remark.ToLower() == tagString.ToLower()) { value = i; break; } if (value != -1) { this._values[idx] = (ushort)value; this.Items[idx].Enable = true; return true; } else return false; } public Boolean setValue(int idx, bool value) { return setValue(idx, (ushort)(value ? 1 : 0)); } public Boolean setValue(int row, int col, ushort value) { var idx = row * this.ColumnCount + col; return setValue(idx, value); } public Boolean setValueToggle(int row, int col, ushort value1, ushort value2) { var idx = row * this.ColumnCount + col; if (getValue(idx) == value1) return setValue(idx, value2); else return setValue(idx, value1); } public Boolean setValue(int row, int col, bool value) { var idx = row * this.ColumnCount + col; return setValue(idx, (ushort)(value ? 1 : 0)); } public Boolean setValue(int row, int col, string value) { var idx = row * this.ColumnCount + col; return setValue(idx, value); } public ushort getValue(int idx) { if (idx >= _values.Length) return 0; return _values[idx]; } public ushort getValue(int row, int col) { var idx = row * this.ColumnCount + col; return getValue(idx); } [Category("arFrame")] public bool ShowIndexString { get { return _showIndexString; } set { _showIndexString = value; Invalidate(); } } [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 MenuGap { get { return menugap; } set { this.menugap = value; RemakeChartRect(); Invalidate(); } } [Category("arFrame"), DisplayName("글자를 이미지 다음에 표시"), Description("이미지가 있는 경우 해당 이미지 옆에 글자를 붙입니다")] public Boolean TextAttachToImage { get { return textattachtoimage; } set { this.textattachtoimage = value; Invalidate(); } } [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("색상-전체배경색")] public override System.Drawing.Color BackColor { get { return backcolor; } set { this.backcolor = value; Invalidate(); } } [Category("arFrame"), DisplayName("색상-글자(그림자)")] public System.Drawing.Color ShadowColor { get { return _shadowColor; } set { _shadowColor = value; this.Invalidate(); } } [Category("arFrame"), DisplayName("색상-글자")] public override Color ForeColor { get { return base.ForeColor; } set { base.ForeColor = value; } } [Category("arFrame"), DisplayName("색상-글자(번호)")] public Color ForeColorPin { get { return foreColorPin; } set { foreColorPin = value; } } [Category("arFrame"), DisplayName("글꼴-번호")] public Font FontPin { get { return fontPin; } set { fontPin = value; Invalidate(); } } [Category("arFrame"), DisplayName("글꼴-항목")] public override Font Font { get { return base.Font; } set { base.Font = value; Invalidate(); } } private int mouseOverItemIndex = -1; public GridView() { 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); //값과 이름은 외부의 값을 사용한다 ResetArray(); if (MinimumSize.Width == 0 || MinimumSize.Height == 0) MinimumSize = new Size(100, 50); } void ResetArray() { if (this._values != null) Array.Resize(ref this._values, itemCount);// = new UInt16[itemCount]; // if (this._titles != null) Array.Resize(ref this._titles, itemCount);// // if (this._names != null) Array.Resize(ref this._names, itemCount);// } int itemCount { get { return ColumnCount * RowCount; } } protected override void OnSizeChanged(EventArgs e) { base.OnSizeChanged(e); RemakeChartRect(); } public event EventHandler ItemClick; public class ItemClickEventArgs : EventArgs { public int idx { get; set; } public GridViewItem Item { get; set; } public ItemClickEventArgs(int idx_, GridViewItem item) { this.Item = item; this.idx = idx_; } } protected override void OnMouseClick(MouseEventArgs e) { //마우스클릭시 해당 버튼을 찾아서 반환한다. if (Items == null || Items.Length < 1) return; for (int i = 0; i < Items.Length; i++) { var rect = Items[i].rect;//[i]; if (rect.Contains(e.Location)) { var menu = Items[i]; //미사용개체는 이벤트를 아에 발생하지 않는다 if (menu.Enable == true && ItemClick != null) ItemClick(this, new ItemClickEventArgs(i, menu)); break; } } } protected override void OnMouseLeave(EventArgs e) { this.mouseOverItemIndex = -1; this.Invalidate(); } protected override void OnMouseMove(MouseEventArgs e) { if (Items == null || Items.Length < 1) { this.mouseOverItemIndex = -1; return; } for (int i = 0; i < Items.Length; i++) { var rect = Items[i].rect;// rects[i]; if (rect.Contains(e.Location)) { if (i != mouseOverItemIndex) { mouseOverItemIndex = i; this.Invalidate(); } break; } } } public void setItemTextAlign(int row, int col, System.Drawing.ContentAlignment TextAlign) { var item = this.Items.Where(t => t.row == row && t.col == col).FirstOrDefault(); if (item != null) item.TextAlign = TextAlign; } public void setItemTextAlign(System.Drawing.ContentAlignment TextAlign) { foreach (var item in this.Items) item.TextAlign = TextAlign; } protected override void OnPaint(PaintEventArgs pe) { //배경그리기 //using (var sb = new System.Drawing.Drawing2D.LinearGradientBrush(DisplayRectangle, BackColor, BackColor2On, System.Drawing.Drawing2D.LinearGradientMode.Vertical)) pe.Graphics.FillRectangle(new SolidBrush(BackColor), DisplayRectangle); if (Items == null) { pe.Graphics.DrawString("no items", this.Font, Brushes.Red, 100, 100); return; } var items = Items.OrderBy(t => t.No); foreach (var menu in items) { drawItem(menu.idx, pe.Graphics); } //테두리 그리기 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); } } public void drawItem(int itemIndex, Graphics g = null) { if (g == null) g = this.CreateGraphics(); var menu = this.Items[itemIndex]; if (menu.rect == RectangleF.Empty) return; var rect = menu.rect;// rects[i]; var diplayText = string.Empty; // if(_titles[1].Trim() != "") // Console.WriteLine("sdf"); //타이틀이 줄번호별로 처리됨 if (_titles != null && menu.row < _titles.Length) { if (_titles[menu.row] == null) _titles[menu.row] = string.Empty; var linebif = _titles[menu.row].Split('|'); if (menu.col < linebif.Length) diplayText = linebif[menu.col]; } UInt16 Value = 0; if (_values != null && menu.idx < _values.Length) Value = _values[menu.idx]; //배경이 투명이 아니라면 그린다. var bgColor1 = Color.FromArgb(30, 30, 30);// BackColor1Off; var bgColor2 = Color.FromArgb(30, 30, 30);// BackColor2Off; //해당 값에 따른 컬러값을 읽는다. if (ColorList != null && Value < ColorList.Length) { bgColor1 = this.ColorList[Value].BackColor1; bgColor2 = this.ColorList[Value].BackColor2; } using (var sb = new System.Drawing.Drawing2D.LinearGradientBrush(rect, bgColor1, bgColor2, System.Drawing.Drawing2D.LinearGradientMode.Vertical)) g.FillRectangle(sb, rect); // if (mouseOverItemIndex == menu.idx) // this.Cursor = Cursors.Hand; // else // this.Cursor = Cursors.Arrow; //테두리를 그리는 속성과 트기가 설정된 경우에만 표시 //if (mouseOverItemIndex == i) // { // pe.Graphics.DrawRectangle(new Pen(Color.DeepSkyBlue), rect.Left, rect.Top, rect.Width, rect.Height); //} //else { if (MenuBorderSize > 0) { using (var p = new Pen(BorderColor, MenuBorderSize)) g.DrawRectangle(p, rect.Left, rect.Top, rect.Width, rect.Height); } } //인덱스번호 출력 if (ShowIndexString && _names != null && menu.idx < _names.Length) { //표시글자 var idxstr = string.Format("[{0}] {1}", menu.idx, _names[menu.idx]); //그림자 추가 if (ShadowColor != System.Drawing.Color.Transparent) g.DrawString(idxstr, FontPin, new SolidBrush(ShadowColor), menu.rect.Left + 4, menu.rect.Top + 4); //일반글자표시 g.DrawString(idxstr, FontPin, new SolidBrush(this.ForeColorPin), menu.rect.Left + 3, menu.rect.Top + 3); } if (diplayText != "") { using (StringFormat sf = new StringFormat(StringFormatFlags.NoClip)) { //글자를 텍스트 이후에 붙이는 거라면? 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; //그림자 추가 if (ShadowColor != System.Drawing.Color.Transparent) g.DrawString(diplayText, this.Font, new SolidBrush(ShadowColor), new RectangleF((float)(rect.Left + 1f), (float)(rect.Top + 1f), (float)rect.Width, (float)rect.Height), sf); g.DrawString($"{diplayText}", this.Font, new SolidBrush(ForeColor), rect, sf); } } if (showDebugInfo) { g.DrawString(Value.ToString(), this.fontPin, Brushes.SkyBlue, rect.Left, rect.Top); } } /// /// arFrame 전용 속성값을 복사 합니다 /// /// public void copyTo(GridView ctl) { ctl.backcolor = this.backcolor; ctl.menugap = this.menugap; ctl.Items = this.Items; ctl.menubordersize = this.menubordersize; ctl.padding = this.padding; ctl.ForeColor = this.ForeColor; ctl.Font = this.Font; ctl.TextAttachToImage = this.TextAttachToImage; ctl.bordercolor = this.bordercolor; ctl.bordersize = this.bordersize; } public void RemakeChartRect() { if (DisplayRectangle == Rectangle.Empty) return; double x = 0; double y = 0; double w = DisplayRectangle.Width / (ColumnCount * 1.0); double h = DisplayRectangle.Height / (RowCount * 1.0); //아이템갯수가 달라졌으므로 다시 갱신해야함 GridViewItem[] item = new GridViewItem[RowCount * ColumnCount]; if(arVeriticalDraw) { for (int c = 0; c < ColumnCount; c++) { for (int r = 0; r < RowCount; r++) { int idx = c * ColumnCount + r; item[idx] = new GridViewItem(idx, r, c); if (this.Items != null && idx < this.Items.Length) item[idx].Enable = this.Items[idx].Enable; // false; else item[idx].Enable = false; item[idx].Padding = new Padding(0, 0, 0, 0); item[idx].TextAlign = ContentAlignment.MiddleCenter; x = (c * w); y = (r * h); item[idx].Dirty = true; item[idx].rect = new RectangleF((float)x, (float)y, (float)w, (float)h); } } } else { for (int r = 0; r < RowCount; r++) { for (int c = 0; c < ColumnCount; c++) { int idx = r * ColumnCount + c; item[idx] = new GridViewItem(idx, r, c); if (this.Items != null && idx < this.Items.Length) item[idx].Enable = this.Items[idx].Enable; // false; else item[idx].Enable = false; item[idx].Padding = new Padding(0, 0, 0, 0); item[idx].TextAlign = ContentAlignment.MiddleCenter; x = (c * w); y = (r * h); item[idx].Dirty = true; item[idx].rect = new RectangleF((float)x, (float)y, (float)w, (float)h); } } } this.Items = item; this.Invalidate(); } } }