using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; using COMM; using System.Diagnostics; namespace Project { /// /// 2017-04-13 13:26:00 : 라벨이므로 커서 IN 시 Hand 에서 Default로 변경함 /// public partial class CtlAuto : Control { #region "Enum & Structure" public enum eColorTheme : byte { DaeHyun = 0, eGrayBlue, eDarkBlue, TopMenu, GrayButton, GrayTitleBar, IOStatus, IOStatusDepp, BlackButton, RedButton, GrayOmokButton, Stepbar, RobotStatus, NewGray_Group, NewGray_BG, NewGray_Button, NewBlue_Button, Custom, } #endregion public arDev.BMS dev_bms { private get; set; } = null; public arDev.FakePLC dev_plc { private get; set; } = null; public arDev.Narumi dev_agv { private get; set; } = null; public Device.Xbee dev_xbe { private get; set; } = null; public event EventHandler ItemClick; private Font _font_bms_vlt = new Font("Consolas", 50, FontStyle.Bold); private Font _font_bms_lev = new Font("Consolas", 150, FontStyle.Bold); private Font _font_main_batlev = new Font("Consolas", 50, FontStyle.Bold); public Font Font_MAIN_BMSLevel { get { return _font_main_batlev; } set { _font_main_batlev = value; Invalidate(); } } public Font Font_BMS_Volt { get { return _font_bms_vlt; } set { _font_bms_vlt = value; Invalidate(); } } public Font Font_BMS_Level { get { return _font_bms_lev; } set { _font_bms_lev = value; Invalidate(); } } public enum eScean { Normal = 0, Progress, } public eScean Scean { get; set; } = eScean.Normal; //public new event EventHandler Click; public string StatusMessage { get; set; } = string.Empty; public CtlAuto() { InitializeComponent(); // Set Optimized Double Buffer to reduce flickering this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); // Redraw when resized this.SetStyle(ControlStyles.ResizeRedraw, true); this.MouseDown += arButton_MouseDown; this.MouseUp += arButton_MouseUp; this.MouseEnter += arButton_MouseEnter; this.MouseLeave += arButton_MouseLeave; this.Resize += arLabel_Resize; base.BackColor = Color.FromArgb(32, 32, 32); ForeColor = Color.White; } ~CtlAuto() { this.MouseDown -= arButton_MouseDown; this.MouseUp -= arButton_MouseUp; this.MouseEnter -= arButton_MouseEnter; this.MouseLeave -= arButton_MouseLeave; this.Resize -= arLabel_Resize; } public void PerformClick() { if (Enabled == false) return; //171126 this.InvokeOnClick(this, new EventArgs()); } void arLabel_Resize(object sender, EventArgs e) { if (this.MinimumSize.Width == 0 || this.MinimumSize.Height == 0) this.MinimumSize = new Size(100, 30); //bRemakeRect = true; Invalidate(); } public new Padding Padding { get { return base.Padding; } set { base.Padding = value; this.Invalidate(); } } public Color BorderColor { get; set; } private int _itemgap = 0; public int ItemGap { get { return _itemgap; } set { _itemgap = value; Invalidate(); } } //Boolean bRemakeRect = true; public item[] Items { get; set; } public StateMachine.ERunStep runStep = StateMachine.ERunStep.READY; public Boolean OnUpdateMode = false; public Boolean Status_AutoRun { get { if (COMM.VAR.BOOL == null) return true; else return COMM.VAR.BOOL[eVarBool.FLAG_AUTORUN]; } } public DateTime StopTime { get; set; } private string stopmessage = ""; public string StopMessage { get { return stopmessage; } set { this.stopmessage = value; this.Invalidate(); } } System.Diagnostics.Stopwatch wframe = new System.Diagnostics.Stopwatch(); Point centerpt; protected override void OnPaint(PaintEventArgs e) { //Set Optimized Double Buffer to reduce flickering e.Graphics.CompositingQuality = CompositingQuality.HighQuality; e.Graphics.InterpolationMode = InterpolationMode.High; e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; if (wframe.IsRunning == false) wframe.Restart(); if (this.Scean == eScean.Normal) { var chargeM = VAR.BOOL?.Get(eVarBool.FLAG_CHARGEONM) ?? false; var chargeA = dev_agv?.system1.Battery_charging ?? false; var charge = chargeM || chargeA; //if (DesignMode) charge = true; if (charge) { Scean_Normal_Charge(e.Graphics, (chargeM ? "수동" : "자동")); } else { Scean_Normal(e.Graphics); } } else if (this.Scean == eScean.Progress) Scean_Progress(e.Graphics); //버젼표시 var version = VAR.STR?.Get(eVarString.SWVersion) ?? string.Empty; if (DesignMode) version = "1.1.1.1"; using (var f = new Font("Consolas", 8)) e.Graphics.DrawString(version, f, Brushes.Gray, DisplayRectangle, sfBottomRight); } StringFormat sfEnd = new StringFormat { Alignment = StringAlignment.Far, LineAlignment = StringAlignment.Center }; StringFormat sfStart = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center }; StringFormat sfCenter = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; StringFormat sfBottom = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Far }; StringFormat sfBottomRight = new StringFormat { Alignment = StringAlignment.Far, LineAlignment = StringAlignment.Far }; StringFormat sfBottomLeft = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Far }; public float ProgressMax { get; set; } = 100; public float ProgressVal { get; set; } = 0; Matrix TranslationTransform = new Matrix(); Matrix RotateTransform = new Matrix(); void Scean_Progress(Graphics g) { var progheight = DisplayRectangle.Height * 0.1f; var r = new RectangleF(DisplayRectangle.Left + 50, DisplayRectangle.Bottom - progheight - (DisplayRectangle.Height * 0.2f), DisplayRectangle.Width - 100, progheight); var rt = new RectangleF( r.Left, DisplayRectangle.Top, r.Width, r.Top - DisplayRectangle.Height * 0.05f); //g.DrawRectangle(Pens.Blue, rt.Left, rt.Top, rt.Width, rt.Height); g.DrawString(this.StatusMessage, this.Font, Brushes.White, rt, sfBottom); var progw = r.Width * (this.ProgressVal / this.ProgressMax); var progr = new RectangleF(r.Left, r.Top, progw, r.Height); g.FillRectangle(new LinearGradientBrush(r, Color.LightSkyBlue, Color.DeepSkyBlue, LinearGradientMode.Vertical), progr); g.DrawRectangle(Pens.DimGray, r.Left, r.Top, r.Width, r.Height); } int textdir = -1; void Scean_Normal_Charge(Graphics g, string mode) { var bmsready = dev_bms?.IsValid ?? false;// != null; if (DesignMode) bmsready = true; if (bmsready == false) { var pts = new List(); pts.Add(new Point(0, 0)); pts.Add(new Point(80, 0)); pts.Add(new Point(0, 80)); using (var f = new Font("Consolas", 110, FontStyle.Bold)) g.DrawString("BMS NOT CONNECTED", f, Brushes.Gold, this.DisplayRectangle, this.sfCenter); g.FillPolygon(Brushes.Gold, pts.ToArray()); pts.Clear(); pts.Add(new Point(0, 0)); pts.Add(new Point(30, 0)); pts.Add(new Point(0, 30)); g.FillPolygon(Brushes.Orange, pts.ToArray()); } else { //단순 수치값을 크게 표시히낟. var Volt = dev_bms?.Current_Volt ?? 25.35f; var Lev = dev_bms?.Current_Level ?? 80.1f; var textColor = Color.Lime; if (Lev < 30) textColor = Color.Red; else if (Lev < 40) textColor = Color.Tomato; else if (Lev < 60) textColor = Color.Orange; else if (Lev < 80) textColor = Color.Gold; using (var textbrush = new SolidBrush(textColor)) g.DrawString($"{Lev:N1}%", this.Font_BMS_Level, textbrush, DisplayRectangle, sfCenter); g.DrawString($"{Volt:N1}v", this.Font_BMS_Volt, Brushes.Gold, DisplayRectangle, sfBottomRight); var r = new RectangleF(DisplayRectangle.Left, DisplayRectangle.Top, DisplayRectangle.Width, 25); //msg = wframe.ElapsedMilliseconds.ToString() + msg; var msgc = mode.Equals("수동") ? Color.Gray : Color.Gray; using (var f = new Font("맑은 고딕", 11, FontStyle.Regular)) using (var sb = new SolidBrush(msgc)) { var msg = mode.Equals("수동") ? "수동 충전 중입니다 / 해제 하려면 케이블을 제거하고 [충전취소] 버튼을 누르세요" : "자동 충전 중 입니다 / 최대 충전량에 도달 하거나 (CALL)이 발생하면 자동 해제 됩니다"; var textsize = g.MeasureString(msg, f); //msg = textsize.Width.ToString() + "_" + TranslationTransform.OffsetX.ToString() + ":" + msg; //var minx = DisplayRectangle.Width - textsize.Width //화면이 넘어갔다면 다시 오른쪽으로 간다 if (textdir < 0 && TranslationTransform.OffsetX < (textsize.Width - DisplayRectangle.Width)) textdir *= -1; else if (textdir > 0 && TranslationTransform.OffsetX >= 0) textdir *= -1; //g.FillRectangle(Brushes.BlanchedAlmond, r.Left, r.Top, r.Width, r.Height); TranslationTransform.Translate(textdir * (wframe.ElapsedMilliseconds / 10f), 0); wframe.Restart(); g.Transform = TranslationTransform; g.DrawString(msg, f, sb, r, sfEnd); } //TranslationTransform.Reset(); } } void Scean_Normal(Graphics g) { // if (Status_AutoRun) // g.FillRectangle(new SolidBrush(Color.FromArgb(40, 40, 40)), this.DisplayRectangle); //else g.FillRectangle(new SolidBrush(Color.FromArgb(32, 32, 32)), this.DisplayRectangle); var wheelSize = new Size((int)(DisplayRectangle.Width * 0.35), (int)(DisplayRectangle.Width * 0.35)); bool agv_run = true; if (dev_agv != null) agv_run = dev_agv.system1.agv_run; Color wheelbackL = agv_run ? Color.DeepSkyBlue : Color.DimGray; Color wheelBorder = Color.Gold; if (dev_agv != null) { if (dev_agv.data.Speed == 'H') wheelBorder = Color.Red; else if (dev_agv.data.Speed == 'M') wheelBorder = Color.Gold; else if (dev_agv.data.Speed == 'L') wheelBorder = Color.Black; else if (dev_agv.data.Speed == 'S') wheelBorder = Color.Magenta; } var wheelspace = 0; var wheelborder = 8; //충전중 아이콘 추가 //var charge = VAR.BOOL?.Get(eVarBool.FLAG_CHARGEONA) ?? false; ////charge = true; //if (charge) //{ // var x = DisplayRectangle.Right - Properties.Resources.ChargeH.Width - 20; // var y = -30; // g.DrawImage(Properties.Resources.ChargeH, x, y); //} //왼쪽오른쪽 분리해서 좌측에는 주행정보를 우측에는 배터리 정보를 표시한다 //left wheeel centerpt = new Point( (int)(DisplayRectangle.Width / 2.0), (int)(DisplayRectangle.Height / 2.0)); var rectL = new Rectangle(DisplayRectangle.Left, DisplayRectangle.Top, (int)(DisplayRectangle.Width / 2f), DisplayRectangle.Height); var rectR = new Rectangle(rectL.Right, DisplayRectangle.Top, (int)(DisplayRectangle.Width / 2f), DisplayRectangle.Height); wheelSize = new Size((int)(rectL.Width * 0.7f), (int)(rectL.Width * 0.7f)); var rect_lwheel = new Rectangle( (int)(rectL.Left + (rectL.Width - wheelSize.Width) / 2f), (int)(rectL.Top + (rectL.Height - wheelSize.Height) / 2f), wheelSize.Width, wheelSize.Height); g.FillEllipse(new SolidBrush(Color.FromArgb(200, wheelbackL)), rect_lwheel); g.DrawEllipse(new Pen(Color.Black, wheelborder), rect_lwheel.AddOffset(1, 1)); g.DrawEllipse(new Pen(wheelBorder, wheelborder), rect_lwheel); //g.DrawRectangle(Pens.Red, rectL); //g.DrawRectangle(Pens.Blue, rectR); //wheel speed text string speedchar = "마크\n멈춤"; if (dev_bms != null) { //speedchar = dev_bms.Current_Level.ToString("N0"); if (dev_agv.data.Speed == 'H') speedchar = "고속"; else if (dev_agv.data.Speed == 'L') speedchar = "저속"; else if (dev_agv.data.Speed == 'M') speedchar = "중속"; else if (dev_agv.data.Speed == 'S') speedchar = "마크\n멈춤"; else speedchar = dev_agv.data.Speed.ToString(); } //g.FillRectangle(Brushes.BlanchedAlmond, r.Left, r.Top, r.Width, r.Height); var degree = 10;// wframe.ElapsedMilliseconds / 10f; //var angle = (float)(degree * Math.PI / 180f); if (RotateTransform.OffsetX == 0) { RotateTransform.Translate(DisplayRectangle.Width / 2f, DisplayRectangle.Height / 2f); } g.Transform = RotateTransform; //g.FillEllipse(Brushes.Magenta, new Rectangle(-5, -5, 10, 10)); RotateTransform.Reset(); g.Transform = RotateTransform; //speedchar = "100"; using (Font f = new Font("맑은 고딕", 70, FontStyle.Bold)) g.DrawString(speedchar, f, Brushes.Black, rect_lwheel, sfCenter); //배터리모양표시 List batpts = new List(); var batw = (int)(rectR.Width * 0.6f); var bath = (int)(rectR.Height * 0.7f); var ptLT = new PointF(rectR.Left + (rectR.Width - batw) / 2f, rectR.Top + ((rectR.Height - bath) / 2f) + (rectR.Height * 0.05f)); batpts.Add(ptLT); batpts.Add(new PointF(ptLT.X + batw, ptLT.Y)); batpts.Add(new PointF(ptLT.X + batw, ptLT.Y + bath)); batpts.Add(new PointF(ptLT.X, ptLT.Y + bath)); //g.DrawPolygon(Pens.Gold, batpts.ToArray()); var bmslevel = 28f; if (dev_bms != null) bmslevel = dev_bms.Current_Level; var CornerRadius = 10; var XPosition = rectR.Left + (rectR.Width - batw) / 2f; var YPosition = rectR.Top + (rectR.Height - bath) / 2f + (rectR.Height * 0.05f); var batrect = new RectangleF(XPosition, YPosition, batw, bath); var bathatsizeH = 30; Color bmsback = Color.Lime; if (bmslevel < 30) bmsback = Color.Red; else if (bmslevel < 40) bmsback = Color.Tomato; else if (bmslevel < 70) bmsback = Color.Gold; using (GraphicsPath Path = new GraphicsPath()) { Path.AddLine(XPosition + CornerRadius, YPosition, XPosition + batw / 2f - (batw * 0.1f), YPosition); Path.AddLine(XPosition + batw / 2f - (batw * 0.1f), YPosition, XPosition + batw / 2f - (batw * 0.1f), YPosition - bathatsizeH + CornerRadius); Path.AddLine(XPosition + batw / 2f - (batw * 0.1f) + CornerRadius, YPosition - bathatsizeH, XPosition + batw / 2f + (batw * 0.1f) - CornerRadius , YPosition - bathatsizeH); Path.AddLine(XPosition + batw / 2f + (batw * 0.1f), YPosition - bathatsizeH + CornerRadius, XPosition + batw / 2f + (batw * 0.1f), YPosition ); Path.AddLine(XPosition + batw / 2f - (batw * 0.1f), YPosition, XPosition + batw - (CornerRadius * 2), YPosition); Path.AddArc(XPosition + batw - (CornerRadius * 2), YPosition, CornerRadius * 2, CornerRadius * 2, 270, 90); Path.AddLine(XPosition + batw, YPosition + CornerRadius, XPosition + batw, YPosition + bath - (CornerRadius * 2)); Path.AddArc(XPosition + batw - (CornerRadius * 2), YPosition + bath - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 0, 90); Path.AddLine(XPosition + batw - (CornerRadius * 2), YPosition + bath, XPosition + CornerRadius, YPosition + bath); Path.AddArc(XPosition, YPosition + bath - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 90, 90); Path.AddLine(XPosition, YPosition + bath - (CornerRadius * 2), XPosition, YPosition + CornerRadius); Path.AddArc(XPosition, YPosition, CornerRadius * 2, CornerRadius * 2, 180, 90); Path.CloseFigure(); var tRegion = new System.Drawing.Region(Path); var bmsh = (int)(bath * (bmslevel / 100f)); var gRegion = new Region(new RectangleF(XPosition, YPosition + bath - bmsh, batw, bmsh)); gRegion.Intersect(tRegion); g.DrawPath(new Pen(bmsback, 20), Path); g.FillRegion(Brushes.WhiteSmoke, tRegion); g.FillRegion(new SolidBrush(bmsback), gRegion); g.DrawString($"{bmslevel:N0}", Font_MAIN_BMSLevel, Brushes.Black, batrect, sfCenter); } this.DrawDirection(g, rect_lwheel, wheelborder); //경고메세지표시 DrawWarning(g); //전체테두리 g.DrawRectangle(new Pen(BorderColor), DisplayRectangle.Left, DisplayRectangle.Top, DisplayRectangle.Width - 1, DisplayRectangle.Height - 1); var nextstop = VAR.BOOL?.Get(eVarBool.NEXTSTOP_MARK) ?? false; //if (VAR.BOOL != null) nextstop = VAR.BOOL[eVarBool.NEXTSTOP_MARK]; //상태메세지표시 string stmsg = string.Empty; if (COMM.VAR.STR != null && COMM.VAR.STR[eVarString.StatusMessage].isEmpty() == false) stmsg = VAR.STR[eVarString.StatusMessage]; else stmsg = "STATUS MESSAGE DEMO"; if (nextstop) stmsg += "|MARK-STOP"; var MsgColor = Color.Lime; if (PUB.Result != null) MsgColor = PUB.Result.SMSG_ForeColor; using (SolidBrush sb = new SolidBrush(MsgColor)) using (Font f = new Font("맑은 고딕", 10, FontStyle.Bold)) g.DrawString(stmsg, f, sb, DisplayRectangle, new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Far, }); } readonly Font StopFont = new Font("맑은 고딕", 30, FontStyle.Bold); public class UIButton { public RectangleF rect { get; set; } public string title { get; set; } public string cmd { get; set; } public bool Visible { get; set; } } public List Buttons = new List(); public delegate void ButtonClickHandler(UIButton idx); public event ButtonClickHandler ButtonClick; void DrawWarning(Graphics g) { string warnmsg = string.Empty; string butcmd = string.Empty; if (dev_agv != null) { if (dev_agv.error.Emergency) warnmsg = "비상 정지"; else if (dev_agv.error.line_out_error) warnmsg = "LINE OUT"; else if (dev_agv.error.Overcurrent) warnmsg = "OVER CURRENT"; else if (dev_agv.system1.agv_run && dev_agv.system1.stop_by_front_detect) warnmsg = "전방 장애물"; } //if (DesignMode) //{ // warnmsg = "비.상.정.지"; // butcmd = "EMG"; //} if (warnmsg.isEmpty() && stopmessage.isEmpty() == false) warnmsg = stopmessage; if (warnmsg != "") { var but = this.Buttons.Where(t => t.title.Equals(warnmsg)).FirstOrDefault(); if (but == null) { but = new UIButton(); but.title = warnmsg; this.Buttons.Add(but); } but.cmd = butcmd; var w = this.Width * 0.9f; var h = this.Height * 0.4f; but.rect = new RectangleF( (float)((this.Width - w) / 2.0f), (float)((this.Height - h) / 2.0f), w, h); var rectt = new RectangleF(but.rect.Left, but.rect.Top, but.rect.Width, 10); var rectb = new RectangleF(but.rect.Left, but.rect.Bottom - 10, but.rect.Width, 10); g.FillRectangle(new SolidBrush(Color.FromArgb(200, Color.White)), but.rect); g.FillRectangle(new SolidBrush(Color.FromArgb(220, Color.Red)), rectt); g.FillRectangle(new SolidBrush(Color.FromArgb(220, Color.Red)), rectb); //var sf = new StringFormat //{ // LineAlignment = StringAlignment.Center, // Alignment = StringAlignment.Center //}; var sfsize = g.MeasureString(warnmsg, StopFont); var scx = (float)((but.rect.Width - sfsize.Width) / 2.0); var scy = (float)((but.rect.Height - sfsize.Height) / 2.0); g.DrawString(warnmsg, StopFont, Brushes.Black, but.rect.Left + scx + 1, but.rect.Top + scy + 1); g.DrawString(warnmsg, StopFont, Brushes.Red, but.rect.Left + scx, but.rect.Top + scy); g.DrawRectangle(new Pen(Color.FromArgb(250, Color.Black), 2), but.rect.Left, but.rect.Top, but.rect.Width, but.rect.Height); } else { //버튼을 모두 숨긴다. foreach (var but in Buttons) but.Visible = false; } } public int frame_direction = 1000 / 10; //초당 4프레임으로 표시한다 public long frame_direction_ms = 0; public int frame_direction_idx = 0; void DrawDirection(Graphics g, Rectangle rect, int wheelborder) { //위쪽에 방향지시등을 그린다. var dirterm = 15; var ditHeight = 50; var dirWidth = (int)(rect.Width / 5.5f); var rect_dirup = new Rectangle( (int)((rect.Left + rect.Width / 2.0) - (dirWidth / 2.0)), rect.Top - ditHeight - dirterm, dirWidth, (ditHeight - wheelborder)); var ptsUp = new Point[] { new Point( rect_dirup.Left, rect_dirup.Bottom), new Point( rect_dirup.Right, rect_dirup.Bottom), new Point( (int)(rect_dirup.Left+ rect_dirup.Width/2.0), rect_dirup.Top) }; bool dirup = true; if (dev_agv != null) dirup = dev_agv.data.Direction == 'B'; if (dirup == true) { g.FillPolygon(Brushes.Lime, ptsUp); } else g.FillPolygon(new SolidBrush(Color.FromArgb(28, 28, 28)), ptsUp); g.DrawPolygon(Pens.Black, ptsUp); //아래쪾에 방향지시등을 그린다 var rect_dirdn = new Rectangle( (int)((rect.Left + rect.Width / 2.0) - (dirWidth / 2.0)), rect.Bottom + wheelborder + 1 + dirterm, dirWidth, (ditHeight - wheelborder)); var ptDn = new Point[] { new Point( rect_dirdn.Left, rect_dirdn.Top), new Point( rect_dirdn.Right, rect_dirdn.Top), new Point( (int)(rect_dirdn.Left+ rect_dirdn.Width/2.0), rect_dirdn.Bottom) }; if (dirup == false) { g.FillPolygon(Brushes.Lime, ptDn); } else g.FillPolygon(new SolidBrush(Color.FromArgb(28, 28, 28)), ptDn); g.DrawPolygon(Pens.Black, ptDn); ////오른쪾에 방향지시등을 그린다 //var dirR = false; //var rect_dirr = new Rectangle( // (int)(rect.Right + dirterm), // (int)(rect.Top + (rect.Height / 2f)), // dirWidth, // (ditHeight - wheelborder)); //var ptR = new Point[] { // new Point( rect_dirr.Left, rect_dirr.Top), // new Point( rect_dirr.Right, rect_dirr.Top), // new Point( (int)(rect_dirr.Left+ rect_dirr.Width/2.0), rect_dirr.Bottom) //}; //if (dirR == false) //{ // g.FillPolygon(Brushes.Lime, ptR); //} //else g.FillPolygon(new SolidBrush(Color.FromArgb(28, 28, 28)), ptR); //g.DrawPolygon(Pens.Black, ptR); } public bool LimitLU { get { if (dev_plc == null) return true; return dev_plc.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_LU); } } public bool LimitLD { get { if (dev_plc == null) return false; return dev_plc.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_LD); } } public bool LimitRU { get { if (dev_plc == null) return false; return dev_plc.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_RU); } } public bool LimitRD { get { if (dev_plc == null) return true; return dev_plc.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_RD); } } void DrawMC(Graphics g) { var boxw = DisplayRectangle.Width * 0.5f; var r = new RectangleF( boxw - 80, DisplayRectangle.Top + 50, boxw, DisplayRectangle.Height - 20); //g.DrawRectangle(Pens.Red, r.Left, r.Top, r.Width, r.Height); var w = r.Width * 0.7f;// this.DisplayRectangle.Width * 0.45; var h = r.Height * 0.5f;// this.DisplayRectangle.Height * 0.75; var pt = new PointF(r.Left + r.Width / 2.0f, r.Top + r.Height / 2.0f); var rect = new RectangleF((float)(pt.X - w / 2.0f), (float)((pt.Y - h / 2.0f) + 20), (float)w, (float)h); //3d모형으로 엣지를 넣는다 // pt = new PointF(DisplayRectangle.Width / 2.1f, DisplayRectangle.Height / 1.5f); var sizeX = 150; // var sizeY = 100; var sizeZ = 150; var PtsFront = new PointF[] { new PointF(pt.X-sizeX,pt.Y-sizeZ / 2.0f), new PointF(pt.X+sizeX,pt.Y-sizeZ / 2.0f), new PointF(pt.X+sizeX,pt.Y+sizeZ / 2.0f), new PointF(pt.X-sizeX,pt.Y+sizeZ / 2.0f) }; var PtsTop = new PointF[] { new PointF(pt.X-sizeX,pt.Y-(sizeZ / 2.0f)), new PointF(pt.X+sizeX,pt.Y-(sizeZ / 2.0f)), new PointF(pt.X +sizeX + 75,pt.Y- sizeZ), new PointF(pt.X - (sizeX / 2.0f) ,pt.Y-sizeZ) }; var PtsBottom = new PointF[] { new PointF(pt.X-sizeX,sizeZ+pt.Y-(sizeZ / 2.0f)), new PointF(pt.X+sizeX,sizeZ+pt.Y-(sizeZ / 2.0f)), new PointF(pt.X +sizeX +75,sizeZ+pt.Y- sizeZ), new PointF(pt.X - (sizeX / 2.0f) ,sizeZ+pt.Y-sizeZ) }; var PtsBack = new PointF[] { new PointF( (sizeX / 2.0f)+pt.X-sizeX,pt.Y-sizeZ ), new PointF( (sizeX / 2.0f)+pt.X+sizeX,pt.Y-sizeZ ), new PointF( (sizeX / 2.0f)+pt.X+sizeX,pt.Y), new PointF( (sizeX / 2.0f)+pt.X-sizeX,pt.Y) }; var PtsRight = new PointF[] { new PointF( PtsFront[1].X, PtsFront[1].Y ), new PointF( PtsBack[1].X, PtsBack[1].Y ), new PointF( PtsBack[2].X, PtsBack[2].Y ), new PointF( PtsFront[2].X, PtsFront[2].Y ) }; var PtsLeft = new PointF[] { new PointF( PtsFront[0].X, PtsFront[0].Y ), new PointF( PtsBack[0].X, PtsBack[0].Y ), new PointF( PtsBack[3].X, PtsBack[3].Y ), new PointF( PtsFront[3].X, PtsFront[3].Y ) }; //foreach (var p in PtsBottom) //{ // var xx = p.X - 5; // var yy = p.Y - 5; // var ww = 10; // var hh = 10; // g.DrawEllipse(Pens.Red, xx, yy, ww, hh); //} //바닥면 출력 g.FillPolygon(new SolidBrush(Color.FromArgb(150, Color.White)), PtsBottom); g.DrawPolygon(Pens.Black, PtsBottom); //윗면 출력 g.FillPolygon(new SolidBrush(Color.FromArgb(50, Color.White)), PtsTop); ////뒷면먼저출력 g.FillPolygon(new SolidBrush(Color.FromArgb(50, Color.White)), PtsBack); ////우측출력 g.FillPolygon(new SolidBrush(Color.FromArgb(10, Color.White)), PtsRight); ////좌측출력 g.FillPolygon(new SolidBrush(Color.FromArgb(10, Color.White)), PtsLeft); //안전커버 뒷 var coverPadding = 10; var coverYOffset = -30; var coverLYOffset = 0; var coverRYOffset = 0; if (LimitRD == true) coverRYOffset = 20; else if (LimitRU == true) coverRYOffset = coverYOffset; if (LimitLD == true) coverLYOffset = 20; else if (LimitLU == true) coverLYOffset = coverYOffset; var PtsCoverBack = new PointF[] { new PointF( PtsBack[0].X+coverPadding, PtsBack[0].Y+coverLYOffset ), new PointF( PtsBack[1].X-coverPadding, PtsBack[1].Y+coverLYOffset ), new PointF( PtsBack[2].X-coverPadding, PtsBack[2].Y+coverLYOffset ), new PointF( PtsBack[3].X+coverPadding, PtsBack[3].Y+coverLYOffset ) }; var PtsCoverFront = new PointF[] { new PointF( PtsFront[0].X+coverPadding, PtsFront[0].Y+coverRYOffset ), new PointF( PtsFront[1].X-coverPadding, PtsFront[1].Y+coverRYOffset ), new PointF( PtsFront[2].X-coverPadding, PtsFront[2].Y+coverRYOffset ), new PointF( PtsFront[3].X+coverPadding, PtsFront[3].Y+coverRYOffset ) }; if (LimitLU == true) { g.FillPolygon(new SolidBrush(Color.FromArgb(100, Color.Red)), PtsCoverBack); g.DrawPolygon(new Pen(Color.DarkRed, 2), PtsCoverBack); } else if (LimitLD == true) { g.FillPolygon(new SolidBrush(Color.FromArgb(100, Color.Blue)), PtsCoverBack); g.DrawPolygon(new Pen(Color.DarkBlue, 2), PtsCoverBack); } else { g.FillPolygon(new SolidBrush(Color.FromArgb(100, Color.Gray)), PtsCoverBack); g.DrawPolygon(Pens.DimGray, PtsCoverBack); } //g.DrawPolygon(Pens.Orange, PtsCoverBack); g.FillPolygon(new SolidBrush(Color.FromArgb(50, Color.White)), PtsFront); // g.DrawPolygon(Pens.Black, PtsFront); if (LimitRU == true) { g.FillPolygon(new SolidBrush(Color.FromArgb(150, Color.Red)), PtsCoverFront); g.DrawPolygon(new Pen(Color.DarkRed, 2), PtsCoverFront); } else if (LimitRD == true) { g.FillPolygon(new SolidBrush(Color.FromArgb(150, Color.Blue)), PtsCoverFront); g.DrawPolygon(new Pen(Color.DarkBlue, 2), PtsCoverFront); } else { g.FillPolygon(new SolidBrush(Color.FromArgb(150, Color.Gray)), PtsCoverFront); g.DrawPolygon(Pens.DimGray, PtsCoverFront); } //중앙포인트 g.FillEllipse(Brushes.White, pt.X - 2, pt.Y - 2, 4f, 4f); ////button - start //var buttonSize = 15; //var offset = 10; //g.FillEllipse(Brushes.Red, offset * 2.7f + PtsTop[0].X - buttonSize / 2.0f, -offset + PtsTop[0].Y - buttonSize / 2.0f, buttonSize, buttonSize); //g.DrawEllipse(Pens.Black, offset * 2.7f + PtsTop[0].X - buttonSize / 2.0f, -offset + PtsTop[0].Y - buttonSize / 2.0f, buttonSize, buttonSize); //g.FillEllipse(Brushes.Blue, offset * 4.2f + PtsTop[0].X - buttonSize / 2.0f, -offset*2.5f + PtsTop[0].Y - buttonSize / 2.0f, buttonSize, buttonSize); //g.DrawEllipse(Pens.Black, offset * 4.2f + PtsTop[0].X - buttonSize / 2.0f, -offset * 2.5f + PtsTop[0].Y - buttonSize / 2.0f, buttonSize, buttonSize); //g.FillEllipse(Brushes.Green, offset * 5.5f + PtsTop[0].X - buttonSize / 2.0f, -offset * 4.0f + PtsTop[0].Y - buttonSize / 2.0f, buttonSize, buttonSize); //g.DrawEllipse(Pens.Black, offset * 5.5f + PtsTop[0].X - buttonSize / 2.0f, -offset * 4.0f + PtsTop[0].Y - buttonSize / 2.0f, buttonSize, buttonSize); } //void DrawBattery(Graphics g) //{ // //우측 끝에 세로로 표시한다 // int r = 10; // int w = 25; // int y = 10; // Rectangle rect = new Rectangle(DisplayRectangle.Right - w - r, y, w, DisplayRectangle.Height - (y * 2)); // var ph = (this.ChargeLevel / 100.0) * rect.Height; // Rectangle rectp = new Rectangle(rect.Left, (int)(rect.Top + rect.Height - ph), rect.Width, (int)ph); // Color pColor = Color.Gold; // if (ChargeLevel <= 40) pColor = Color.Tomato; // else if (ChargeLevel >= 80) pColor = Color.Lime; // if (rectp.Height > 1) // { // using (LinearGradientBrush b = new LinearGradientBrush(rectp, pColor, Color.FromArgb(150, 150, 150), LinearGradientMode.Vertical)) // g.FillRectangle(b, rectp); // } // //for (int i = 1; i < 10; i++) // //{ // // var ly = (int)( rect.Height * ((i*1.0) / 10.0) ); // // g.DrawLine(Pens.Gray, rect.Left, rect.Top + ly, rect.Right, rect.Top + ly); // // g.DrawString((10-i).ToString(), this.Font, Brushes.Gray, rect.Left+5, ly+5); // //} // //전체테두리 // using (Pen p = new Pen(Color.FromArgb(100, Color.Black))) // g.DrawRectangle(p, rect); //} public class item { public bool Enable_Direction { get; set; } public Color BackColor1 { get; set; } public Color BackColor2 { get; set; } public Color ForeColor { get; set; } public Color ShadowColor { get; set; } public Color BorderColor { get; set; } public Color RightColor { get; set; } public Color LeftColor { get; set; } [Browsable(false)] public Rectangle fullrect { get; set; } [Browsable(false)] public Rectangle leftrect { get; set; } [Browsable(false)] public Rectangle rightrect { get; set; } public item() { BorderColor = Color.FromArgb(100, 100, 100); fullrect = Rectangle.Empty; leftrect = Rectangle.Empty; rightrect = Rectangle.Empty; BackColor1 = Color.White; BackColor2 = Color.Transparent; ForeColor = Color.DimGray; ShadowColor = Color.Black; Enable_Direction = true; } public string Title { get; set; } public void Draw(Graphics g, Font font, StringFormat sf) { Pen pen_border = null; LinearGradientBrush br_back = null; SolidBrush br_text = null; //펜 if (pen_border == null) pen_border = new Pen(this.BorderColor); else pen_border.Color = this.BorderColor; //배경브러쉬 if (br_back == null) br_back = new LinearGradientBrush(this.fullrect, this.BackColor1, this.BackColor2, LinearGradientMode.Vertical); else { br_back.LinearColors[0] = this.BackColor1; br_back.LinearColors[1] = this.BackColor2; } //제목브러쉬 if (br_text == null) br_text = new SolidBrush(this.ForeColor); else br_text.Color = this.ForeColor; //배경표시 g.FillRectangle(br_back, this.fullrect); //제목표시 if (this.Title.isEmpty() == false) { if (this.ShadowColor != Color.Transparent && this.ShadowColor != this.ForeColor) { using (var brShadow = new SolidBrush(this.ShadowColor)) g.DrawString( this.Title, font, brShadow, new Rectangle( this.fullrect.Left + 1, this.fullrect.Top + 1, this.fullrect.Width, this.fullrect.Height), sf); } g.DrawString(this.Title, font, br_text, this.fullrect, sf); g.DrawString(this.Title, font, br_text, this.fullrect, sf); } //테두리표시 g.DrawRectangle(pen_border, this.fullrect); if (Enable_Direction) { //좌측테두리 if (this.leftrect.IsEmpty == false) { if (this.LeftColor != Color.Transparent) { using (SolidBrush sb = new SolidBrush(this.LeftColor)) g.FillRectangle(sb, this.leftrect); } g.DrawRectangle(pen_border, this.leftrect); } //우측테두리 if (this.rightrect.IsEmpty == false) { if (this.RightColor != Color.Transparent) { using (SolidBrush sb = new SolidBrush(this.RightColor)) g.FillRectangle(sb, this.rightrect); } g.DrawRectangle(pen_border, this.rightrect); } } if (pen_border != null) pen_border.Dispose(); if (br_back != null) br_back.Dispose(); if (br_text != null) br_text.Dispose(); } } public class ItemClickEventArgs : EventArgs { public item Item { get; set; } public ItemClickEventArgs(item item) { this.Item = item; } } void arButton_MouseLeave(object sender, EventArgs e) { //isMouseOver = false; this.Cursor = Cursors.Default; Invalidate(); } void arButton_MouseEnter(object sender, EventArgs e) { //isMouseOver = true; //this.Cursor = Cursors.Hand; Invalidate(); } void arButton_MouseUp(object sender, MouseEventArgs e) { if (!Enabled) { return; } // isMouseDown = false; Invalidate(); } void arButton_MouseDown(object sender, MouseEventArgs e) { if (Enabled == false || Enabled == false) return; // isMouseDown = true; //item fullrect 에서 클릭위치를 찾아야함 if (Items != null && Items.Length > 0) { //마우스위치가 아이템에 포함되어있다면 var focusItem = Items.Where(t => t.fullrect.Contains(e.Location)).FirstOrDefault(); if (focusItem != null) { ItemClick?.Invoke(this, new ItemClickEventArgs(focusItem)); } } if (Buttons.Any()) { //마우스위치가 아이템에 포함되어있다면 var focusItem = Buttons.Where(t => t.rect.Contains(e.Location)).FirstOrDefault(); if (focusItem != null) { //ItemClick?.Invoke(this, new ItemClickEventArgs(focusItem)); ButtonClick?.Invoke(focusItem); } } Invalidate(); } } }