2004 lines
		
	
	
		
			79 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			2004 lines
		
	
	
		
			79 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| 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;
 | |
| using System.Linq;
 | |
| using System.Security.Authentication.ExtendedProtection;
 | |
| using System.Security.Policy;
 | |
| using static System.Net.Mime.MediaTypeNames;
 | |
| using System.Data.SqlTypes;
 | |
| using System.Windows.Media.Animation;
 | |
| 
 | |
| namespace TrendCtrlII
 | |
| {
 | |
|     public enum EDRAGTYPE
 | |
|     {
 | |
|         SCREEN,
 | |
|         ZOOM,
 | |
|         UC,
 | |
|         NONE
 | |
|     }
 | |
| 
 | |
|     public enum ESCREENMODE
 | |
|     {
 | |
|         INIT,
 | |
|         TEMPDATA,
 | |
|         GRAPH
 | |
|     }
 | |
| 
 | |
|     public enum EBUTTONTYPE
 | |
|     {
 | |
|         LEFTMON,
 | |
|         RIGHTMON
 | |
|     }
 | |
| 
 | |
|     public enum EALIGN
 | |
|     {
 | |
|         LEFT,
 | |
|         CENTER,
 | |
|         RIGHT
 | |
|     }
 | |
| 
 | |
|     public partial class TrendCtrlII : UserControl
 | |
|     {
 | |
| 
 | |
|         private BufferedGraphicsContext context;
 | |
|         private BufferedGraphics bufferedGraphics;
 | |
| 
 | |
| 
 | |
| 
 | |
|         private ChartStyle _Style = new ChartStyle();
 | |
|         public CMouseinfo Mouseinfo;    //마우스위치정보
 | |
| 
 | |
|         public Boolean Refresh_BackGround = true;
 | |
|         public Boolean Refresh_Grpah = true;
 | |
| 
 | |
|         //화면이동모드
 | |
|         public Boolean ScreenMove = false;
 | |
| 
 | |
|         //Boolean Make_BackT = false;
 | |
| 
 | |
|         Bitmap layer_bakT;  //전체영역의 배경
 | |
|         Bitmap layer_bak;
 | |
| 
 | |
|         Bitmap layer_graph;
 | |
|         Bitmap layer_graphT;    //전체영역의 그래프
 | |
| 
 | |
|         public float MaxValueY { get; set; } = 15;
 | |
| 
 | |
| 
 | |
| 
 | |
|         public Single LineWidth = 1;
 | |
|         private Rectangle UserZoom;     //사용자줌영역
 | |
| 
 | |
|         //실값
 | |
|         public Single[] values;
 | |
|         // public int[] times;
 | |
|         private CChinfo[] chinfo;
 | |
| 
 | |
|         public Boolean Key_Control = false;
 | |
| 
 | |
|         // private Rectangle Cursorrect;
 | |
| 
 | |
|         //2015-02-17 : 시간정보를 chinfo 에서 분리
 | |
|         public Dictionary<UInt32, Int64> Time;
 | |
| 
 | |
|         public void RemoveAt(int idx)
 | |
|         {
 | |
|             //배열갯수를 벗어나면 처리하지 않는다.
 | |
|             if (idx >= this.Time.Count) return;
 | |
| 
 | |
|             //삭제대상의 키를 확인한다.
 | |
|             var timeKey = this.Time.Take(idx).First().Key;
 | |
| 
 | |
|             //시간정보삭제
 | |
|             this.Time.Remove(timeKey);
 | |
| 
 | |
|             //채널정보 중 타임키를 공유하는 자료를 삭제한다.
 | |
|             this.chinfo.ToList().ForEach(t => t.Value.Remove(timeKey));
 | |
| 
 | |
|         }
 | |
| 
 | |
|         public void AddData(long val_time, int ch, float val_volt, string ch_grp, string ch_title, Color ch_color)
 | |
|         {
 | |
|             //존재하지 않는 시간이라면 추가한다.
 | |
|             var ttime = Time.Where(t => t.Value == val_time).FirstOrDefault();
 | |
|             if (ttime.Key is default(UInt32) && ttime.Value is default(Int64)) // 기존에 값이 존재하지 않는경우
 | |
|             {
 | |
|                 this.Time.Add((uint)this.Time.Count + 1, val_time);
 | |
|                 ttime = Time.Where(t => t.Value == val_time).FirstOrDefault();
 | |
|             }
 | |
| 
 | |
|             //해당 채널이 존재하는지 확인한다
 | |
|             var chdata = this.CHInfo.Where(t => t.CH == ch).FirstOrDefault();
 | |
|             if (chdata == null)
 | |
|             {
 | |
|                 Array.Resize(ref chinfo, chinfo.Length + 1);
 | |
|                 chdata = new CChinfo
 | |
|                 {
 | |
|                     CH = ch,
 | |
|                     Idx = (ushort)ch,
 | |
|                     GROUP = ch_grp,
 | |
|                     TITLE = ch_title,
 | |
|                     Color = ch_color,
 | |
|                     Show = true,
 | |
|                 };
 | |
|                 chinfo[chinfo.Length - 1] = chdata;
 | |
|             }
 | |
| 
 | |
|             //해당 시간대의 데이터가 없다면 추가한다.
 | |
|             if (chdata.Value.ContainsKey(ttime.Key) == false)
 | |
|                 chdata.Value.Add(ttime.Key, val_volt);
 | |
| 
 | |
|             RangeUpdateData = true;
 | |
|         }
 | |
| 
 | |
|         public void AddData(long val_time, int ch, float val_volt)
 | |
|         {
 | |
|             //존재하지 않는 시간이라면 추가한다.
 | |
|             var ttime = Time.Where(t => t.Value == val_time).FirstOrDefault();
 | |
|             if (ttime.Key is default(UInt32))
 | |
|             {
 | |
|                 this.Time.Add((uint)this.Time.Count + 1, val_time);
 | |
|             }
 | |
| 
 | |
|             //해당 채널이 존재하는지 확인한다
 | |
|             var chdata = this.CHInfo.Where(t => t.CH == ch).FirstOrDefault();
 | |
|             if (chdata != null)
 | |
|             {
 | |
|                 //해당 시간대의 데이터가 없다면 추가한다.
 | |
|                 if (chdata.Value.ContainsKey(ttime.Key) == false)
 | |
|                     chdata.Value.Add(ttime.Key, val_volt);
 | |
|             }
 | |
|             RangeUpdateData = true;
 | |
| 
 | |
|         }
 | |
| 
 | |
|         private Boolean init;    //그리드초기화완료여부
 | |
|         public String initmsg = "initializing...";
 | |
|         public int initpercent = 0;
 | |
| 
 | |
|         public List<CUserCursor> uc = new List<CUserCursor>(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;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 현재데이터중 가장 마지막의 시간정보를 반환합니다. (없는경우 1900년도가 반화노딤)
 | |
|         /// </summary>
 | |
|         /// <returns></returns>
 | |
|         public Int64 LastDate()
 | |
|         {
 | |
|             if (Time == null) return DateTime.Parse("1900-01-01").ToFileTime();
 | |
|             if (Time.Count < 1) return DateTime.Parse("1900-01-01").ToFileTime();
 | |
|             return Time.Last().Value;// [Time.Count - 1].Value;
 | |
|         }
 | |
| 
 | |
|         public Int64 FirstDate()
 | |
|         {
 | |
|             if (Time == null) return DateTime.Parse("1900-01-01").ToFileTime();
 | |
|             if (Time.Count < 1) return DateTime.Parse("1900-01-01").ToFileTime();
 | |
|             return Time.First().Value;
 | |
|         }
 | |
| 
 | |
|         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));
 | |
|             Time = new Dictionary<uint, long>();
 | |
| 
 | |
| 
 | |
|             // 더블 버퍼링을 위한 BufferedGraphicsContext 및 BufferedGraphics 초기화
 | |
|             this.context = BufferedGraphicsManager.Current;
 | |
|             bufferedGraphics = context.Allocate(this.CreateGraphics(), this.ClientRectangle);
 | |
|             bufferedGraphics.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
 | |
|         }
 | |
| 
 | |
| 
 | |
|         protected override void Dispose(bool disposing)
 | |
|         {
 | |
|             if (disposing)
 | |
|             {
 | |
|                 if (bufferedGraphics != null)
 | |
|                 {
 | |
|                     bufferedGraphics.Dispose();
 | |
|                 }
 | |
|             }
 | |
|             base.Dispose(disposing);
 | |
|         }
 | |
| 
 | |
|         public ChartStyle Style
 | |
|         {
 | |
|             get { return this._Style; }
 | |
|             set { this._Style = value; }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Draws the background gradient and the grid into Graphics <paramref name="g"/>
 | |
|         /// </summary>
 | |
|         /// <param name="g">Graphic</param>
 | |
|         public void DrawBackgroundWindow(Graphics g, RectangleF crect, RectangleF winrect)
 | |
|         {
 | |
|             //WINDOW BORDER
 | |
|             RectangleF borderrect = new RectangleF(winrect.Left, winrect.Top, winrect.Width - 2, winrect.Height - 2);
 | |
|             g.DrawRectangle(Pens.LightGray, borderrect.Left, borderrect.Top, borderrect.Width, borderrect.Height);
 | |
| 
 | |
|             //CHART BORDER
 | |
|             g.DrawRectangle(new Pen(Color.LightGray, 1), crect.Left, crect.Top, crect.Width, crect.Height);
 | |
| 
 | |
|         }
 | |
| 
 | |
|         public void Set_Refresh()
 | |
|         {
 | |
|             Console.WriteLine("Graph : Set_Refresh");
 | |
|             Refresh_BackGround = true;
 | |
|             Refresh_Grpah = true;
 | |
|         }
 | |
| 
 | |
|         void DrawScreen_Nodata_With_Message(Graphics g, string Message)
 | |
|         {
 | |
|             //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 = g.MeasureString(initmsg, nf);
 | |
|             g.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);
 | |
|             g.FillRectangle(Brushes.Green, new Rectangle(rr.Left, rr.Top, perc, rr.Height));
 | |
| 
 | |
|             //Display Control Border
 | |
|             g.DrawRectangle(Pens.DarkGray, rr);
 | |
|         }
 | |
|         void DrawScreen_Chart(Graphics g)
 | |
|         {
 | |
|             Graphics g_bak;
 | |
|             Graphics g_graph;
 | |
| 
 | |
|             //초기화전이다.
 | |
|             if (this.layer_bak == null && this.layer_bakT == null) return;
 | |
| 
 | |
|             if (Style.XV1 == Style.X1 && Style.XV2 == Style.X2)
 | |
|             {
 | |
|                 //전체영역이면(전체용 비트맵을 사용함)
 | |
|                 g_bak = Graphics.FromImage(this.layer_bakT);
 | |
|                 g_graph = Graphics.FromImage(this.layer_graphT);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 g_bak = Graphics.FromImage(this.layer_bak);
 | |
|                 g_graph = Graphics.FromImage(this.layer_graph);
 | |
|             }
 | |
| 
 | |
|             // g.CompositingMode = CompositingMode.SourceOver;
 | |
| 
 | |
|             if (Refresh_BackGround)
 | |
|             {
 | |
|                 // g_bak.CompositingMode = CompositingMode.SourceOver;
 | |
|                 g_bak.Clear(Color.White);
 | |
|                 DrawBackgroundWindow(g_bak, ChartRect, WindowRect);
 | |
|                 Draw_Grid(g_bak, ChartRect);  //x축,y축의 눈금과 그리드표시
 | |
|                 Refresh_BackGround = false;
 | |
|             }
 | |
| 
 | |
|             if (Refresh_Grpah)
 | |
|             {
 | |
|                 // g_graph.CompositingMode = CompositingMode.SourceOver;
 | |
|                 g_graph.Clear(Color.Transparent);
 | |
|                 Draw_channel(g_graph, ChartRect, WindowRect);
 | |
|                 Refresh_Grpah = false;
 | |
|             }
 | |
| 
 | |
|             g_bak.Dispose();
 | |
|             g_graph.Dispose();
 | |
| 
 | |
|             //전체영역의경우 별도 할당된 이미지를 사용한ㄷ(최초 1번만 그리게된다)
 | |
|             if (Style.XV1 == Style.X1 && Style.XV2 == Style.X2)
 | |
|             {
 | |
|                 g.DrawImage(layer_bakT, 0, 0);
 | |
|                 g.DrawImage(layer_graphT, 0, 0);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 g.DrawImage(layer_bak, 0, 0);
 | |
|                 g.DrawImage(layer_graph, 0, 0);
 | |
|             }
 | |
| 
 | |
| 
 | |
| 
 | |
|             //기타정보그림
 | |
|             Draw_ZoomSelect(g);
 | |
|             Draw_Cursor(g, ChartRect);
 | |
|             Draw_MouseInfo(g);
 | |
|             Draw_Debug(g);
 | |
|             if (ShowLegend) Draw_legend(g);
 | |
|             g_bak.Dispose();
 | |
|             g_graph.Dispose();
 | |
| 
 | |
|             //그리드는 미리 그려넣는다.
 | |
|             //축범위 시작시간 : max(데이터영역,보이는영역)
 | |
|             //축범위 종료시간 : min(데이터영역,보이는영역)
 | |
|             //g.Clear(this.BackColor);
 | |
| 
 | |
|             var times = DateTime.FromFileTime(Style.X1);
 | |
|             var timee = DateTime.FromFileTime(Style.X2);
 | |
|             var rangeX = this.RangeX;
 | |
|             var rangeY = this.RangeY;
 | |
|             var rangeTimeS = DateTime.FromFileTime(this.Time[RangeX.min]);
 | |
|             var rangeTimeE = DateTime.FromFileTime(this.Time[RangeX.max]);
 | |
| 
 | |
|             var DrawSX = Math.Max(times.ToFileTime(), rangeTimeS.ToFileTime());
 | |
|             var DrawEX = Math.Min(timee.ToFileTime(), rangeTimeE.ToFileTime());
 | |
|             var TimeSX = DateTime.FromFileTime(DrawSX);
 | |
|             var TimeEX = DateTime.FromFileTime(DrawEX);
 | |
|             var TermX = Math.Max(10, (TimeEX - TimeSX).TotalSeconds / 10f);
 | |
| 
 | |
|             var pitchX = ChartRect.Width / 10f;
 | |
|             var pitchY = ChartRect.Height / 10f;
 | |
|             //var borderPen = new Pen(Color.LightGray);// .FromArgb(150, 0xB0, 0xB0, 0xB0), 1);
 | |
|             //borderPen.DashStyle = DashStyle.DashDot;
 | |
|             //float x1, y1, x2, y2;
 | |
|             //for (int r = 1; r < 10; r++)
 | |
|             //{
 | |
|             //    x1 = ChartRect.X;
 | |
|             //    y1 = ChartRect.Y + r * pitchY;
 | |
|             //    y2 = y1;
 | |
|             //    x2 = ChartRect.Right;
 | |
|             //    g.DrawLine(borderPen, x1, y1, x2, y2);
 | |
| 
 | |
|             //    for (int c = 1; c < 10; c++)
 | |
|             //    {
 | |
|             //        x1 = ChartRect.X + c * pitchX;
 | |
|             //        y1 = ChartRect.Y;
 | |
|             //        x2 = x1;
 | |
|             //        y2 = ChartRect.Bottom;
 | |
|             //        g.DrawLine(borderPen, x1, y1, x2, y2);
 | |
|             //    }
 | |
|             //}
 | |
| 
 | |
|             ////draw grid text (X axis)
 | |
|             //for (int c = 1; c < 10; c++)
 | |
|             //{
 | |
|             //    x1 = ChartRect.X + c * pitchX;
 | |
|             //    y1 = ChartRect.Y;
 | |
|             //    x2 = x1;
 | |
|             //    y2 = ChartRect.Bottom;
 | |
|             //    g.DrawLine(borderPen, x1, y1, x2, y2);
 | |
| 
 | |
|             //    var valX = TimeSX.AddSeconds(c * TermX);
 | |
|             //    {
 | |
|             //        var txtrect = new RectangleF(x1 - pitchX / 2f, ChartRect.Bottom + 5, pitchX, 35);
 | |
|             //        g.DrawString($"{valX:yy-MM-dd\nHH:mm:ss}", this.Font, Brushes.Black, txtrect, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
 | |
|             //        g.DrawRectangle(Pens.Red, txtrect.X, txtrect.Y, txtrect.Width, txtrect.Height);
 | |
|             //    }
 | |
|             //}
 | |
|             //for (int r = 1; r < 10; r++)
 | |
|             //{
 | |
|             //    x1 = ChartRect.X;
 | |
|             //    y1 = ChartRect.Y + r * pitchY;
 | |
|             //    y2 = y1;
 | |
|             //    x2 = ChartRect.Right;
 | |
| 
 | |
|             //    var minY = rangeY.min;
 | |
|             //    var maxY = rangeY.max;
 | |
|             //    var TermY = Math.Max(0.1, (maxY - minY) / 10f); //전체 10조각
 | |
|             //    var valY = minY + ((10-r) * TermY); //Y값은 반전시켜야 한다
 | |
| 
 | |
|             //    var txtrect = new RectangleF(ChartRect.Left-50, y1-20 , 50, 40);
 | |
|             //    g.DrawString($"{valY:#0.0}v", this.Font, Brushes.Black, txtrect, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
 | |
|             //    g.DrawRectangle(Pens.Red, txtrect.X, txtrect.Y, txtrect.Width, txtrect.Height);
 | |
| 
 | |
|             //}
 | |
| 
 | |
|             //borderPen.DashStyle = DashStyle.Solid;
 | |
|             //g.DrawRectangle(borderPen, ChartRect.X, ChartRect.Y, ChartRect.Width, ChartRect.Height);
 | |
|             //borderPen.Dispose();
 | |
| 
 | |
|             StringBuilder sb = new StringBuilder();
 | |
|             sb.AppendLine($"Startv View(Y) : {Style.YV1}~{Style.YV2}");
 | |
|             sb.AppendLine($"Startv View(X) : {times}~{timee},{(timee - times).TotalHours}hours");
 | |
|             sb.AppendLine($"Data Range(X) : {rangeTimeS}~{rangeTimeE}");
 | |
|             sb.AppendLine($"Data Range(Y) : {rangeY.min}~{rangeY.max}");
 | |
|             g.DrawString(sb.ToString(), this.Font, Brushes.Red, 100, 100);
 | |
| 
 | |
|             //g.DrawRectangle(Pens.Red, ChartRect.Left, ChartRect.Top, ChartRect.Width, ChartRect.Height);
 | |
|             //g.DrawRectangle(Pens.Blue, LegendRect.Left, LegendRect.Top, LegendRect.Width, LegendRect.Height);
 | |
|             //this.Update();
 | |
|             //this.ResumeLayout();
 | |
|         }
 | |
|         /// Override OnPaint method
 | |
|         protected override void OnPaint(PaintEventArgs e)
 | |
|         {
 | |
|             //base.OnPaint(e);
 | |
|             DateTime start = DateTime.Now;
 | |
| 
 | |
|             //표시아이템이없다면 오류를 낸다.
 | |
|             var g = bufferedGraphics.Graphics;
 | |
|             g.Clear(this.BackColor);
 | |
| 
 | |
|             if (init == false)
 | |
|             {
 | |
|                 DrawScreen_Nodata_With_Message(g, "최기화가 완료되지 않았습니다");
 | |
|             }
 | |
|             else if (chinfo == null)
 | |
|             {
 | |
|                 DrawScreen_Nodata_With_Message(g, initmsg);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
| 
 | |
|                 if (RangeUpdateData == true)
 | |
|                 {
 | |
|                     var datas = CHInfo.Where(t => t.Value.Where(s => s.Key > 0).Any());
 | |
|                     if (datas.Any())
 | |
|                     {
 | |
|                         //자료가 있는것을 대상으로 처리한다.
 | |
|                         pre_minX = datas.Min(t => t.Value.Where(s => s.Key > 0).Min(v => v.Key));
 | |
|                         pre_maxX = datas.Max(t => t.Value.Where(s => s.Key > 0).Max(v => v.Key));
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         pre_minX = pre_maxX = 0;
 | |
|                     }
 | |
| 
 | |
|                     datas = CHInfo.Where(t => t.Value.Where(s => s.Value < MaxValueY && s.Value > -MaxValueY).Any());
 | |
|                     if (datas.Any())
 | |
|                     {
 | |
|                         //100을 초과한 범위는 제한한다
 | |
|                         pre_minY = datas.Min(t => t.Value.Where(s => s.Value < MaxValueY && s.Value > -MaxValueY).Min(u => u.Value));
 | |
|                         pre_maxY = datas.Max(t => t.Value.Where(s => s.Value < MaxValueY && s.Value > -MaxValueY).Max(u => u.Value));
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         pre_minY = pre_maxY = 0;
 | |
|                     }
 | |
| 
 | |
|                     RangeUpdateData = false;
 | |
|                 }
 | |
| 
 | |
|                 DrawScreen_Chart(g);
 | |
| 
 | |
|             }
 | |
|             bufferedGraphics.Render(e.Graphics);
 | |
|             var ts = DateTime.Now - start;
 | |
|             e.Graphics.DrawString($"refresh time:{ts.TotalMilliseconds}ms", this.Font, Brushes.Red, 10, 10);
 | |
|         }
 | |
| 
 | |
|         public bool ShowLegend { get; set; } = false;
 | |
|         void Draw_legend(Graphics g)
 | |
|         {
 | |
|             if (chinfo == null || chinfo.Any() == false) return;
 | |
|             var maxcnt = 10;
 | |
|             var h = LegendRect.Height / maxcnt;
 | |
|             var w = LegendRect.Width;
 | |
|             var showitem = this.chinfo.Where(t => t.Show).ToList();
 | |
|             var itemcnt = Math.Min(10, showitem.Count());
 | |
|             for (int i = 0; i < itemcnt; i++)
 | |
|             {
 | |
|                 var y = LegendRect.Y + i * h;
 | |
|                 var item = showitem[i];
 | |
|                 var rect = new RectangleF(LegendRect.X, y, w, h);
 | |
|                 var rectflag = new RectangleF(rect.X, rect.Y, rect.Width * 0.15f, rect.Height);
 | |
|                 var rectttitle = new RectangleF(rectflag.Right + 3, rect.Y, rect.Width - rectflag.Width - 3, rect.Height);
 | |
|                 using (var bgcolor = new SolidBrush(item.Color))
 | |
|                     g.FillRectangle(bgcolor, rectflag);
 | |
|                 var title = $"{item.TITLE}";
 | |
|                 if (item.Value.Any())
 | |
|                     title = $"{item.TITLE} ({item.Value.Last().Value}v)";
 | |
| 
 | |
|                 g.DrawString(title, this.Font, Brushes.Black, rectttitle, new StringFormat
 | |
|                 {
 | |
|                     Alignment = StringAlignment.Near,
 | |
|                     LineAlignment = StringAlignment.Center
 | |
|                 }); ;
 | |
|                 g.DrawRectangle(Pens.Black, rect.X, rect.Y, rect.Width, rect.Height);
 | |
|             }
 | |
|         }
 | |
|         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 ▦ C1 2012-00-00- 00:00:00 ▦ 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 - FontSize.Height);
 | |
|             //Cursorrect.Width = (int)(FontSize.Width * 1.1);
 | |
|             //Cursorrect.Height = (int)(FontSize.Height * 1.3);
 | |
| 
 | |
|             //g.FillRectangle(Brushes.DimGray, Cursorrect);
 | |
|             //g.DrawRectangle(Pens.Gray, Cursorrect);
 | |
| 
 | |
|             //Single newy = Cursorrect.Top + ((Cursorrect.Height - FontSize.Height)/2) ;
 | |
|             //Single Maxwidth = 0;
 | |
| 
 | |
|             //String fulltext = "";
 | |
| 
 | |
|             var qry = from CUserCursor cs in uc
 | |
|                       orderby cs.Idx
 | |
|                       select cs;
 | |
| 
 | |
| 
 | |
|             cursorstr = "";
 | |
|             foreach (CUserCursor uctl in qry)
 | |
|             {
 | |
|                 Single newx = GetXfromTime(uctl.Time, Crect);
 | |
|                 uctl.Newx = newx;
 | |
| 
 | |
|                 Single imgsizew = vmsnet.Properties.Resources.down_16.Width;
 | |
|                 Single imgsizeh = vmsnet.Properties.Resources.down_16.Height;
 | |
| 
 | |
|                 cursorstr += " ▦ C" + (uctl.Idx + 1).ToString() + " " + GetTimeStr(uctl.Time, true, true, true, true);
 | |
| 
 | |
|                 FontSize = g.MeasureString(cursorstr.ToString(), cfont);
 | |
|                 //  if (FontSize.Width > Maxwidth) Maxwidth = FontSize.Width;
 | |
| 
 | |
|                 if (uctl.Idx < 1)
 | |
|                 {
 | |
|                     g.DrawImage(vmsnet.Properties.Resources.down_16, (newx - imgsizew / 2) - 1, Crect.Top - imgsizeh - 5);
 | |
|                     g.DrawLine(new Pen(Color.Green, 1), newx, Crect.Top, newx, Crect.Top + Crect.Height);
 | |
| 
 | |
|                     // fulltext = cursorstr;
 | |
| 
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     TimeSpan ts = DateTime.FromFileTime(uctl.Time) - DateTime.FromFileTime(uc[0].Time);
 | |
|                     cursorstr += "  △t " + ts.Days.ToString() + "d " + ts.Hours.ToString() + ":" + ts.Minutes.ToString() + ":" + ts.Seconds.ToString();
 | |
| 
 | |
|                     g.DrawImage(vmsnet.Properties.Resources.down_orange, (newx - imgsizew / 2) - 1, Crect.Top - imgsizeh - 5);
 | |
|                     g.DrawLine(new Pen(Color.Orange, 1), newx, Crect.Top, newx, Crect.Top + Crect.Height);
 | |
|                     // if (fulltext == "") fulltext = cursorstr;
 | |
|                     //  else fulltext += "\n" + cursorstr; 
 | |
| 
 | |
|                 }
 | |
|                 //  newy += FontSize.Height + 1;
 | |
|             }
 | |
| 
 | |
|             if (cursorstr != "")
 | |
|             {
 | |
|                 FontSize = g.MeasureString(cursorstr, cfont);
 | |
|                 g.DrawString(cursorstr, cfont, Brushes.Black, Crect.Right - FontSize.Width - 2, Crect.Top - FontSize.Height - 2);
 | |
|             }
 | |
| 
 | |
|             //
 | |
|             // 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(Mouseinfo.Time, true, true, true, true) + "\n" + Mouseinfo.Volt.ToString("#0.00") + "v";
 | |
|                 if (Style.Show_DebugMsg) 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);
 | |
|                 if (Mouseinfo.Position.X >= (this.ChartRect.Left + ChartRect.Width / 2))
 | |
|                 {
 | |
|                     //마우스위치에따라서 표시정보 위치를 좌/우 교환한다  150223
 | |
|                     rect = new RectangleF(Mouseinfo.Position.X - (tmsize.Width + 10) - 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)
 | |
|         {
 | |
| 
 | |
|             //그리드는 무조건 10개로 쪼개서 표시한다.
 | |
| 
 | |
|             //설정된 표시영역
 | |
|             DateTime SDate = DateTime.FromFileTime(Style.XV1);
 | |
|             DateTime EDate = DateTime.FromFileTime(Style.XV2);
 | |
| 
 | |
|             //실제데이터영역
 | |
|             DateTime Real_SDate = DateTime.FromFileTime(Time[RangeX.min]);
 | |
|             DateTime Real_EDate = DateTime.FromFileTime(Time[RangeX.max]);
 | |
| 
 | |
|             var (normalizedStart, normalizedEnd) = NormalizeTimeRangeHalfHourIntervals(SDate, EDate);
 | |
|             //SDVDate = normalizedStart;
 | |
|             SDate = normalizedStart;
 | |
|             EDate = normalizedEnd;
 | |
| 
 | |
|             SDate = Real_SDate > SDate ? Real_EDate : SDate;    //실제데이터가 보이는 영역보다 크다면 , 실데이터를 기준으로 한다.
 | |
|             EDate = Real_EDate > EDate ? EDate : Real_SDate;    //실제데이터가 종료일자보다 크면 종료일자로 표시한다.
 | |
| 
 | |
|             TimeSpan TS = EDate - SDate;    //timespan
 | |
| 
 | |
|             var TermX = (int)((EDate - SDate).TotalSeconds / 10f);
 | |
| 
 | |
|             if (TS.TotalSeconds > Style.MaxZoomX)
 | |
|             {
 | |
|                 //표시간격 최소 10초
 | |
|                 int tm = 10;
 | |
| 
 | |
|                 if (Style.XGap == 0)
 | |
|                 {
 | |
|                     tm = (int)(TS.TotalSeconds / 5);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     tm = Style.XGap;
 | |
|                 }
 | |
| 
 | |
|                 var termcnt = (int)(TS.TotalSeconds / tm);
 | |
|                 if (termcnt < 10)
 | |
|                 {
 | |
|                     tm = (int)(TS.TotalSeconds / 10f);
 | |
|                 }
 | |
|                 else if (termcnt > 10) //간격이 너무 크다
 | |
|                 {
 | |
|                     tm = (int)(TS.TotalSeconds / 10f);
 | |
|                 }
 | |
|                 tm = GetClosestInterval(tm);
 | |
| 
 | |
|                 for (Int64 i = 0; i <= TS.TotalSeconds; i += tm)
 | |
|                 {
 | |
|                     DateTime NewDate = SDate.AddSeconds(i); //시작시간에서
 | |
|                     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);
 | |
|                         SDate = NewDate;
 | |
|                     }
 | |
| 
 | |
|                     Single newx = GetXfromTime(NewDate.ToFileTime(), crect);
 | |
|                     String timestr = "";
 | |
| 
 | |
|                     if (i == 0) timestr = GetDateTimeStr(NewDate.ToFileTime(), true);
 | |
|                     else timestr = GetTimeStr(NewDate.ToFileTime(), i == 0 ? true : false, false);
 | |
| 
 | |
|                     timestr = NewDate.ToString("yy-MM-dd") + "\n" + NewDate.ToString("HH:mm:ss");
 | |
| 
 | |
|                     DrawString(g, timestr, Style.FontX, 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);
 | |
|                 }
 | |
| 
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 //Y축 값을 표시할 값이 없으면 오류를 표시한다.
 | |
|                 DrawString(g, "ERRX", Style.FontX, Brushes.Black, new PointF(crect.Left - 2, crect.Bottom), EALIGN.RIGHT, EALIGN.CENTER);
 | |
|             }
 | |
| 
 | |
| 
 | |
| 
 | |
|             //세로(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);
 | |
| 
 | |
|             if (Math.Abs(Style.YV2 - Style.YV1) >= Style.MaxZoomY)
 | |
|             {
 | |
|                 Single term;
 | |
|                 if (Style.YGap == 0)
 | |
|                 {
 | |
|                     term = (Style.YV2 - Style.YV1) / 10;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     term = Style.YGap;
 | |
|                 }
 | |
| 
 | |
|                 for (Single i = Style.YV1; i <= Style.YV2; i += term)
 | |
|                 {
 | |
|                     // 세로길이 = 10v : 
 | |
|                     Single newy = GetYfromVolt(i, crect);
 | |
|                     if (Style.YV1 == 0 && i == 0)
 | |
|                     {
 | |
| 
 | |
|                     }
 | |
|                     else g.DrawLine(new Pen(Color.Gray), crect.Left, newy, crect.Left + crect.Width, newy);
 | |
| 
 | |
|                     //소수점없는경우에눈금표시한다.
 | |
|                     DrawString(g, i.ToString("#0.00"), Style.FontY, Brushes.Black, new PointF(crect.Left - 2, newy), EALIGN.RIGHT, EALIGN.CENTER);
 | |
|                 }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 //Y축 값을 표시할 값이 없으면 오류를 표시한다.
 | |
|                 DrawString(g, "ERRY", Style.FontY, Brushes.Black, new PointF(crect.Left - 2, crect.Top + 2), EALIGN.RIGHT, EALIGN.CENTER);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public (DateTime normalizedStart, DateTime normalizedEnd) NormalizeTimeRangeHalfHourIntervals(DateTime start, DateTime end)
 | |
|         {
 | |
|             const int intervalInSeconds = 1800; // 30 minutes
 | |
| 
 | |
|             DateTime normalizedStart = NormalizeTimeToInterval(start, intervalInSeconds, roundDown: true);
 | |
|             DateTime normalizedEnd = NormalizeTimeToInterval(end, intervalInSeconds, roundDown: false);
 | |
| 
 | |
|             return (normalizedStart, normalizedEnd);
 | |
|         }
 | |
| 
 | |
|         private DateTime NormalizeTimeToInterval(DateTime time, int intervalInSeconds, bool roundDown)
 | |
|         {
 | |
|             long ticks = time.Ticks / TimeSpan.TicksPerSecond;
 | |
|             if (roundDown)
 | |
|             {
 | |
|                 ticks = (ticks / intervalInSeconds) * intervalInSeconds; // Round down
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 ticks = ((ticks + intervalInSeconds - 1) / intervalInSeconds) * intervalInSeconds; // Round up
 | |
|             }
 | |
|             return new DateTime(ticks * TimeSpan.TicksPerSecond);
 | |
|         }
 | |
| 
 | |
| 
 | |
|         private readonly int[] TimeIntervals = new int[]
 | |
|            {
 | |
|                 1, 10, 30, 60, 300, 600, 1800, 3600, 21600, 43200, 86400, 432000, 864000, 2592000
 | |
|            };
 | |
|         public int GetClosestInterval(int seconds)
 | |
|         {
 | |
|             // Handle cases where seconds is less than the smallest interval or more than the largest interval
 | |
|             if (seconds <= TimeIntervals[0])
 | |
|                 return TimeIntervals[0];
 | |
|             if (seconds >= TimeIntervals[TimeIntervals.Length - 1])
 | |
|                 return TimeIntervals[TimeIntervals.Length - 1];
 | |
| 
 | |
|             // Find the closest interval
 | |
|             int closestInterval = TimeIntervals[0];
 | |
|             int minDifference = Math.Abs(seconds - closestInterval);
 | |
| 
 | |
|             foreach (int interval in TimeIntervals)
 | |
|             {
 | |
|                 int difference = Math.Abs(seconds - interval);
 | |
|                 if (difference < minDifference)
 | |
|                 {
 | |
|                     minDifference = difference;
 | |
|                     closestInterval = interval;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return closestInterval;
 | |
|         }
 | |
| 
 | |
|         public void Draw_Debug(Graphics g)
 | |
|         {
 | |
|             if (!Style.Show_DebugMsg) return;
 | |
| 
 | |
|             //Single newy = 50;
 | |
|             //String newstr = "";
 | |
|             SizeF fontsize;
 | |
| 
 | |
|             StringBuilder DebugMsg = new StringBuilder();
 | |
| 
 | |
|             DebugMsg.AppendLine("Mouseinfo=" + this.Mouseinfo.Position.ToString() + " " + this.Mouseinfo.Showinfo.ToString());
 | |
|             DebugMsg.AppendLine("Mouseinfo0=" + this.Mouseinfo.Position0.ToString() + " idx=" + this.Mouseinfo.DragIndex.ToString());
 | |
|             DebugMsg.AppendLine("Mouse Volt =" + this.Mouseinfo.Volt.ToString() + " ,Time=" + DateTime.FromFileTime(Mouseinfo.Time).ToString());
 | |
|             DebugMsg.AppendLine("Mouse Drag=" + Mouseinfo.Drag.ToString() + " " + Mouseinfo.DragType.ToString());
 | |
|             DebugMsg.AppendLine("Mouse DragStart=" + Mouseinfo.DragStart.ToString());
 | |
|             DebugMsg.AppendLine("TimeCount =" + Time.Count.ToString());
 | |
| 
 | |
|             TimeSpan NowTerm = DateTime.FromFileTime(Style.X2) - DateTime.FromFileTime(Style.X1);
 | |
|             DebugMsg.AppendLine("XGap =" + Style.XGap.ToString() + ",YGap=" + Style.YGap.ToString() + ",Xterm=" + Style.X표시범위.ToString() + ",NowTerm=" + NowTerm.ToString());
 | |
| 
 | |
|             foreach (String file in Files)
 | |
|             {
 | |
|                 DebugMsg.AppendLine("File = " + file);
 | |
|             }
 | |
|             foreach (CUserCursor ucitem in uc)
 | |
|             {
 | |
|                 DebugMsg.AppendLine("uc" + ucitem.Idx.ToString() + ",x=" + ucitem.Newx.ToString() + ",time=" + ucitem.Time.ToString());
 | |
|             }
 | |
| 
 | |
|             DebugMsg.AppendLine("======================");
 | |
|             DebugMsg.AppendLine("시간축=" + Style.X1.ToString() + "~" + Style.X2.ToString() + " : " + DateTime.FromFileTime(Style.X1).ToString("yy-MM-dd HH:mm:ss") + "~" + DateTime.FromFileTime(Style.X2).ToString("yy-MM-dd HH:mm:ss"));
 | |
|             DebugMsg.AppendLine("시간축V=" + Style.XV1.ToString() + "/" + Style.XV2.ToString() + " : " + DateTime.FromFileTime(Style.XV1).ToString("yy-MM-dd HH:mm:ss") + "~" + DateTime.FromFileTime(Style.XV2).ToString("yy-MM-dd HH:mm:ss"));
 | |
|             DebugMsg.AppendLine("시간축VO=" + Style.XV1o.ToString() + "/" + Style.XV2o.ToString() + " : " + DateTime.FromFileTime(Style.XV1o).ToString("yy-MM-dd HH:mm:ss") + "~" + DateTime.FromFileTime(Style.XV2o).ToString("yy-MM-dd HH:mm:ss"));
 | |
|             DebugMsg.AppendLine("======================");
 | |
|             DebugMsg.AppendLine("전압축=" + Style.Y1.ToString() + "~" + Style.Y2.ToString());
 | |
|             DebugMsg.AppendLine("전압축V=" + Style.YV1.ToString() + "~" + Style.YV2.ToString());
 | |
|             DebugMsg.AppendLine("전압축VO=" + Style.YV1o.ToString() + "~" + Style.YV2o.ToString());
 | |
|             DebugMsg.AppendLine("======================");
 | |
| 
 | |
|             DebugMsg.AppendLine("UserZoom=" + UserZoom.ToString());
 | |
| 
 | |
|             // newstr = "CHinfo=" + chinfo.GetUpperBound(0);
 | |
| 
 | |
|             foreach (CChinfo ch in chinfo)
 | |
|             {
 | |
|                 DebugMsg.AppendLine("idx=" + ch.Idx.ToString() + ",visible:" + ch.Show.ToString() + ",cnt=" + ch.Value.Count.ToString() + ",Color=" + ch.Color.ToString());
 | |
|             }
 | |
| 
 | |
|             fontsize = g.MeasureString(DebugMsg.ToString(), this.Font);
 | |
|             g.FillRectangle(new SolidBrush(Color.FromArgb(180, Color.Black)), new Rectangle(100, 100, (int)(fontsize.Width * 1.3), (int)(fontsize.Height * 1.3)));
 | |
|             g.DrawString(DebugMsg.ToString(), this.Font, Brushes.Tomato, 110, 110);
 | |
|         }
 | |
| 
 | |
|         public List<String> Files = new List<string>();
 | |
| 
 | |
|         public void DataClear()
 | |
|         {
 | |
|             if (uc != null) uc.Clear();
 | |
|             if (chinfo != null) Array.Clear(chinfo, 0, chinfo.Length);
 | |
|             if (Time != null) this.Time.Clear();
 | |
|             if (Files != null) Files.Clear();
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 지정된 시간값이 현재 존재하는가?
 | |
|         /// </summary>
 | |
|         /// <param name="value">int64 : time value</param>
 | |
|         /// <returns></returns>
 | |
|         public Boolean ExistTime(Int64 _value)
 | |
|         {
 | |
|             //   if (Time.Count < 1) return false;
 | |
| 
 | |
|             return Time.Select(t => t.Value).ToList().Contains(_value);
 | |
|             //for (int i = 1; i <= Time.Count; i++)
 | |
|             //{
 | |
|             //    if (_value == Time[i - 1].Value) return true;
 | |
|             //}
 | |
|             //return false;
 | |
|         }
 | |
| 
 | |
|         public void ScaleFitX()
 | |
|         {
 | |
|             var xrange = this.RangeX;
 | |
|             this.Style.XV1 = xrange.min;
 | |
|             this.Style.XV2 = xrange.max;
 | |
|             this.Invalidate();
 | |
|         }
 | |
|         public void ScaleFitY()
 | |
|         {
 | |
|             var xrange = this.RangeY;
 | |
|             this.Style.YV1 = xrange.min;
 | |
|             this.Style.YV2 = xrange.max;
 | |
|             this.Invalidate();
 | |
|         }
 | |
|         public void ScaleFitXY()
 | |
|         {
 | |
|             ScaleFitX();
 | |
|             ScaleFitY();
 | |
|         }
 | |
| 
 | |
| 
 | |
|         public void Draw_channel(Graphics g, RectangleF crect, RectangleF wrect)
 | |
|         {
 | |
|             //지정된 시간에 속한 타임만 취듯한다.
 | |
|             var rangeX = this.RangeX;
 | |
|             var minTime = this.Time[rangeX.min];
 | |
|             var maxTime = this.Time[rangeX.max];
 | |
| 
 | |
|             var qry = Time
 | |
|     .Where(t => t.Value >= Style.XV1 && t.Value <= Style.XV2)
 | |
|     .OrderBy(t => t.Value)
 | |
|     .ToDictionary(t => t.Key, t => t.Value);
 | |
| 
 | |
| 
 | |
| 
 | |
|             if (qry.Any() == false) return;
 | |
| 
 | |
|             //지정된 시간영역의 자료의 범위를 측정
 | |
|             var time_min = qry.Min(t => t.Key); //최소시간정보
 | |
|             var time_max = qry.Max(t => t.Key); //최대시간정보
 | |
| 
 | |
|             //각채널의 데이터를 확인한다(시간정보[최소~최대]에 포함된것만 표시한다)
 | |
|             var chlist = chinfo.Where(t => t != null && t.Show
 | |
|             && (t.Value.Max(s => s.Key) >= time_min && t.Value.Min(s => s.Key) <= time_max)).ToList();
 | |
| 
 | |
|             foreach (var ch in chinfo)
 | |
|             {
 | |
|                 if (ch == null || ch.Show == false) continue;
 | |
|                 //var minX = ch.Value.Min(s => s.Key);
 | |
|                 //var maxX = ch.Value.Max(s => s.Key);
 | |
| 
 | |
|                 //해당채널내에서 지정된 영역의 자료만 가져온다.
 | |
|                 var valueList = ch.Value.Where(t => t.Key >= time_min && t.Key <= time_max).ToDictionary(t => t.Key, t => t.Value);
 | |
|                 if (valueList.Any() == false) continue;
 | |
| 
 | |
|                 List<PointF> linearrya = new List<PointF>(0);
 | |
| 
 | |
|                 Single PreX = 0;
 | |
|                 Single PreY = 0;
 | |
|                 Boolean fc1 = false, fc2 = false;
 | |
|                 int idx = 0;
 | |
| 
 | |
|                 //저장된 모든 값을 출력한다.
 | |
|                 foreach (var cdata in valueList)
 | |
|                 {
 | |
|                     //시간정보는 동일하다면 조회하지 않게한다.
 | |
|                     var time = qry[cdata.Key];
 | |
|                     var volt = cdata.Value;
 | |
| 
 | |
|                     //좌표계산
 | |
|                     Single newx = GetXfromTime(time, crect) - 1;
 | |
|                     Single newy = GetYfromVolt(volt, crect) - 1;
 | |
| 
 | |
|                     //커서값확인
 | |
|                     foreach (CUserCursor cs in uc)
 | |
|                     {
 | |
|                         if (cs.Idx == 0 && time >= cs.Time && fc1 == false)
 | |
|                         {
 | |
|                             if (volt > 60) ch.C1value = "OVER";
 | |
|                             else ch.C1value = volt.ToString();
 | |
|                             fc1 = true;
 | |
|                         }
 | |
|                         else if (cs.Idx == 1 && time >= cs.Time && fc2 == false)
 | |
|                         {
 | |
|                             if (volt > 60) ch.C2value = "OVER";
 | |
|                             else ch.C2value = volt.ToString();
 | |
|                             fc2 = true;
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     //너무가까운데이터는 그리지 않는다.
 | |
|                     //if (Math.Abs(newx - PreX) < 1 && Math.Abs(newy - PreY) < 1)
 | |
|                     //{
 | |
|                     //    //Console.WriteLine("SKip Pixel");
 | |
|                     //    continue;
 | |
|                     //}
 | |
|                     //else
 | |
|                     //{
 | |
|                     PreX = newx;
 | |
|                     PreY = newy;
 | |
|                     //}
 | |
| 
 | |
|                     if (newx >= wrect.Left && newx <= wrect.Left + wrect.Width)  //y축은 구분없이 모두 그리게한다.
 | |
|                         linearrya.Add(new PointF(newx, newy));
 | |
| 
 | |
|                     if (Style.Show_DataPoint)
 | |
|                     {
 | |
|                         var size = 2;
 | |
|                         g.FillEllipse(new SolidBrush(Color.FromArgb(180, ch.Color)), new RectangleF(newx - size, newy - size, size * 2, size * 2));
 | |
|                         g.DrawEllipse(Pens.Black, new RectangleF(newx - size, newy - size, size * 2, size * 2));
 | |
|                     }
 | |
| 
 | |
| 
 | |
|                     idx += 1;
 | |
| 
 | |
|                 }
 | |
|                 if (linearrya.Count > 1)
 | |
|                     g.DrawLines(new Pen(ch.Color, 10), linearrya.ToArray());
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public void Draw_ZoomSelect(Graphics g)
 | |
|         {
 | |
|             //사용자줌영역표시
 | |
|             if (this.UserZoom.Width != 0)
 | |
|             {
 | |
|                 int x, y, w, h;
 | |
| 
 | |
|                 w = Math.Abs(UserZoom.Width);
 | |
|                 h = Math.Abs(UserZoom.Height);
 | |
| 
 | |
|                 if (UserZoom.Width > 0) x = UserZoom.Left;
 | |
|                 else x = UserZoom.Width + UserZoom.Left;
 | |
| 
 | |
|                 if (UserZoom.Height > 0) y = UserZoom.Top;
 | |
|                 else y = UserZoom.Height + UserZoom.Top;
 | |
| 
 | |
|                 //Y축 줌을 사용하지 않으므로 높이부분은 모두로 처리한다.
 | |
|                 if (!Style.UseZoomY)
 | |
|                 {
 | |
|                     y = (int)ChartRect.Top;
 | |
|                     h = (int)ChartRect.Height;
 | |
|                 }
 | |
| 
 | |
|                 Rectangle rect = new Rectangle(x, y, w, h);
 | |
| 
 | |
|                 Int64 startx = GetTimeFromX(rect.Left - this.ChartRect.Left, ChartRect);    //줌영역의 시작시간정보
 | |
|                 Int64 endx = GetTimeFromX(rect.Left + rect.Width - ChartRect.Left, ChartRect);  //줌영역의 종료시간정보
 | |
| 
 | |
|                 Single starty = (Single)GetVoltfromY(rect.Top, ChartRect);
 | |
|                 Single endy = (Single)GetVoltfromY(rect.Top + rect.Height, ChartRect);
 | |
| 
 | |
|                 String ZommMsg = "";
 | |
| 
 | |
|                 //선택된 영역 Drawing
 | |
|                 TimeSpan zoomts = DateTime.FromFileTime(startx) - DateTime.FromFileTime(endx);
 | |
|                 if (Math.Abs(zoomts.TotalSeconds) >= Style.MaxZoomX && Math.Abs(starty - endy) >= Style.MaxZoomY && rect.Width > 20) //150224 줌영역자체의 크기는 10px를 넘도록
 | |
|                 {
 | |
|                     //시간은 최소1분 , 전압값은 최소 1v
 | |
|                     g.FillRectangle(new SolidBrush(Color.FromArgb(150, Color.Lime)), rect);
 | |
|                     ZommMsg = Math.Abs(zoomts.TotalSeconds).ToString("N0") + Style.UnitX;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     g.FillRectangle(new SolidBrush(Color.FromArgb(150, Color.Red)), rect);
 | |
| 
 | |
|                     if (rect.Width <= 20)
 | |
|                     {
 | |
|                         ZommMsg = "줌 선택영역을 넓게 지정하세요";
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         if (Math.Abs(zoomts.TotalSeconds) < Style.MaxZoomX)
 | |
|                         {
 | |
|                             ZommMsg = "줌을 활성화 하려면 최소(" + Style.MaxZoomX.ToString() + Style.UnitX + "의 구간을 선택해야합니다";
 | |
|                         }
 | |
|                         else
 | |
|                         {
 | |
|                             ZommMsg = "줌을 활성화 하려면 최소(" + Style.MaxZoomY.ToString() + Style.UnitY + "의 구간을 선택해야합니다";
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                 }
 | |
| 
 | |
|                 g.DrawRectangle(Pens.Black, rect);
 | |
| 
 | |
|                 //시간정보 Display
 | |
|                 g.DrawString(GetTimeStr(startx, true, true) + "," + (Style.Y2 - starty).ToString("#0.00") + Style.UnitY, this.Font, Brushes.Black, rect.Left, rect.Top);
 | |
|                 String fontstr = GetTimeStr(endx, true, true) + "," + (Style.Y2 - endy).ToString("#0.00") + Style.UnitY;
 | |
|                 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);
 | |
| 
 | |
|                 if (ZommMsg != "")
 | |
|                     DrawString(g, ZommMsg, this.Font, Brushes.Black, new PointF(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2), EALIGN.CENTER, EALIGN.CENTER);
 | |
| 
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 화면의 좌,우 측에 존재하는 이돈버튼(월을 움직이는 버튼이며 월 이동을위해서 이벤트를 발생한다)
 | |
|         /// </summary>
 | |
|         /// <param name="G"></param>
 | |
|         //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)
 | |
|         {
 | |
|             if (Filetime < 0D) return "-Err-";
 | |
| 
 | |
|             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("yy-MM-dd") + " " + timestr;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     if (nolf) timestr = TimeDate.ToString("dd") + "일 " + timestr;
 | |
|                     else timestr = timestr + "\n" + TimeDate.ToString("dd") + "일";
 | |
|                 }
 | |
|             }
 | |
|             return timestr;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// (전체시간 * 현재X) / 전체너비
 | |
|         /// </summary>
 | |
|         /// <param name="t"></param>
 | |
|         /// <returns></returns>
 | |
|         public Int64 GetTimeFromX(Single X, RectangleF crect)
 | |
|         {
 | |
|             if (crect.Width < 1 || crect.Height < 1) return 0;
 | |
|             DateTime sd = DateTime.FromFileTime(Style.XV1);
 | |
|             DateTime ed = DateTime.FromFileTime(Style.XV2);
 | |
|             TimeSpan ts = ed - sd;
 | |
| 
 | |
|             Int64 gap = (Int64)((ts.TotalMilliseconds * X) / crect.Width);
 | |
|             return sd.AddMilliseconds(gap).ToFileTime();
 | |
|         }
 | |
|         public Single GetXfromTime(Int64 t)
 | |
|         {
 | |
|             return (((this.ChartRect.Width) * (t - Style.XV1)) / (Style.XV2 - Style.XV1)) + ChartRect.Left;
 | |
|         }
 | |
|         public Single GetXfromTime(Int64 t, RectangleF crect)
 | |
|         {
 | |
|             return (((crect.Width) * (t - Style.XV1)) / (Style.XV2 - Style.XV1)) + crect.Left;
 | |
|         }
 | |
|         public Single GetVoltfromY(Single Y, RectangleF crect)
 | |
|         {
 | |
| 
 | |
|             return ((Style.Y2 - Style.Y1) * Y) / crect.Height;
 | |
| 
 | |
|         }
 | |
|         public Single GetYfromVolt(Single volt, RectangleF crect)
 | |
|         {
 | |
|             //volt = (Style._endvolt - Style._startvolt) - volt;  150223 : Y값도 X축처럼 표시변수 YV 값으로 수정함
 | |
|             return (crect.Height - ((crect.Height * (volt - Style.YV1)) / (Style.YV2 - Style.YV1))) + 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 Boolean INIT
 | |
|         {
 | |
|             get { return this.init; }
 | |
|             set { this.init = value; }
 | |
|         }
 | |
|         public CChinfo[] CHInfo
 | |
|         {
 | |
|             get { return this.chinfo; }
 | |
|             set { this.chinfo = value; }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 데이터가 추가되었거나 변경되었다면 이 값이 True가 되며 False는 manual 로 전환해야 합니다
 | |
|         /// </summary>
 | |
|         bool RangeUpdateData = true;
 | |
|         uint pre_minX, pre_maxX;
 | |
|         float pre_minY, pre_maxY;
 | |
| 
 | |
|         public (uint min, uint max) RangeX
 | |
|         {
 | |
|             get
 | |
|             {
 | |
| 
 | |
|                 return (pre_minX, pre_maxX);
 | |
|             }
 | |
|         }
 | |
|         public (float min, float max) RangeY
 | |
|         {
 | |
|             get
 | |
|             {
 | |
| 
 | |
|                 return (pre_minY, pre_maxY);
 | |
|             }
 | |
|         }
 | |
| 
 | |
| 
 | |
|         public int LegendWidth { get; set; } = 200;
 | |
|         public RectangleF LegendRect { get; private set; }
 | |
| 
 | |
|         public Rectangle ScreenRect { get; private set; } = Rectangle.Empty;
 | |
|         protected override void OnSizeChanged(EventArgs e)
 | |
|         {
 | |
|             base.OnSizeChanged(e);
 | |
|             if (this.Visible == false) return;
 | |
|             Console.WriteLine("OnSizeChanged");
 | |
| 
 | |
| 
 | |
|         }
 | |
| 
 | |
|         void CreateBufferGraphic()
 | |
|         {
 | |
|             if (this.bufferedGraphics != null)
 | |
|             {
 | |
|                 bufferedGraphics.Dispose();
 | |
|                 bufferedGraphics = context.Allocate(this.CreateGraphics(), this.ClientRectangle);
 | |
|                 bufferedGraphics.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
 | |
|             }
 | |
| 
 | |
|         }
 | |
|         protected override void OnResize(EventArgs e)
 | |
|         {
 | |
|             base.OnResize(e);
 | |
|             Console.WriteLine("OnResize");
 | |
|             if (this.Visible == false) return;
 | |
| 
 | |
|             //크기변경이 없다면 처리하지 않는다.
 | |
|             //if (ScreenRect.Equals(this.ClientRectangle))
 | |
|             {
 | |
|                 if (this.bufferedGraphics == null && context != null)
 | |
|                 {
 | |
|                     if (this.ClientRectangle.Width != 0 && this.ClientRectangle.Height != 0)
 | |
|                     {
 | |
|                         bufferedGraphics = context.Allocate(this.CreateGraphics(), this.ClientRectangle);
 | |
|                         bufferedGraphics.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
 | |
|                     }
 | |
|                 }
 | |
|                 return;
 | |
|             }
 | |
|             //ScreenRect = ClientRectangle;
 | |
| 
 | |
|             if (this.bufferedGraphics != null && context != null)
 | |
|             {
 | |
|                 bufferedGraphics.Dispose();
 | |
|                 if (this.ClientRectangle.Width == 0 || this.ClientRectangle.Height == 0)
 | |
|                 {
 | |
|                     bufferedGraphics = null;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     bufferedGraphics = context.Allocate(this.CreateGraphics(), this.ClientRectangle);
 | |
|                     bufferedGraphics.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
| 
 | |
|             LegendWidth = 100;
 | |
|             this.WindowRect = new RectangleF(0, 0, this.Width, this.Height);
 | |
|             if (ShowLegend)
 | |
|             {
 | |
|                 this.ChartRect = new RectangleF(Padding.Left, Padding.Top,
 | |
|             this.Width - (Padding.Left + 10) - LegendWidth - 20,
 | |
|             (Single)(this.Height - (Padding.Top + Padding.Bottom)));
 | |
|                 LegendRect = new RectangleF(ChartRect.Right + 10, ChartRect.Y, LegendWidth + 10, ChartRect.Height);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 this.ChartRect = new RectangleF(Padding.Left, Padding.Top,
 | |
|                 this.Width - (Padding.Left + Padding.Right) - 20,
 | |
|                 (Single)(this.Height - (Padding.Top + Padding.Bottom)));
 | |
|                 LegendRect = RectangleF.Empty;  // new RectangleF(ChartRect.Right + 20, ChartRect.Y, LegendWidth, ChartRect.Height);
 | |
| 
 | |
|             }
 | |
| 
 | |
|             int SW = this.Width;
 | |
|             int SH = this.Height;
 | |
|             if (this.Width == 0 || this.Height == 0)
 | |
|             {
 | |
|                 SW = 600;
 | |
|                 SH = 600;
 | |
|             }
 | |
| 
 | |
| 
 | |
|             layer_bak = new Bitmap(SW, SH);
 | |
|             layer_graph = new Bitmap(SW, SH);
 | |
|             layer_bakT = new Bitmap(SW, SH);
 | |
|             layer_graphT = new Bitmap(SW, SH);
 | |
| 
 | |
|             Graphics.FromImage(layer_bak).Clear(Color.White);
 | |
|             Graphics.FromImage(layer_bakT).Clear(Color.White);
 | |
| 
 | |
|             Set_Refresh();
 | |
|             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 && this.Mouseinfo.Position.Y <= ChartRect.Top)
 | |
|                     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.TrendCtrl_MouseDown);
 | |
|             this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.TrendCtrl_MouseMove);
 | |
|             this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.TrendCtrl_MouseUp);
 | |
|             this.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.TrendCtrl_MouseWhell);
 | |
|             this.ResumeLayout(false);
 | |
|         }
 | |
| 
 | |
|         public void Graph_Reset()
 | |
|         {
 | |
|             Style.ResetXxis();
 | |
|             Style.ResetYxis();
 | |
|             Set_Refresh();
 | |
|             Console.WriteLine("Graph : Graph_Reset");
 | |
|         }
 | |
| 
 | |
|         private void TrendCtrl_MouseDown(object sender, MouseEventArgs e)
 | |
|         {
 | |
| 
 | |
| 
 | |
|             switch (e.Button)
 | |
|             {
 | |
|                 case System.Windows.Forms.MouseButtons.Left:
 | |
| 
 | |
|                     //드래그판단을위한 위치값을 저장한다.
 | |
|                     Mouseinfo.DragStart = new PointF(e.X - this.WindowRect.Left, e.Y - WindowRect.Top);
 | |
| 
 | |
|                     //화면이동모드일때는 좌측버튼도 중앙버튼처럼 처리해야한다.
 | |
|                     if (ScreenMove)
 | |
|                     {
 | |
|                         //X축 줌을 사용한경우에만 가능하게 한다.
 | |
|                         if (Style.UseZoomX)
 | |
|                         {
 | |
|                             //아무것도없는 빈공간이라면 화면이동(=줌시작)으로 대체한다.
 | |
|                             if (e.X >= ChartRect.Left && e.X <= ChartRect.Left + ChartRect.Width && e.Y >= ChartRect.Top && e.Y <= ChartRect.Top + ChartRect.Height)
 | |
|                             {
 | |
|                                 if (Style.XV2 == Style.X2 && Style.XV1 == Style.X1)
 | |
|                                 {
 | |
|                                     //데이터영역과 표시영역이 동일하다(이동할 영역이 없는경우이다)
 | |
|                                     Mouseinfo.DragType = EDRAGTYPE.NONE;
 | |
|                                 }
 | |
|                                 else
 | |
|                                 {
 | |
|                                     //이동할영역이 존재하므로 이동시킨다.
 | |
|                                     Mouseinfo.DragType = EDRAGTYPE.SCREEN;
 | |
|                                     this.UserZoom = new Rectangle(0, 0, 0, 0);
 | |
|                                 }
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
| 
 | |
|                         //사용자포인트관련
 | |
|                         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 (Style.UseZoomX)
 | |
|                             {
 | |
|                                 Mouseinfo.DragType = EDRAGTYPE.ZOOM;
 | |
|                                 this.UserZoom = new Rectangle(e.X, e.Y, 0, 0);
 | |
|                             }
 | |
|                             else
 | |
|                             {
 | |
|                                 //줌을 사용하지 않기로 하여 ㅆ다면?
 | |
|                                 Mouseinfo.DragType = EDRAGTYPE.NONE;
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     break;
 | |
| 
 | |
|                 case System.Windows.Forms.MouseButtons.Middle:
 | |
| 
 | |
|                     //X축 줌을 사용한경우에만 가능하게 한다.
 | |
|                     if (Style.UseZoomX)
 | |
|                     {
 | |
|                         //아무것도없는 빈공간이라면 화면이동(=줌시작)으로 대체한다.
 | |
|                         if (e.X >= ChartRect.Left && e.X <= ChartRect.Left + ChartRect.Width && e.Y >= ChartRect.Top && e.Y <= ChartRect.Top + ChartRect.Height)
 | |
|                         {
 | |
|                             if (Style.XV2 == Style.X2 && Style.XV1 == Style.X1)
 | |
|                             {
 | |
|                                 //데이터영역과 표시영역이 동일하다(이동할 영역이 없는경우이다)
 | |
|                                 Mouseinfo.DragType = EDRAGTYPE.NONE;
 | |
|                             }
 | |
|                             else
 | |
|                             {
 | |
|                                 //이동할영역이 존재하므로 이동시킨다.
 | |
|                                 Mouseinfo.DragType = EDRAGTYPE.SCREEN;
 | |
|                                 this.UserZoom = new Rectangle(0, 0, 0, 0);
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     break;
 | |
| 
 | |
|                 case System.Windows.Forms.MouseButtons.Right:   // 줌 초기화
 | |
|                                                                 // if (Message != null) Message("줌영역을 초기화합니다");
 | |
|                     Style.XV1 = Style.XV1o;
 | |
|                     Style.XV2 = Style.XV2o;
 | |
|                     Style.Y1 = Style.YV1o;
 | |
|                     Style.Y2 = Style.YV2o;
 | |
|                     Set_Refresh(); //전체화면용 데이터를 바로 사용하면된다)
 | |
| 
 | |
|                     Console.WriteLine("Mouse R Click : REFRESH");
 | |
|                     Refresh();
 | |
|                     //if(Message != null) Message("");
 | |
|                     break;
 | |
| 
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private void TrendCtrl_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(Mouseinfo.Position.X - ChartRect.Left, ChartRect); // +this.startview;
 | |
|             this.Mouseinfo.Volt = this._Style.Y2 - GetVoltfromY(Mouseinfo.Position.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;
 | |
|             }
 | |
| 
 | |
|             //사용자포인터위라면?
 | |
|             int idx = this.check_userpoint(e);
 | |
|             if (idx != -1)
 | |
|             {
 | |
|                 Mouseinfo.Cross = false;
 | |
|                 Mouseinfo.Hand = false;
 | |
|                 Mouseinfo.Drag = false;
 | |
|                 Mouseinfo.ChangePos = true;
 | |
|                 Mouseinfo.DragType = EDRAGTYPE.UC;
 | |
|             }
 | |
| 
 | |
|             //드래그중판단
 | |
|             if (Mouseinfo.Drag)
 | |
|             {
 | |
|                 switch (Mouseinfo.DragType)
 | |
|                 {
 | |
|                     case EDRAGTYPE.NONE:
 | |
|                         break;
 | |
|                     case EDRAGTYPE.UC:
 | |
|                         Single newx = (e.X);
 | |
|                         Int64 newtime = GetTimeFromX(newx - ChartRect.Left, ChartRect);
 | |
|                         if (Mouseinfo.DragIndex < uc.Count)
 | |
|                         {
 | |
|                             //데이터가 없는경우이다.
 | |
|                             this.uc[Mouseinfo.DragIndex].Newx = newx;
 | |
|                             this.uc[Mouseinfo.DragIndex].Time = newtime;
 | |
|                         }
 | |
|                         break;
 | |
|                     case EDRAGTYPE.ZOOM:
 | |
|                         this.UserZoom.Width = (int)(e.X - WindowRect.X - Mouseinfo.DragStart.X);
 | |
|                         if (Key_Control || Style.UseZoomY)   //컨트롤이 눌려져있다면 줌을 사용한다.
 | |
|                         {
 | |
|                             this.UserZoom.Height = (int)(e.Y - WindowRect.Y - Mouseinfo.DragStart.Y);
 | |
|                         }
 | |
|                         else
 | |
|                         {
 | |
|                             this.UserZoom.Height = (int)ChartRect.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; //양수라면 오른쪽으로 이동했다.
 | |
|                         TimeSpan termtime = DateTime.FromFileTime(GetTimeFromX(Mouseinfo.Position.X, ChartRect)) - DateTime.FromFileTime(GetTimeFromX(Mouseinfo.DragStart.X, ChartRect));
 | |
| 
 | |
| 
 | |
|                         Int64 NewSD = DateTime.FromFileTime(Style.XV1).AddSeconds(-1 * termtime.TotalSeconds).ToFileTime();// +  (int)mstime;
 | |
|                         Int64 NewED = DateTime.FromFileTime(Style.XV2o).AddSeconds(-1 * termtime.TotalSeconds).ToFileTime(); //endviewo + (int)mstime;
 | |
| 
 | |
|                         //해당 시간영역의 전체 데이터 영역에 들어있어야 이동이 가능하다
 | |
|                         if ((NewSD > Style.X1 && NewED < Style.X2))
 | |
|                         {
 | |
|                             Style.XV1 = NewSD;
 | |
|                             Style.XV2 = NewED;
 | |
| 
 | |
|                             //y축 사용시에만 설정되게한다.
 | |
|                             if (Key_Control || Style.UseZoomY)
 | |
|                             {
 | |
|                                 Single termy = Mouseinfo.Position.Y - Mouseinfo.DragStart.Y - ChartRect.Top;
 | |
|                                 Single termvolt = GetVoltfromY(termy, ChartRect);
 | |
|                                 Single mvolt = termvolt;
 | |
| 
 | |
|                                 Single SV = Style.YV1o + mvolt;
 | |
|                                 Single EV = Style.YV2o + mvolt;
 | |
| 
 | |
|                                 Style.YV1 = SV;
 | |
|                                 Style.YV2 = EV;
 | |
| 
 | |
| 
 | |
|                             }
 | |
|                             Mouseinfo.DragStart = Mouseinfo.Position; //현재위치부터 드래그가 다시되도록
 | |
|                             Set_Refresh();
 | |
|                         }
 | |
| 
 | |
| 
 | |
|                         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();
 | |
|         }
 | |
| 
 | |
| 
 | |
|         public void Graph_Left(int perc)
 | |
|         {
 | |
|             DateTime newStartview = DateTime.FromFileTime(this.Style.XV1);
 | |
|             DateTime newEndview = DateTime.FromFileTime(this.Style.XV2);
 | |
|             TimeSpan term = newEndview - newStartview;
 | |
|             DateTime NewStart = newStartview.AddMinutes(-1 * (term.TotalMinutes / perc));
 | |
|             DateTime NewEnd = newEndview.AddMinutes(-1 * (term.TotalMinutes / perc));
 | |
|             if (NewStart < DateTime.FromFileTime(Style.X1)) return;
 | |
|             this.Style.XV1 = NewStart.ToFileTime();
 | |
|             this.Style.XV2 = NewEnd.ToFileTime();
 | |
|             Set_Refresh();
 | |
|             Refresh();
 | |
|             Console.WriteLine("Graph : Graph_Left");
 | |
|         }
 | |
| 
 | |
|         public void Graph_Right(int perc)
 | |
|         {
 | |
|             DateTime newStartview = DateTime.FromFileTime(this.Style.XV1);
 | |
|             DateTime newEndview = DateTime.FromFileTime(this.Style.XV2);
 | |
|             TimeSpan term = newEndview - newStartview;
 | |
|             DateTime NewStart = newStartview.AddMinutes(term.TotalMinutes / perc);
 | |
|             DateTime NewEnd = newEndview.AddMinutes(term.TotalMinutes / perc);
 | |
|             if (NewEnd > DateTime.FromFileTime(Style.X2)) return;
 | |
|             this.Style.XV1 = NewStart.ToFileTime();
 | |
|             this.Style.XV2 = NewEnd.ToFileTime();
 | |
|             Set_Refresh();
 | |
|             Refresh();
 | |
|             Console.WriteLine("Graph : Graph_Right");
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 현재 그래프의 Y축 좌표영역을 10% 위로 이동합니다.
 | |
|         /// </summary>
 | |
|         public void Graph_Up()
 | |
|         {
 | |
|             Single v = (Style.YV2 - Style.YV1) / 10;
 | |
|             Style.YV2 -= v;
 | |
|             Style.YV1 -= v;
 | |
|             Set_Refresh();
 | |
|             Refresh();
 | |
|             Console.WriteLine("Graph : Graph_Up");
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 현재 그래프의 Y축 좌표영역을 10% 아래로 이동합니다.
 | |
|         /// </summary>
 | |
|         public void Graph_Down()
 | |
|         {
 | |
|             Single v = (Style.YV2 - Style.YV1) / 10;
 | |
|             Style.YV2 += v;
 | |
|             Style.YV1 += v;
 | |
|             Set_Refresh();
 | |
|             Refresh();
 | |
|             Console.WriteLine("Graph : Graph_Down");
 | |
|         }
 | |
| 
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 현재 그래프의 Y축 좌표영역을 10% 확대합니다.
 | |
|         /// </summary>
 | |
|         public void Graph_ZoomInY()
 | |
|         {
 | |
|             Single v = (Style.YV2 - Style.YV1) / 10;
 | |
|             Style.YV2 -= v;
 | |
|             Style.YV1 += v;
 | |
|             Set_Refresh();
 | |
|             Refresh();
 | |
|             Console.WriteLine("Graph : Graph_ZoomInY");
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 현재 그래프의 Y축 좌표영역을 10% 축소합니다.
 | |
|         /// </summary>
 | |
|         public void Graph_ZommOutY()
 | |
|         {
 | |
|             Single v = (Style.YV2 - Style.YV1) / 10;
 | |
|             Style.YV2 += v;
 | |
|             Style.YV1 -= v;
 | |
|             Set_Refresh();
 | |
|             Refresh();
 | |
|             Console.WriteLine("Graph : Graph_ZommOutY");
 | |
|         }
 | |
| 
 | |
| 
 | |
|         public void ZoomIN()
 | |
|         {
 | |
|             DateTime newStartview = DateTime.FromFileTime(this.Style.XV1);
 | |
|             DateTime newEndview = DateTime.FromFileTime(this.Style.XV2);
 | |
|             TimeSpan term = newEndview - newStartview;
 | |
|             DateTime NewStart = newStartview.AddMinutes(term.TotalMinutes / 20);
 | |
|             DateTime NewEnd = newEndview.AddMinutes(-1 * (term.TotalMinutes / 20));
 | |
|             if (NewStart >= DateTime.FromFileTime(Style.X2).AddMinutes(-10)) NewStart = DateTime.FromFileTime(Style.X2).AddMinutes(-10);
 | |
|             if (NewEnd <= DateTime.FromFileTime(Style.X1).AddMinutes(10)) NewEnd = DateTime.FromFileTime(Style.X1).AddMinutes(10);
 | |
|             Style.XV1 = NewStart.ToFileTime();
 | |
|             this.Style.XV2 = NewEnd.ToFileTime();
 | |
|             Set_Refresh();
 | |
|             Refresh();
 | |
|             Console.WriteLine("Graph : ZoomIN");
 | |
|         }
 | |
| 
 | |
|         public void ZoomOUT()
 | |
|         {
 | |
|             DateTime newStartview = DateTime.FromFileTime(Style.XV1);
 | |
|             DateTime newEndview = DateTime.FromFileTime(Style.XV2);
 | |
|             TimeSpan term = newEndview - newStartview;
 | |
|             DateTime NewStart = newStartview.AddMinutes(-1 * (term.TotalMinutes / 20));
 | |
|             DateTime NewEnd = newEndview.AddMinutes(term.TotalMinutes / 20);
 | |
|             if (newStartview < DateTime.FromFileTime(Style.X1)) NewStart = DateTime.FromFileTime(Style.X1);
 | |
|             if (newEndview > DateTime.FromFileTime(Style.X2)) NewEnd = DateTime.FromFileTime(Style.X2);
 | |
|             Style.XV1 = NewStart.ToFileTime();
 | |
|             Style.XV2 = NewEnd.ToFileTime();
 | |
|             Set_Refresh();
 | |
|             Refresh();
 | |
|             Console.WriteLine("Graph : ZoomOUT");
 | |
|         }
 | |
| 
 | |
|         private void TrendCtrl_MouseWhell(object sender, MouseEventArgs e)
 | |
|         {
 | |
|             if (Key_Control)
 | |
|             {
 | |
|                 //온도축 변경(Y)
 | |
|                 Single news, newe;
 | |
| 
 | |
|                 news = Style.Y2;
 | |
|                 newe = Style.Y1;
 | |
| 
 | |
|                 Single TimerTerm = newe - news;
 | |
| 
 | |
|                 if (e.Delta > 0)
 | |
|                 {
 | |
|                     //확대                   
 | |
|                     news = news + (TimerTerm / 10);
 | |
|                     newe = newe + (-1 * (TimerTerm / 10));
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     //축소(down)
 | |
|                     news = news + (-1 * (TimerTerm / 10));
 | |
|                     newe = newe + (1 * (TimerTerm / 10));
 | |
|                 }
 | |
| 
 | |
|                 if (news > 400) news = 400;
 | |
|                 if (news < -200) news = -200;
 | |
| 
 | |
| 
 | |
|                 Style.Y2 = news;
 | |
|                 Style.Y1 = newe;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 //시간축 변경(X)
 | |
|                 DateTime news, newe;
 | |
| 
 | |
|                 news = DateTime.FromFileTime(Style.XV1);
 | |
|                 newe = DateTime.FromFileTime(Style.XV2);
 | |
| 
 | |
|                 TimeSpan TimerTerm = newe - news;
 | |
| 
 | |
|                 if (e.Delta > 0)
 | |
|                 {
 | |
|                     //확대
 | |
|                     if (TimerTerm.TotalSeconds < Style.MaxZoomX) return;
 | |
|                     news = news.AddSeconds(TimerTerm.TotalSeconds / 10);
 | |
|                     newe = newe.AddSeconds(-1 * (TimerTerm.TotalSeconds / 10));
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     //축소(down)
 | |
|                     news = news.AddSeconds(-1 * (TimerTerm.TotalSeconds / 10));
 | |
|                     newe = newe.AddSeconds(1 * (TimerTerm.TotalSeconds / 10));
 | |
|                 }
 | |
| 
 | |
|                 if (news > DateTime.FromFileTime(Style.X2)) news = DateTime.FromFileTime(Style.X2);
 | |
|                 if (news < DateTime.FromFileTime(Style.X1)) news = DateTime.FromFileTime(Style.X1);
 | |
|                 if (newe > DateTime.FromFileTime(Style.X2)) newe = DateTime.FromFileTime(Style.X2);
 | |
|                 if (newe < DateTime.FromFileTime(Style.X1)) newe = DateTime.FromFileTime(Style.X1);
 | |
| 
 | |
|                 if (news < DateTime.FromFileTime(Style.X1) || newe > DateTime.FromFileTime(Style.X2))
 | |
|                 {
 | |
|                     //MessageBox.Show("데이터가 없으므로 줌을 사용할 수 없습니다");                
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     Style.XV1 = news.ToFileTime();
 | |
|                     Style.XV2 = newe.ToFileTime();
 | |
|                     Style.XV1 = news.ToFileTime();
 | |
|                     Style.XV2o = newe.ToFileTime();
 | |
|                 }
 | |
| 
 | |
|             }
 | |
| 
 | |
|             this.Set_Refresh();
 | |
|             this.Refresh();
 | |
|             Console.WriteLine("Graph : Mouse Wheel");
 | |
|         }
 | |
| 
 | |
|         private void TrendCtrl_MouseUp(object sender, MouseEventArgs e)
 | |
|         {
 | |
|             Mouseinfo.Drag = false;
 | |
|             if (Mouseinfo.DragType == EDRAGTYPE.UC)
 | |
|             {
 | |
|                 Refresh_Grpah = true;   //다시값을 계산하려면 실행해야함
 | |
|                 this.Refresh();
 | |
|                 Console.WriteLine("Graph : MouseUp1");
 | |
| 
 | |
|                 if (OnUpdateUserCursor != null)
 | |
|                     OnUpdateUserCursor(Mouseinfo.DragIndex);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 if (UserZoom.Width != 0 && e.Button == System.Windows.Forms.MouseButtons.Left) //줌영역이 있다면 줌을 활성화한다.
 | |
|                 {
 | |
|                     int x1, x2, y1, y2;
 | |
| 
 | |
|                     x1 = UserZoom.Left;
 | |
|                     x2 = UserZoom.Left + UserZoom.Width;
 | |
| 
 | |
|                     if (!Style.UseZoomY)
 | |
|                     {
 | |
|                         y1 = (int)ChartRect.Top;
 | |
|                         y2 = (int)ChartRect.Bottom;
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         y1 = UserZoom.Top;
 | |
|                         y2 = UserZoom.Bottom;
 | |
|                     }
 | |
| 
 | |
| 
 | |
|                     Int64 startx = GetTimeFromX(x1 - ChartRect.Left, ChartRect);
 | |
|                     Int64 endx = GetTimeFromX(x2 - ChartRect.Left, ChartRect);
 | |
| 
 | |
|                     Single endy = Style.Y2 - GetVoltfromY(y1 - ChartRect.Top, ChartRect);
 | |
|                     Single starty = Style.Y2 - GetVoltfromY(y2 - ChartRect.Top, ChartRect);
 | |
| 
 | |
|                     if (endx < startx)  //교환
 | |
|                     {
 | |
|                         Int64 t = startx;
 | |
|                         startx = endx;
 | |
|                         endx = t;
 | |
|                     }
 | |
| 
 | |
|                     if (endy < starty)  //교환
 | |
|                     {
 | |
|                         Single t = starty;
 | |
|                         starty = endy;
 | |
|                         endy = t;
 | |
|                     }
 | |
| 
 | |
|                     TimeSpan tst = DateTime.FromFileTime(endx) - DateTime.FromFileTime(startx);
 | |
|                     Single VoltTerm = endy - starty;
 | |
|                     if (tst.TotalSeconds >= Style.MaxZoomX && VoltTerm >= Style.MaxZoomY && UserZoom.Width > 20) //보기영역이 5초는 넘어야 줌이 가능한다.
 | |
|                     {
 | |
|                         this.Style.XV1 = startx;
 | |
|                         this.Style.XV2 = endx;
 | |
| 
 | |
|                         this.Style.YV1 = starty;// +this.Style.최소값;
 | |
|                         this.Style.YV2 = endy;// +this.Style.최대값;
 | |
| 
 | |
|                         UserZoom.Width = 0;
 | |
|                         Set_Refresh();
 | |
|                         this.Refresh();
 | |
|                         Console.WriteLine("Graph : MouseUp2");
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         UserZoom.Width = 0;
 | |
|                         Set_Refresh();
 | |
|                         this.Refresh();
 | |
|                         Console.WriteLine("Graph : MouseUp3");
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         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 = "";
 | |
|             //        }
 | |
|             //    }
 | |
| 
 | |
|             //    Refresh_Grpah = true;   //다시갱신해야 값이 계산됨
 | |
|             //    this.Refresh();
 | |
| 
 | |
|             //    if(OnUpdateUserCursor != null)
 | |
|             //        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));
 | |
| 
 | |
|             //        Refresh_Grpah = true;   //다시갱신해야 값이 계산됨
 | |
|             //        this.Refresh();
 | |
| 
 | |
|             //        if (OnUpdateUserCursor != null)
 | |
|             //            OnUpdateUserCursor(this.uc.Count);
 | |
|             //    }
 | |
| 
 | |
|             //}
 | |
| 
 | |
|         }
 | |
| 
 | |
| 
 | |
|         private void DispCtrl_Load(object sender, EventArgs e)
 | |
|         {
 | |
| 
 | |
|         }
 | |
| 
 | |
| 
 | |
| 
 | |
|     }       //end class
 | |
| 
 | |
| }   //end namespace | 
