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 StaffLayoutCtl { public partial class grid : Control { public Boolean DeveloperMode = true; private Point GridCount = new Point(30, 20); private CGrid[,] gridrect = null; public grid() { InitializeComponent(); // Set Optimized Double Buffer to reduce flickering this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); // Redraw when resized this.SetStyle(ControlStyles.ResizeRedraw, true); this.Resize += arLabel_Resize; this.MouseDown += grid_MouseDown; this.MouseMove += grid_MouseMove; this.MouseUp += grid_MouseUp; gridrect = new CGrid[GridCount.X, GridCount.Y]; } void grid_MouseUp(object sender, MouseEventArgs e) { Boolean bOK = false; if(mousedn && mouseDrag && selectindex != -1 && diffrect != RectangleF.Empty) { if(Math.Abs(mousediff.X) >= 10 && Math.Abs(mousediff.Y) >= 10) { //좌측코드가 속한 row,col 값으로 이동한다. for(int i = 0; i<= gridrect.GetUpperBound(0);i++) { for (int j = 0; j <= gridrect.GetUpperBound(1); j++) { var grid = this.gridrect[i, j]; if(grid.Rect.Contains( diffrect.Location )) { var item = this.Items[selectindex]; item.Row = grid.Row; item.Col = grid.Col; bOK = true; break; } } if (bOK) break; } } } mousedn = false; mouseDrag = false; this.Invalidate(); } void grid_MouseMove(object sender, MouseEventArgs e) { mousepos = e.Location; if (mousedn) mouseDrag = true; else mouseDrag = false; //선택개체 위로 오면 마우스 모양을 변경한다. if (selectindex < 0) { if (this.Cursor != Cursors.Arrow) { this.Cursor = Cursors.Arrow; this.Invalidate(); } } else { var item = Items[selectindex]; //중앙부에 있다면 이동형 핸드를 //외곽에 있다면 크기 조정용 을 표시한다. //크기조정용 영역을 게산한다. RectangleF rectt = new RectangleF(item.Rect.Left, item.Rect.Top - 10, item.Rect.Width, 20); RectangleF rectb = new RectangleF(item.Rect.Left, item.Rect.Bottom - 10, item.Rect.Height, 20); RectangleF rectl = new RectangleF(item.Rect.Left - 10, item.Rect.Top, 20, item.Rect.Height); RectangleF rectr = new RectangleF(item.Rect.Right - 10, item.Rect.Top, 20, item.Rect.Height); if (rectt.Contains(e.Location)) { if (this.Cursor != Cursors.PanNorth) { this.Cursor = Cursors.PanNorth; this.Invalidate(); } } else if (rectb.Contains(e.Location)) { if (this.Cursor != Cursors.PanSouth) { this.Cursor = Cursors.PanSouth; this.Invalidate(); } } else if (rectl.Contains(e.Location)) { if (this.Cursor != Cursors.PanWest) { this.Cursor = Cursors.PanWest; this.Invalidate(); } } else if (rectr.Contains(e.Location)) { if (this.Cursor != Cursors.PanEast) { this.Cursor = Cursors.PanEast; this.Invalidate(); } } else if (item.Rect.Contains(e.Location)) { if (this.Cursor != Cursors.Hand) { this.Cursor = Cursors.Hand; this.Invalidate(); } } else { if (this.Cursor != Cursors.Arrow) { this.Cursor = Cursors.Arrow; this.Invalidate(); } else { if (mousedn) { } } } this.Invalidate(); //화면이 업데이트되도록 함 } } Boolean mouseDrag = false; Boolean mousedn = false; Point mousednpos = Point.Empty; Point mousepos = Point.Empty; int selectindex = -1; void grid_MouseDown(object sender, MouseEventArgs e) { mousedn = true; //save down point mousednpos = e.Location; //선택된 아이템을 찾아야한다. Boolean selected = false; int r = 0; int c = 0; for (int i = 0; i < Items.Count; i++) { var item = Items[i]; if (item.Rect.Contains(e.Location)) { selectindex = i; selected = true; r = item.Row; c = item.Col; selectRect = item.Rect; //다른 아이템의 선택을 해제한다. Console.WriteLine(string.Format("select item : {0}/{1}", item.Row, item.Col)); break; } } if (selected) { foreach (var item in Items) { if (item.Row == r && item.Col == c) item.Select = true; else item.Select = false; } } else { selectindex = -1; var selitem = Items.Where(t => t.Select); foreach (var item in selitem) item.Select = false; } Invalidate(); } void arLabel_Resize(object sender, EventArgs e) { Make_Grid(); Invalidate(); } Point mousediff = Point.Empty; RectangleF diffrect = RectangleF.Empty; protected override void OnPaint(PaintEventArgs pe) { base.OnPaint(pe); Draw_Grid(pe.Graphics); Draw_Item(pe.Graphics); if (mouseDrag && mousedn && selectindex != -1 && mousednpos != Point.Empty) { mousediff = new Point(mousepos.X - mousednpos.X, mousepos.Y - mousednpos.Y); //이동영역을 diffrect = new RectangleF(selectRect.Left + mousediff.X, selectRect.Top + mousediff.Y, selectRect.Width, selectRect.Height); using(SolidBrush sb = new SolidBrush(Color.FromArgb(100,Color.Gray))) { pe.Graphics.FillRectangle(sb, diffrect); } pe.Graphics.DrawRectangle(Pens.DimGray, diffrect.Left, diffrect.Top, diffrect.Width, diffrect.Height); } Draw_Debug(pe.Graphics); } void Draw_Debug(Graphics g) { System.Text.StringBuilder sb = new StringBuilder(); sb.AppendLine("diff = " + mousediff.ToString()); sb.AppendLine("drag : " + mouseDrag.ToString()); sb.AppendLine("mouse down : " + mousedn.ToString() + ", " + mousednpos.ToString()); sb.AppendLine("mouse pos : " + this.mousepos.ToString()); sb.AppendLine("select index : " + this.selectindex.ToString() + "," + this.selectRect.ToString()); sb.AppendLine("sel rect : " + this.selectRect.ToString()); sb.AppendLine("diff rect : " + this.diffrect.ToString()); sb.AppendLine("cell size : " + cellSize.ToString()); using (Font f = new Font("Consolas", 20f)) { g.DrawString(sb.ToString(), f, Brushes.Black, 50 - 1, 50 - 1); g.DrawString(sb.ToString(), f, Brushes.Black, 50 - 1, 50 + 1); g.DrawString(sb.ToString(), f, Brushes.Black, 50 + 1, 50 - 1); g.DrawString(sb.ToString(), f, Brushes.Black, 50 + 1, 50 + 1); g.DrawString(sb.ToString(), f, Brushes.Red, 50, 50); } } public List Items = new List(); RectangleF selectRect = RectangleF.Empty; SizeF cellSize = SizeF.Empty; void Draw_Item(Graphics g) { if (DeveloperMode) { //demo item Items.Clear(); Items.Add(new CItem(r: 1, c: 1, rs: 2, cs: 2, text: "김치균", bg: Color.White.ToArgb())); Items.Add(new CItem(4, 4, 1, 1, "박성민")); Items.Add(new CItem(6, 6, 10, 3, "고진일")); Items.Add(new CItem(7, 7, 2, 2, "테스트")); Items[1].Select = true; } int idx = 0; foreach (var item in Items) { float x = item.Col * cellSize.Width; float y = item.Row * cellSize.Height; float w = item.ColSpan * cellSize.Width; float h = item.RowSpan * cellSize.Height; RectangleF rectf = new RectangleF(x, y, w, h); g.FillRectangle(Brushes.Yellow, rectf); item.Rect = rectf; if (item.Select) { g.DrawRectangle(new Pen(Color.Blue, 4f), rectf.Left, rectf.Top, rectf.Width, rectf.Height); //크기조정을 위한 좌우 화살표가 필요하다. } string data = idx.ToString(); if (item.Text != "'") data = item.Text; g.DrawString(data + item.Select.ToString(), this.Font, Brushes.Black, x, y); idx += 1; } } void Make_Grid() { float gw = DisplayRectangle.Width / GridCount.Y; float gh = DisplayRectangle.Height / GridCount.X; cellSize = new SizeF(gw, gh); for (int i = 0; i < GridCount.X; i++) { for (int j = 0; j < GridCount.Y; j++) { int idx = (i * GridCount.Y) + j; RectangleF rect = new RectangleF(j * gw, i * gh, gw, gh); ; this.gridrect[i, j] = new CGrid(idx); this.gridrect[i, j].Rect = rect; this.gridrect[i, j].Row = i; this.gridrect[i, j].Col = j; } } } void Draw_Grid(Graphics g) { if(gridrect[0,0]== null) Make_Grid(); for (int i = 0; i <= gridrect.GetUpperBound(0); i++) { for (int j = 0; j <= gridrect.GetUpperBound(1); j++) { var grid = this.gridrect[i, j]; g.DrawRectangle(Pens.Black, grid.Rect.Left, grid.Rect.Top, grid.Rect.Width, grid.Rect.Height); g.DrawString(grid.IDX.ToString(), this.Font, Brushes.Blue, grid.Rect.Left, grid.Rect.Top); } } } } }