using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace TrendCtrlII { public enum EDRAGTYPE { SCREEN, ZOOM, UC } public enum EBUTTONTYPE { LEFTMON, RIGHTMON } public enum EALIGN { LEFT, CENTER, RIGHT } public partial class TrendCtrlII : UserControl { private ChartStyle _Style = new ChartStyle(); public CMouseinfo Mouseinfo; //마우스위치정보 public string yymm; private Int64 starttime; private Int64 endtime; //zoom area private Int64 startview; //zoom 시작시간 private Int64 endview; //zoom 종료시간 public Int64 startviewo; //zoom 시작시간 public Int64 endviewo; //zoom 종료시간 public Int64 querystart; public Int64 queryend; public Single LineWidth = 1; private Rectangle UserZoom; //사용자줌영역 //실값 public Single[] values; public int[] times; private CChinfo[] chinfo; private Rectangle Cursorrect; //화면상의 버튼데이터 //private List Buttons = new List(0); //private List Buttonstag = new List(0); //private List Buttonstype = new List(0); private Boolean init; //그리드초기화완료여부 public String initmsg = "initializing..."; public int initpercent = 0; public List uc = new List(0); //사용자커서 최대2개까지한다. //미정리 //MY EVENT //public event OnClickProbeSensorHandlerL OnClickLEFT; //셀클릭 //public delegate void OnClickProbeSensorHandlerL(); //public event OnClickProbeSensorHandlerR OnClickRIGHT; //셀클릭 //public delegate void OnClickProbeSensorHandlerR(); public event OnUpdateUserControlHandler OnUpdateUserCursor; //UPDATE USER CURSOR public delegate void OnUpdateUserControlHandler(int idx); //화면디자인관련 private Cursor cursor = Cursors.Default; //현재커서의모양 private StringBuilder Warn_msg = new StringBuilder(""); //경고메세지(화면 최상단중앙에 표시됨) private Font Warn_Font; //기타설정' public RectangleF WindowRect; //머릿부분 public RectangleF ChartRect; public TrendCtrlII() { InitializeComponent(); // Initialize Variables // 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); this.Font = SystemInformation.MenuFont; this.Warn_Font = new Font("나눔고딕", 20, FontStyle.Bold); this.Warn_msg.Append("메세지가 없습니다"); this.Mouseinfo = new CMouseinfo(new PointF(0, 0)); } public ChartStyle Style { get { return this._Style; } set { this._Style = value; } } /// /// Draws the background gradient and the grid into Graphics /// /// Graphic public void DrawBackgroundWindow(Graphics g,RectangleF crect,RectangleF winrect) { //using (Brush gradientBrush = new LinearGradientBrush(this.WindowRect, Style.design_backcolor_start, Style.design_backcolor_bottom, LinearGradientMode.Vertical)) //{ // g.FillRectangle(gradientBrush, this.WindowRect); //} //g.FillRectangle(Brushes.Black, this.WindowRect); //전체창에대한 보더 RectangleF borderrect = new RectangleF(winrect.Left, winrect.Top, winrect.Width - 1, winrect.Height - 1); g.DrawRectangle(Pens.Gray, borderrect.Left, borderrect.Top, borderrect.Width, borderrect.Height); //실제차트정보 //g.FillRectangle(Brushes.Gray, ChartRect.Left + 2, ChartRect.Top + 2, ChartRect.Width, ChartRect.Height); //g.FillRectangle(Brushes.Black, ChartRect); //Display Collection TIME //String Str = "Collection Time : " + GetDateTimeStr(startview, false) + " - " + GetDateTimeStr(endview, false); //SizeF fontszie = g.MeasureString(Str, this.Font); //// Rectangle rect = new Rectangle((int)winrect.Left, (int)winrect.Top, (int)winrect.Width, (int)(fontszie.Height * 2)); // g.DrawString(Str, this.Font, Brushes.Black, rect.Left + 10, 3+rect.Top + (rect.Height - fontszie.Height) / 2); // //g.DrawLine(Pens.Black, winrect.Left, fontszie.Height * 2, winrect.Left + winrect.Width, fontszie.Height * 2); //CHART BORDER g.DrawRectangle(new Pen(Color.Black, 2), crect.Left, crect.Top, crect.Width, crect.Height); } /// Override OnPaint method protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); this.SuspendLayout(); //Buttons.Clear(); //Buttonstag.Clear(); //Buttonstype.Clear(); //윈도우크기와 차트영역을 활성화한다. //표시아이템이없다면 오류를 낸다. if ( !init || chinfo == null) { //progress int bw = (int)(this.Width * 0.8); int bh = (int)(this.Height * 0.05); Rectangle rr = new Rectangle((this.Width - bw) / 2, (this.Height - bh) / 2 + 10, bw, bh); //Display Initial Message Font nf = new Font("나눔고딕", 20, FontStyle.Bold); Rectangle FullRect = new Rectangle(0, 0, this.Width, this.Height); SizeF initsize = e.Graphics.MeasureString(initmsg, nf); e.Graphics.DrawString(initmsg, nf, Brushes.Black, this.Width / 2 - initsize.Width / 2, this.Height / 2 - initsize.Height / 2 - bh); //Display progress Bar if (initpercent > 100) initpercent = 100; int perc = (int)(rr.Width * initpercent / 100); e.Graphics.FillRectangle(Brushes.Green, new Rectangle(rr.Left, rr.Top, perc, rr.Height)); //Display Control Border e.Graphics.DrawRectangle(Pens.DarkGray, rr); //using (Brush gradientBrush = new LinearGradientBrush(FullRect, Color.Gray, Color.Gray, LinearGradientMode.Vertical)) //{ // // e.Graphics.FillRectangle(gradientBrush, FullRect); // // String initstr = "initializing..."; // //if (initmsg != "") initstr += "\n\n" + initmsg; //} //LinearGradientBrush lb = new LinearGradientBrush(rr, Color.Gray, Color.WhiteSmoke,LinearGradientMode.Vertical); //lb.Dispose(); //e.Graphics.DrawRectangle(Pens.DarkGoldenrod, FullRect.Left, FullRect.Top, FullRect.Width - 1, FullRect.Height - 1); this.ResumeLayout(); return; } // AntiAliasing e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; //e.Graphics.DrawString(this.chinfo.Length.ToString(), this.Font, Brushes.Red, 200, 200); try { DrawBackgroundWindow(e.Graphics, ChartRect, WindowRect); } //전체배경및 차트배경 } catch { } try { Draw_Grid(e.Graphics, ChartRect); //x축,y축의 눈금과 그리드표시 } catch { } //Draw_NaviLR(e.Graphics, ChartRect); try { Draw_channel(e.Graphics, ChartRect, WindowRect); } catch { } try { Draw_ZoomSelct(e.Graphics); } catch { } try { Draw_Cursor(e.Graphics, ChartRect); } catch { } try { Draw_MouseInfo(e.Graphics); } catch { Draw_Debug(e.Graphics); } this.Update(); this.ResumeLayout(); } public void Draw_Cursor(Graphics g,RectangleF Crect ) { if (this.uc.Count == 0) return; Font cfont = new Font("나눔고딕", 10, FontStyle.Bold); //커서는 기본 2개를 둔다(전체사이즈를 측정하기위해서 임시로 크기를 테스트한다.) String cursorstr = "▦ C1 2012-00-00- 00:00:00\n▦ C1 2012-00-00- 00:00:00\n▦ C1 2012-00-00- 00:00:00"; SizeF FontSize = g.MeasureString(cursorstr.ToString(), cfont); //커서가표시될영역 Cursorrect = new Rectangle(0, 0, 50,50); Cursorrect.X = (int)(Crect.Left + Crect.Width - FontSize.Width * 1.1) - 1; Cursorrect.Y = (int)Crect.Top + 2; Cursorrect.Width = (int)(FontSize.Width * 1.1); Cursorrect.Height = (int)(FontSize.Height * 1.3); g.FillRectangle(Brushes.Black, Cursorrect); g.DrawRectangle(Pens.Gray, Cursorrect); Single newy = Cursorrect.Top + ((Cursorrect.Height - FontSize.Height)/2) ; Single Maxwidth = 0; String fulltext = ""; foreach (CUserCursor uctl in this.uc) { Single newx = GetXfromTime(uctl.Time, Crect); uctl.Newx = newx; Single imgsizew = Properties.Resources.down_16.Width; Single imgsizeh = Properties.Resources.down_16.Height; cursorstr = ("▦ C" + (uctl.Idx + 1).ToString() + " " + GetTimeStr((int)uctl.Time, true, true, true, true)); // cursorstr += uctl.Newx.ToString(); FontSize = g.MeasureString(cursorstr.ToString(), cfont); if (FontSize.Width > Maxwidth) Maxwidth = FontSize.Width; if (uctl.Idx < 1) { g.DrawImage(Properties.Resources.down_16, (newx - imgsizew / 2)-1, Crect.Top - imgsizeh - 5); //g.DrawLine(new Pen(Color.Gray, 2), newx+1, Crect.Top, newx+1, Crect.Top + Crect.Height); g.DrawLine(new Pen(Color.Green, 1), newx, Crect.Top, newx, Crect.Top + Crect.Height); // g.DrawString(newx.ToString() + "," + uctl.Time.ToString(), this.Font, Brushes.Red, newx, 300); g.DrawString(cursorstr, cfont, Brushes.Lime, Cursorrect.Left + ((Cursorrect.Width - FontSize.Width) / 2), newy); fulltext = cursorstr; } else { cursorstr += "\n\t△t " + GetTimeStr((int)Math.Abs(uctl.Time - uc[0].Time), false, true, true, false); g.DrawImage(Properties.Resources.down_orange, (newx - imgsizew / 2) - 1, Crect.Top - imgsizeh - 5); //g.DrawLine(new Pen(Color.Gray, 2), newx + 1, Crect.Top, newx + 1, Crect.Top + Crect.Height); g.DrawLine(new Pen(Color.Orange, 1), newx, Crect.Top, newx, Crect.Top + Crect.Height); // g.DrawString(newx.ToString() + "," + uctl.Time.ToString(), this.Font, Brushes.Red, newx, 300); g.DrawString(cursorstr, cfont, Brushes.Orange, Cursorrect.Left + ((Cursorrect.Width - FontSize.Width) / 2), newy); if (fulltext == "") fulltext = cursorstr; else fulltext += "\n" + cursorstr; } newy += FontSize.Height + 1; } FontSize = g.MeasureString(fulltext, cfont); Cursorrect = new Rectangle((int)(ChartRect.Left + ChartRect.Width - Maxwidth), (int)ChartRect.Top, (int)Maxwidth, (int)(newy - FontSize.Height)); } public void Draw_MouseInfo(Graphics g) { if (this.Mouseinfo.Showinfo) //마웃위치정보를 화면에 표시를 한다. { String tm = GetTimeStr((int)Mouseinfo.Time, true, true,true,true) + "\n" + Mouseinfo.Volt.ToString("#0.00") + "v"; if (Style.디버그메세지) tm += "\n" + Mouseinfo.Time.ToString(); SizeF tmsize = g.MeasureString(tm,Style._mouseinfofont); RectangleF rect = new RectangleF(Mouseinfo.Position.X + 5, Mouseinfo.Position.Y + 5, tmsize.Width+10, tmsize.Height+10); //g.FillRectangle(new SolidBrush(Color.FromArgb(140,Color.Green)), rect); g.DrawRectangle(Pens.Black, rect.Left, rect.Top, rect.Width, rect.Height); g.DrawString(tm, Style._mouseinfofont, new SolidBrush(Style.design_mouseinfocolor ), rect.Left + (rect.Width - tmsize.Width) / 2, rect.Top + (rect.Height - tmsize.Height) / 2); } } public void Draw_Grid(Graphics g,RectangleF crect) { //가로(시간축)표시 //DrawString(g, GetDateTimeStr(endview, true), Style._xfont, Brushes.Black, new PointF(crect.Left + crect.Width, crect.Top + crect.Height + 5), EALIGN.CENTER); DateTime SDate = DateTime.FromFileTime(startview); DateTime EDate = DateTime.FromFileTime(endview); TimeSpan TS = EDate - SDate; //timespan //표시간견(10등분) UInt32 tm = (UInt32)(TS.TotalSeconds / 10); for (DateTime SD = SDate; SD <= EDate; SD.AddSeconds(tm) ) { } for (Int64 i = 0; i <= (endview - startview); i += tm) { Int64 NewDateNumber = startview + i; DateTime NewDate = DateTime.FromFileTime(NewDateNumber); if (SDate.Day != NewDate.Day) { //일자가 바귀엇으므로 해당 일즤 세로축을 표시 DateTime LineDay = DateTime.Parse(NewDate.ToString("yyyy-MM-dd 00:00:00")); Single newx2 = GetXfromTime(LineDay.ToFileTime(), crect); g.DrawLine(new Pen(Color.FromArgb(50, Color.Black)), newx2, crect.Top, newx2, crect.Top + crect.Height); //Font newf = new Font("나눔고딕", 40, FontStyle.Bold); //DrawString(g, timestr2, newf, Brushes.Black, new PointF(newx2, ChartRect.Top + ChartRect.Height - 100), EALIGN.CENTER); SDate = NewDate; } Single newx = GetXfromTime(NewDateNumber, crect); String timestr = ""; if (i == 0) timestr = GetDateTimeStr(NewDateNumber, true); else timestr = GetTimeStr(NewDateNumber, i == 0 ? true : false, false); timestr = NewDate.ToString("yy-MM-dd") + "\n" + NewDate.ToString("HH:mm:ss"); // timestr += "\n" + disptime.ToString(); DrawString(g, timestr, Style._xfont, Brushes.Black, new PointF(newx, crect.Top + crect.Height + 5), EALIGN.CENTER); if (i > 0) g.DrawLine(new Pen(Color.Gray), newx, crect.Top, newx, crect.Top + crect.Height); } //세로(VOLT)표시 //g.DrawString("start="+Style._startvolt.ToString(), this.Font, Brushes.Red, 100, 100); //g.DrawString("end="+Style._endvolt.ToString(), this.Font, Brushes.Red, 100, 120); //g.DrawString("최소="+Style.최소값.ToString(), this.Font, Brushes.Red, 100, 140); //g.DrawString("최대="+Style.최대값.ToString(), this.Font, Brushes.Red, 100, 160); Single term = (Style._endvolt - Style._startvolt) / 10; for (Single i = Style._startvolt; i <= Style._endvolt; i += term) { // 세로길이 = 10v : Single newy = GetYfromVolt(i, crect); if (i != 0) g.DrawLine(new Pen(Color.Gray), crect.Left, newy, crect.Left + crect.Width, newy); //소수점없는경우에눈금표시한다. DrawString(g, i.ToString("#0.00"), Style._yfont, Brushes.Black, new PointF(crect.Left - 2, newy), EALIGN.RIGHT, EALIGN.CENTER); //int disptime = i + startview; //String timestr = GetTimeStr(disptime, i == 0 ? true : false); //DrawString(g, timestr, Style._xfont, Brushes.Orange, new PointF(newx, ChartRect.Top + ChartRect.Height), EALIGN.CENTER); //if (i > 0) g.DrawLine(new Pen(Color.FromArgb(100, Color.Red)), newx, ChartRect.Top, newx, ChartRect.Top + ChartRect.Height); } } public void Draw_Debug(Graphics g) { if (!Style.디버그메세지) return; Single newy = 50; String newstr = ""; SizeF fontsize; newstr = "Mouseinfo=" + this.Mouseinfo.Position.ToString() + " " + this.Mouseinfo.Showinfo.ToString() ; fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height; g.DrawString(newstr, this.Font, Brushes.Red, 100, newy); newstr = "Mouseinfo0=" + this.Mouseinfo.Position0.ToString()+ " idx=" + this.Mouseinfo.DragIndex.ToString(); fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height; g.DrawString(newstr, this.Font, Brushes.Red, 100, newy); if (uc.Count > 0) { newstr = "uc1=" + uc[0].Newx.ToString() + "," + uc[0].Time.ToString(); fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height; g.DrawString(newstr, this.Font, Brushes.Red, 100, newy); } if (uc.Count > 1) { newstr = "uc2=" + uc[1].Newx.ToString() + "," + uc[1].Time.ToString(); fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height; g.DrawString(newstr, this.Font, Brushes.Red, 100, newy); } newstr = "Time=" + starttime.ToString() + "/" + endtime.ToString(); fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height; g.DrawString(newstr, this.Font, Brushes.Red, 100, newy); newstr = "ViewTime=" + startview.ToString() + "/" + endview.ToString(); fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height; g.DrawString(newstr, this.Font, Brushes.Red, 100, newy); newstr = "ViewTimeO=" + startviewo.ToString() + "/" + endviewo.ToString(); fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height; g.DrawString(newstr, this.Font, Brushes.Red, 100, newy); newstr = "Drag=" + Mouseinfo.Drag.ToString() + " " + Mouseinfo.DragType.ToString(); fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height; g.DrawString(newstr, this.Font, Brushes.Red, 100, newy); newstr = "DragStart=" + Mouseinfo.DragStart.ToString(); fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height; g.DrawString(newstr, this.Font, Brushes.Red, 100, newy); newstr = "UserZoom=" + UserZoom.ToString(); fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height; g.DrawString(newstr, this.Font, Brushes.Red, 100, newy); newy += fontsize.Height; newstr = "CHinfo=" + chinfo.GetUpperBound(0); for (int i =0;i<= chinfo.GetUpperBound(0);i++) { newstr += "\n" + i.ToString() + "," + this.chinfo[i].idx + ",visible:" + chinfo[i].Show.ToString(); } fontsize = g.MeasureString(newstr, this.Font); g.DrawString(newstr, this.Font, Brushes.Red, 100, newy); newy += fontsize.Height; } public void Draw_channel(Graphics g,RectangleF crect,RectangleF wrect) { //각채널의 그래프를 그린다. foreach (CChinfo c in chinfo) { if (c == null) continue; if (!c.Show) continue; if (c.Value.Count < 1) continue; List linearrya = new List(0); Single PreX = 0; Single PreY = 0; Boolean fc1 = false, fc2 = false; for (int i = 0; i < c.Value.Count; i++) //가능한 셀값을 모두 확인한다. { Single time = c.Time[i]; //이셀의 시간 Single volt = c.Value[i]; //이셀의 볼트 //if (volt == 0) continue; Single newx = GetXfromTime(time, crect) - 1; Single newy = GetYfromVolt(volt, crect) - 1; //너무가까운데이터는 그리지 않는다. if (Math.Abs(newx - PreX) < 0.2 || Math.Abs(newy - PreY) < 0.2) continue; if (!c.Show) { c.C1value = "--"; c.C2value = "--"; } else if (uc.Count > 0 && time >= uc[0].Time && fc1 == false) //셀의시간이 커서의시간을 넘는 순간의 값을 저장 { //g.DrawString(uc[0].Time.ToString() + "," + time.ToString() + " volt=" + volt.ToString(), this.Font, Brushes.Red, 200, 200); if (volt > 60) c.C1value = "OVER"; else c.C1value = volt.ToString(); fc1 = true; } if (uc.Count > 1 && time >= uc[1].Time && fc2 == false) { //g.DrawString(uc[1].Time.ToString() + "," + time.ToString() + " volt=" + volt.ToString(), this.Font, Brushes.Red, 200, 300); if (volt > 60) c.C2value = "OVER"; else c.C2value = volt.ToString(); fc2 = true; } // e.Graphics.DrawString(time.ToString() + " v=" + volt.ToString(), this.Font, Brushes.Black, newx, newy); if (newx >= wrect.Left && newx <= wrect.Left + wrect.Width && newy >= wrect.Top && newy <= wrect.Top + wrect.Height) linearrya.Add(new PointF(newx, newy)); g.FillEllipse(new SolidBrush(c.color), new RectangleF(newx-1, newy-1, 2, 2)); } try { g.DrawLines(new Pen(c.color, LineWidth), linearrya.ToArray()); } catch { } } } public void Draw_ZoomSelct(Graphics g) { //사용자줌영역표시 if (this.UserZoom.Width != 0) { int x, y, w, h; if (UserZoom.Width > 0) { x = UserZoom.Left; w = UserZoom.Width; } else { x = UserZoom.Width + UserZoom.Left; w = Math.Abs(UserZoom.Width); } if (UserZoom.Height > 0) { y = UserZoom.Top; h = UserZoom.Height; } else { y = UserZoom.Height + UserZoom.Top; h = Math.Abs(UserZoom.Height); } Rectangle rect = new Rectangle(x, y, w, h); int startx = (int)Math.Round(GetTimeFromX(rect.Left - this.ChartRect.Left, ChartRect), 1); int endx = (int)Math.Round(GetTimeFromX(rect.Left + rect.Width - ChartRect.Left, ChartRect), 1); Single starty =(Single)(Math.Round(GetVoltfromY(rect.Top - this.ChartRect.Top, ChartRect), 1)); Single endy = (Single)Math.Round(GetVoltfromY(rect.Top + rect.Height - ChartRect.Top, ChartRect), 1); //선택된 영역 Drawing if (endx - startx >= 5) g.FillRectangle(new SolidBrush(Color.FromArgb(150, Color.Lime)), rect); else g.FillRectangle(new SolidBrush(Color.FromArgb(150, Color.Red)), rect); g.DrawRectangle(Pens.Black, rect); //시간정보 Display g.DrawString(GetTimeStr(startx + starttime, true,true) + "," + (Style.최대값 - starty).ToString("#0.0") + "v" , this.Font, Brushes.Black, rect.Left, rect.Top); String fontstr = GetTimeStr(endx + starttime, true, true) + "," + (Style.최대값 - endy).ToString("#0.0") + "v"; SizeF fontsize = g.MeasureString(fontstr, this.Font); g.DrawString(fontstr, this.Font, Brushes.Black, rect.Left - 5 + rect.Width - fontsize.Width, rect.Top + rect.Height - fontsize.Height); } } /// /// 화면의 좌,우 측에 존재하는 이돈버튼(월을 움직이는 버튼이며 월 이동을위해서 이벤트를 발생한다) /// /// //public void Draw_NaviLR(Graphics G, RectangleF crect) //{ // return; // //LEFT NAVI // Single x, y, xw = 30; // x = crect.Left - 3; // y = crect.Top + crect.Height / 2 - xw / 2; // PointF[] aa = new PointF[4]; // aa[0] = new PointF(x, y); // aa[1] = new PointF(x - xw, y + xw); // aa[2] = new PointF(x, y + xw + xw); // aa[3] = new PointF(x, y); // PointF[] aa1 = new PointF[4]; // aa1[0] = new PointF(x + 2, y + 2); // aa1[1] = new PointF(x + 2 - xw, y + xw + 2); // aa1[2] = new PointF(x + 2, y + xw + xw + 2); // aa1[3] = new PointF(x + 2, y + 2); // G.FillPolygon(Brushes.Black, aa1); // G.FillPolygon(Brushes.DarkRed, aa); // G.DrawPolygon(Pens.Black, aa); // Buttons.Add(new RectangleF(x - xw, y, xw, xw*2)); // Buttonstag.Add("LBUTTON"); // Buttonstype.Add(EBUTTONTYPE.LEFTMON); // //RIGHT NAVI // x = crect.Left + crect.Width + 3; // y = crect.Top + crect.Height / 2 - xw / 2; // aa = new PointF[4]; // aa[0] = new PointF(x, y); // aa[1] = new PointF(x + xw, y + xw); // aa[2] = new PointF(x, y + xw + xw); // aa[3] = new PointF(x, y); // aa1 = new PointF[4]; // aa1[0] = new PointF(x + 2, y + 2); // aa1[1] = new PointF(x + 2 + xw, y + xw + 2); // aa1[2] = new PointF(x + 2, y + xw + xw + 2); // aa1[3] = new PointF(x + 2, y + 2); // G.FillPolygon(Brushes.Black, aa1); // G.FillPolygon(Brushes.DarkRed, aa); // G.DrawPolygon(Pens.Black, aa); // Buttons.Add(new RectangleF(x, y, xw, xw*2)); // Buttonstag.Add("RBUTTON"); // Buttonstype.Add(EBUTTONTYPE.RIGHTMON); //} public String GetDateTimeStr(Int64 Filetime, Boolean linefeed) { DateTime TimeDate = DateTime.FromFileTime(Filetime); String timestr = ""; if (linefeed) timestr = TimeDate.ToShortDateString() + "\n" + TimeDate.ToShortTimeString(); //' yymm + "-" + day.ToString("00") + "\n" + hour.ToString("00") + ":" + min.ToString("00") + ":" + sec.ToString("00"); else timestr = TimeDate.ToString();// yymm + "-" + day.ToString("00") + " " + hour.ToString("00") + ":" + min.ToString("00") + ":" + sec.ToString("00"); return timestr; } public String GetTimeStr(Int64 Filetime, Boolean withday, Boolean withseconed, Boolean nolf = false, Boolean showyear = false) { DateTime TimeDate = DateTime.FromFileTime(Filetime); String timestr = ""; if (TimeDate.Second == 0 || !withseconed) timestr = TimeDate.ToString("HH:mm");// TimeDate.Hour.ToString("00") + ":" + TimeDate.Minute.ToString("00"); else timestr = TimeDate.ToString("HH:mm:ss"); // hour.ToString("00") + ":" + min.ToString("00") + ":" + sec.ToString("00"); if (withday) { if (showyear) { timestr = TimeDate.ToString("yyMM-dd") + " " + timestr; } else { if (nolf) timestr = TimeDate.ToString("dd") + "일 " + timestr; else timestr = timestr + "\n" + TimeDate.ToString("dd") + "일"; } } return timestr; } /// /// (전체시간 * 현재X) / 전체너비 /// /// /// private Single GetTimeFromX(Single t, RectangleF crect) { return ((endview - startview) * t) / crect.Width; } private Single GetXfromTime(Single t,RectangleF crect) { return (((crect.Width) * (t - startview)) / (endview - startview)) + crect.Left; } private Single GetVoltfromY(Single Y, RectangleF crect) { return ((Style._endvolt - Style._startvolt) * Y) / crect.Height; } private Single GetYfromVolt(Single volt, RectangleF crect) { //volt = (Style._endvolt - Style._startvolt) - volt; return (crect.Height - ((crect.Height * (volt - Style._startvolt)) / (Style._endvolt - Style._startvolt))) + crect.Top; //return (((crect.Height) * volt) / (Style.최대값)) + crect.Top; } private void DrawString(Graphics G, String str, Font font, Brush br, PointF ops, EALIGN XCenter = EALIGN.LEFT, EALIGN YCenter = EALIGN.LEFT) { SizeF fsize = G.MeasureString(str, font); Single newx = ops.X; Single newy = ops.Y; if (XCenter == EALIGN.CENTER) newx = ops.X - fsize.Width / 2; else if (XCenter == EALIGN.RIGHT) newx = ops.X - fsize.Width; if (YCenter == EALIGN.CENTER) newy = ops.Y - fsize.Height / 2; else if (YCenter == EALIGN.RIGHT) newy = ops.Y - fsize.Height; G.DrawString(str, font, br, newx, newy); } public Int64 Starttime { get { return this.starttime; } set { this.starttime = value; startview = value; } } public Int64 Endtime { get { return this.endtime; } set { this.endtime = value; endview = value; } } public Int64 Startview { get { return this.startview; } set { this.startview = value; } } public Int64 Endview { get { return this.endview; } set { this.endview = value; } } public Boolean INIT { get { return this.init; } set { this.init = value; } } public CChinfo[] CHInfo { get { return this.chinfo; } set { this.chinfo = value; } } protected override void OnResize(EventArgs e) { base.OnResize(e); this.WindowRect = new RectangleF(0, 0, this.Width, this.Height); this.ChartRect = new RectangleF(Style.왼쪽여백, (Style.위쪽여백/2), this.Width - (Style.왼쪽여백 * 2), (Single)(this.Height - (Style.위쪽여백 * 1.5))); Invalidate(); } private int check_userpoint(MouseEventArgs e) { if (this.uc.Count ==0 ) return -1; for (int i = 0; i < this.uc.Count; i++) { CUserCursor uuc = this.uc[i]; //현재위치가 해당 Rectagle 안이라면 속해있다. if ((int)this.Mouseinfo.Position.X >= (int)uuc.Newx - 2 && (int)this.Mouseinfo.Position.X <= (int)(uuc.Newx) + 2) // MessageBox.Show(i.ToString()); return i; } return -1; } //private int check_buttons(MouseEventArgs e) //{ // if (this.Buttons == null) return -1; // for (int i = 0; i < this.Buttons.Count; i++) // { // RectangleF rect = this.Buttons[i]; // //현재위치가 해당 Rectagle 안이라면 속해있다. // if (e.X > rect.X && e.X < rect.X + rect.Width) // { // if (e.Y > rect.Y && e.Y < rect.Y + rect.Height) return i; // } // } // return -1; //} private void InitializeComponent() { this.SuspendLayout(); // // TrendCtrl // this.Name = "TrendCtrl"; this.Size = new System.Drawing.Size(287, 321); this.Load += new System.EventHandler(this.DispCtrl_Load); this.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.TrendCtrl_MouseDoubleClick); this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.DispCtrl_MouseDown); this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.DispCtrl_MouseMove); this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.TrendCtrl_MouseUp); this.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.TrendCtrl_MouseWhell); this.ResumeLayout(false); } private void DispCtrl_MouseDown(object sender, MouseEventArgs e) { //드래그판단을위한 위치값을 저장한다. Mouseinfo.DragStart = new PointF(e.X - ChartRect.Left, e.Y - ChartRect.Top); //우측버튼은 줌의 초기화를 수행한다. if (e.Button == System.Windows.Forms.MouseButtons.Right) { //startview = starttime; //endview = endtime; //Style._startvolt = Style.최소값; //Style._endvolt = Style.최대값; //Refresh(); //return; } else if (e.Button == System.Windows.Forms.MouseButtons.Left) { //현재마우스위치의 아이템을 찾ㄴ은다. //int idx = check_buttons(e); //if (idx != -1) //{ // Object tt = this.Buttonstag[idx]; // EBUTTONTYPE BT = this.Buttonstype[idx]; // switch (BT) // { // case EBUTTONTYPE.LEFTMON: // OnClickLEFT(); // break; // case EBUTTONTYPE.RIGHTMON: // OnClickRIGHT(); // break; // } //} int idx = check_userpoint(e); if (idx != -1) { Mouseinfo.DragType = EDRAGTYPE.UC; Mouseinfo.DragIndex = idx; return; } //아무것도없는 빈공간이라면 화면이동(=줌시작)으로 대체한다. //if (idx == -1 && e.X >= ChartRect.Left && e.X <= ChartRect.Left + ChartRect.Width && e.Y >= ChartRect.Top && e.Y <= ChartRect.Top + ChartRect.Height) //{ // if (endview - startview == (endtime - starttime)) // { // Mouseinfo.DragType = EDRAGTYPE.ZOOM; // this.UserZoom = new Rectangle(e.X, e.Y, 0, 0); // } // else // { // Mouseinfo.DragType = EDRAGTYPE.SCREEN; // this.UserZoom = new Rectangle(0, 0, 0, 0); // } // return; //} } } private void DispCtrl_MouseMove(object sender, MouseEventArgs e) { //마우스의 위치가 실시간 저장된다. if (this.Mouseinfo == null) this.Mouseinfo = new CMouseinfo(new PointF(e.X - this.WindowRect.Left, e.Y - this.WindowRect.Top)); else this.Mouseinfo.Position = new PointF(e.X - this.WindowRect.Left, e.Y - this.WindowRect.Top); this.Mouseinfo.Time = GetTimeFromX(e.X - ChartRect.Left,ChartRect)+ this.startview; this.Mouseinfo.Volt = this._Style._endvolt - GetVoltfromY(e.Y - ChartRect.Top, ChartRect) ; this.Mouseinfo.Showinfo = false; //MouseStatus initialize... Mouseinfo.Hand = false; Mouseinfo.Cross = false; Mouseinfo.Move = false; Mouseinfo.ChangePos = false; // if (e.X >= ChartRect.X && e.X <= ChartRect.X + ChartRect.Width) if (e.Y >= ChartRect.Top && e.Y <= ChartRect.Top + ChartRect.Height) Mouseinfo.Showinfo = true; else Mouseinfo.Showinfo = false; //이동중인데 마우스가 눌려있다면 DRAG다 if (e.Button == MouseButtons.Left) Mouseinfo.Drag = true; else Mouseinfo.Drag = false; if (Mouseinfo.Drag) //드래그중이다 { Mouseinfo.Move = true; //화면이동으로 } else { if (e.X >= ChartRect.Left && e.X <= ChartRect.Left + ChartRect.Width) { if (e.Y >= ChartRect.Top && e.Y <= ChartRect.Top + ChartRect.Height) { Mouseinfo.Cross = true; //화면내부라면 크로스 } else Mouseinfo.Cross = false; } else Mouseinfo.Cross = false; } //버튼위라면 HAND를 활성화한다. //int idx = this.check_buttons(e); //if (idx != -1) //{ // Mouseinfo.Cross = false; // Mouseinfo.Hand = true; // Mouseinfo.Drag = false; // Mouseinfo.ChangePos = false; //} //사용자포인터위라면? int idx = this.check_userpoint(e); if (idx != -1) { Mouseinfo.Cross = false; Mouseinfo.Hand = false; Mouseinfo.Drag = false; Mouseinfo.ChangePos = true; } //드래그중판단 if (Mouseinfo.Drag) { switch (Mouseinfo.DragType) { case EDRAGTYPE.UC: Single newx = ( e.X); float newtime = GetTimeFromX(newx - ChartRect.Left, ChartRect) + startview; this.uc[Mouseinfo.DragIndex].Newx = newx; this.uc[Mouseinfo.DragIndex].Time = newtime; //OnUpdateUserCursor(Mouseinfo.DragIndex); break; case EDRAGTYPE.ZOOM: this.UserZoom.Width = (int)(e.X - Mouseinfo.DragStart.X - ChartRect.Left); this.UserZoom.Height = (int)(e.Y - Mouseinfo.DragStart.Y - ChartRect.Left); if (Mouseinfo.Cross) this.Cursor = Cursors.Cross; break; case EDRAGTYPE.SCREEN: if (Mouseinfo.Move) { this.Cursor = Cursors.NoMove2D; Mouseinfo.Showinfo = false; } //이동한pixcel을 시간정보로 변환한다. //현재마우스위치값 - 드래그시작마우스위치값을 뺸 픽셀을 초로환산한다. Single term = Mouseinfo.DragStart.X-Mouseinfo.Position.X; //양수라면 오른쪽으로 이동했다. Single termtime = GetTimeFromX(term, ChartRect); Single termy = Mouseinfo.Position.Y- Mouseinfo.DragStart.Y- ChartRect.Top ; Single termvolt = GetVoltfromY(termy, ChartRect); Single mstime = termtime ; //((endview - startview) / 50); Single mvolt = termvolt; //if (Mouseinfo.Position.X < Mouseinfo.Position0.X) //{ // mstime = -1 * mstime; //} Int64 SD = startviewo + (int)mstime; Int64 ED = endviewo + (int)mstime; Single SV = Style._startvolto + mvolt; Single EV = Style._endvolto + mvolt; if ((SD < starttime || ED > endtime)) { //더이상 줌을 못한다.. } else { startview = SD; endview = ED; Style._startvolt = SV; Style._endvolt = EV; //startviewo = startview; //endviewo = endview; } break; } } else { if (Mouseinfo.Hand) this.Cursor = Cursors.Hand; if (Mouseinfo.Cross) this.Cursor = Cursors.Cross; if (Mouseinfo.ChangePos) this.Cursor = Cursors.SizeWE; } this.Refresh(); } private void TrendCtrl_MouseWhell(object sender, MouseEventArgs e) { //MessageBox.Show(e.Delta.ToString()); //int news = 0, newe = 0; //news = startview; //newe = endview; //if (e.Delta > 0) //{ // //up // news += (endview-startview)/10; // newe -= (endview - startview) / 10; //} //else //{ // //down // news -= (endview - startview) / 10; // newe += (endview - startview) / 10; //} //if (news > endtime) news = endtime; //if (news < starttime) news = starttime; //if (newe > endtime) newe = endtime; //if (newe < starttime) newe = starttime; //if (news < starttime || newe > endtime) //{ // //MessageBox.Show("데이터가 없으므로 줌을 사용할 수 없습니다"); //} //else //{ // startview = news; // endview = newe; // startviewo = news; // endviewo = newe; //} //this.Refresh(); } private void TrendCtrl_MouseUp(object sender, MouseEventArgs e) { if (Mouseinfo.Drag && Mouseinfo.DragType == EDRAGTYPE.UC) { ////만약 화면 박을 넘어서면 삭제한다. //if (uc[Mouseinfo.DragIndex].Newx <= ChartRect.Left || uc[Mouseinfo.DragIndex].Newx >= ChartRect.Left + ChartRect.Width) //{ // uc.Remove(uc[Mouseinfo.DragIndex]); // if (uc.Count == 1) // { // uc[0].Idx = 0; // foreach (CChinfo c in this.chinfo) // { // c.C2value = ""; // } // } //} this.Refresh(); OnUpdateUserCursor(Mouseinfo.DragIndex); } //startviewo = startview; //endviewo = endview; //Style._startvolto = Style._startvolt; //Style._endvolto = Style._endvolt; //Mouseinfo.Drag = false; //if (UserZoom.Width != 0) //줌영역이 있다면 줌을 활성화한다. //{ // int x1, x2,y1,y2; // x1 = UserZoom.Left; // x2 = UserZoom.Left + UserZoom.Width; // y1 = UserZoom.Top; // y2 = UserZoom.Top + UserZoom.Height; // int startx = (int)Math.Round(GetTimeFromX(x1 - ChartRect.Left, ChartRect), 0); // int endx = (int)Math.Round(GetTimeFromX(x2 - ChartRect.Left, ChartRect), 0); // Single starty =(Single) Math.Round(GetVoltfromY(y1 - ChartRect.Top, ChartRect), 1); // Single endy = (Single)Math.Round(GetVoltfromY(y2 - ChartRect.Top, ChartRect), 1); // if (endx < startx) //교환 // { // int t = startx; // startx = endx; // endx = t; // } // //if (endy < starty) //교환 // //{ // // Single t = starty; // // starty = endy; // // endy = t; // //} // if (endx - startx >= 10) //보기영역이 5초는 넘어야 줌이 가능한다. // { // this.startview = startx + this.starttime ; // this.endview = endx + this.starttime; // this.startviewo = this.startview; // this.endviewo = this.endview; // if (starty < endy) // { // this.Style._endvolt = Style.최대값 - starty;// +this.Style.최소값; // this.Style._startvolt = Style.최대값 - endy;// +this.Style.최대값; // } // else // { // this.Style._startvolt = Style.최대값 - starty;// +this.Style.최소값; // this.Style._endvolt = Style.최대값 - endy;// +this.Style.최대값; // } // //////////// // this.Style._startvolto = this.Style._startvolt; // this.Style._endvolto = this.Style._endvolt; // ////////////// // UserZoom.Width = 0; // this.Refresh(); // } // else // { // UserZoom.Width = 0; // this.Refresh(); // } //} } private void TrendCtrl_MouseDoubleClick(object sender, MouseEventArgs e) { //마우스더블클릭 int idx = check_userpoint(e); if (idx != -1) { //삭제한다. uc.Remove(uc[Mouseinfo.DragIndex]); if (uc.Count == 1) { uc[0].Idx = 0; foreach (CChinfo c in this.chinfo) { c.C2value = ""; } } this.Refresh(); OnUpdateUserCursor(Mouseinfo.DragIndex); return; } if (e.Button == System.Windows.Forms.MouseButtons.Left) { if (this.uc.Count < 2) { Single newx = GetXfromTime(Mouseinfo.Time, ChartRect); this.uc.Add(new CUserCursor((short)this.uc.Count, Mouseinfo.Time, newx)); this.Refresh(); OnUpdateUserCursor(this.uc.Count); } } } private void DispCtrl_Load(object sender, EventArgs e) { } } //end class } //end namespace