using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Windows.Forms; using AR; namespace UIControl { public partial class HMI : System.Windows.Forms.Control { arDev.DIO.IDIO dio = null; arDev.MOT.IMotion mot = null; #region "Variable - Private" Timer tm; Boolean _ardebugmode = false; eScean _scean = eScean.Nomal; //기타 내부 변수 int AnimationStepConv = 30; //컨베어 이동 애니메이션 최대 값 //int AnimationStepPort = 9; //포트 이동 애니메이션 최대 값 Boolean bRemakeRect = true; //이값이 활성화되면 각 영역을 다시 그리게 된다 DateTime updatetime = DateTime.Now; //화면을 다시 그린 시간 Brush BRPortBg = new SolidBrush(Color.FromArgb(50, Color.DimGray)); Brush BRDetectDn = new SolidBrush(Color.FromArgb(50, Color.DimGray)); StringFormat sfCenter; StringFormat sfLeft = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center }; SolidBrush brVacOff = new SolidBrush(Color.FromArgb(150, Color.White)); SolidBrush brVacOn = new SolidBrush(Color.FromArgb(200, Color.Lime)); Font arFont_MotPosName { get; set; } Pen penVacOn = new Pen(Color.Red, 5); Pen penVacOff = new Pen(Color.Black, 5); //영역(큰 그림?) (bRemakeRect 에 의 해 생성된다) RectangleF rect_main = RectangleF.Empty; // RectangleF rect_frontShuttle = RectangleF.Empty; //RectangleF rect_rearShuttle = RectangleF.Empty; RectangleF rect_conveyor = RectangleF.Empty; RectangleF rect_picker = RectangleF.Empty; RectangleF rect_printl = RectangleF.Empty; RectangleF rect_printr = RectangleF.Empty; //영역(피커) RectangleF rect_picker_left = RectangleF.Empty; RectangleF rect_picker_front_vac1 = RectangleF.Empty; RectangleF rect_picker_front_vac2 = RectangleF.Empty; RectangleF rect_picker_front_vac3 = RectangleF.Empty; RectangleF rect_picker_front_vac4 = RectangleF.Empty; //X축 포트 (F-L:0, F-R:1, R-L:2, R-R:3 //RectangleF[] rect_port = new RectangleF[4]; RectangleF[] rect_zone = new RectangleF[11]; //CIcon[] icons = new CIcon[7]; List Buttons = new List(); List menuButtons = new List(); #endregion #region "Variable - Public" // public double[] arMotorPosition = new double[] { 0, 0, 0, 0, 0 }; public int ConveyorRunPoint = 1; //컨베어 모터 이동시 이동 화살표의 위치값(내부 타이머에의해 증가함) public double arMcLengthW = 1460; public double arMcLengthH = 1350;// public bool CVLeftBusy = false; public bool CVLeftReady = false; public bool CVRightBusy = false; public bool CVRightReady = false; #endregion RectangleF rect_vision = RectangleF.Empty; public string arVision_RID { get; set; } public string arVision_SID { get; set; } RectangleF rect_zlaxis = RectangleF.Empty;// new RectangleF((float)motZLPosX, (float)motZPosY, motZwPx, (float)motZhPx); public Boolean arVisionProcessL { get; set; } public Boolean arVisionProcessC { get; set; } public Boolean arVisionProcessR { get; set; } #region "Property" public int arCountV0 { get; set; } public int arCountV1 { get; set; } public int arCountV2 { get; set; } public int arCountPrint0 { get; set; } public int arCountPrint1 { get; set; } public Boolean arPortLItemOn { get; set; } public Boolean arPortRItemOn { get; set; } public Boolean arPLItemON { get; set; } public Boolean arPRItemON { get; set; } public Boolean arMagnet0 { get; set; } public Boolean arMagnet1 { get; set; } public Boolean arMagnet2 { get; set; } public Boolean arPickerSafeZone { get; set; } private Padding _padding = new Padding(0); public new Padding Padding { get { return _padding; } set { _padding = value; bRemakeRect = true; this.Invalidate(); } } /// /// 현재 메뉴가 표시되어있는가? /// public Boolean HasPopupMenu { get; private set; } /// /// 현재표시된 메뉴는 사용자의 입력을 반드시 받아야 하는가? /// public Boolean PopupMenuRequireInput { get; private set; } public Font arFont_PortMessage { get; set; } public eScean Scean { get { return _scean; } set { _scean = value; bRemakeRect = true; this.Invalidate(); } } //컨베이어에 설치된 자재 감지 센서 public Boolean[] arDI_Cv_Detect { get; set; } //컨베이어 입구 안전 센서 public Boolean arInitMOT { get; set; } public Boolean arJobEND { get; set; } public Boolean arLowDiskSpace { get; set; } //용량 부족 메세지 여부 public double arFreespace { get; set; } //남은 디스크 용량 비율 public Boolean arFGVision0RDY { get; set; } public Boolean arFGVision1RDY { get; set; } public Boolean arFGVision2RDY { get; set; } public Boolean arFGVision0END { get; set; } public Boolean arFGVision1END { get; set; } public Boolean arFGVision2END { get; set; } public Boolean arFGPrinter0RDY { get; set; } public Boolean arFGPrinter1RDY { get; set; } public Boolean arFGPrinter2RDY { get; set; } public Boolean arFGPrinter0END { get; set; } public Boolean arFGPrinter1END { get; set; } public Boolean arFGPrinter2END { get; set; } public Boolean arDI_SaftyOk { get; set; } public string arMotPosNamePX { get; set; } public string arMotPosNamePZ { get; set; } public string arMotPosNameLM { get; set; } public string arMotPosNameLZ { get; set; } public string arMotPosNameRM { get; set; } public string arMotPosNameRZ { get; set; } public Boolean arMotILockPKX { get; set; } public Boolean arMotILockPKZ { get; set; } public Boolean arMotILockPLM { get; set; } public Boolean arMotILockPLZ { get; set; } public Boolean arMotILockPRM { get; set; } public Boolean arMotILockPRZ { get; set; } public Boolean arMotILockPRL { get; set; } public Boolean arMotILockPRR { get; set; } public Boolean arMotILockVS0 { get; set; } public Boolean arMotILockVS1 { get; set; } public Boolean arMotILockVS2 { get; set; } public Boolean arMotILockCVL { get; set; } public Boolean arMotILockCVR { get; set; } public Boolean PrintLPICK { get; set; } public Boolean PrintRPICK { get; set; } public Boolean L_PICK_FW { get; set; } public Boolean L_PICK_BW { get; set; } public Boolean R_PICK_FW { get; set; } public Boolean R_PICK_BW { get; set; } public Boolean[] arMOT_LimUp = new bool[] { false, false, false, false, false, false, false }; public Boolean[] arMOT_LimDn = new bool[] { false, false, false, false, false, false, false }; public Boolean[] arMOT_Origin = new bool[] { false, false, false, false, false, false, false }; public Boolean[] arMOT_Alm = new bool[] { false, false, false, false, false, false, false }; public Boolean[] arMOT_HSet = new bool[] { false, false, false, false, false, false, false }; public Boolean[] arMOT_SVOn = new bool[] { false, false, false, false, false, false, false }; public Boolean arFlag_Minspace { get; set; } public byte arUnloaderSeq { get; set; } public Boolean arFlag_UnloaderBusy { get; set; } public Boolean arFlag_UnloaderErr { get; set; } public Boolean arConn_REM { get; set; } public Boolean arFG_RDY_YP_FPICKON { get; set; } public Boolean arFG_RDY_YP_FPICKOF { get; set; } public Boolean arFG_RDY_YP_RPICKON { get; set; } public Boolean arFG_RDY_YP_RPICKOF { get; set; } public Boolean arFG_CMD_YP_FPICKON { get; set; } //public Boolean arFG_CMD_YP_FPICKOF { get; set; } public Boolean arFG_CMD_YP_RPICKON { get; set; } //public Boolean arFG_CMD_YP_RPICKOF { get; set; } //비상정지 센서 상태 public Boolean arDI_Emergency { get; set; } public Boolean arDIAir { get; set; } public Boolean arConn_MOT { get; set; } public Boolean arConn_DIO { get; set; } public Boolean arAIRDetect { get; set; } public Boolean arConn_BCD { get; set; } public Boolean arConn_PLC { get; set; } public int arLastDetectIndex { get; set; } public Boolean arDebugMode { get { return _ardebugmode; } set { this._ardebugmode = value; Invalidate(); } } public CPort[] arVar_Port { get; set; } public CPicker[] arVar_Picker { get; set; } public Boolean arConvRun { get; set; } public Boolean arIsRunning { get; set; } private List zitem = new List(); public long[] zonetime = new long[11]; public Font arFont_count { get; set; } public Font arFont_picker { get; set; } public double arMotorLengthY { get; set; } public double arMotorLengthZL { get; set; } public double arMotorLengthZR { get; set; } private double[] _armotpos = new double[] { 0, 0, 0, 0, 0, 0, 0 }; public double[] arMotorPosition { get { return _armotpos; } set { _armotpos = value; } } private double[] _arhomepgoress = new double[] { 0, 0, 0, 0, 0, 0, 0 }; public double[] arHomeProgress { get { return _arhomepgoress; } set { _arhomepgoress = value; } } private CMenu[] _menus = null; public CMenu[] arMenus { get { return _menus; } set { _menus = value; this.Invalidate(); } } #endregion public Boolean PickerSafezone = false; public HMI() { // 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); this.SetStyle(ControlStyles.ContainerControl, false); this.SetStyle(ControlStyles.Selectable, true); // Redraw when resized this.SetStyle(ControlStyles.ResizeRedraw, true); this.Resize += Loader_Resize; sfCenter = new StringFormat(); sfCenter.Alignment = StringAlignment.Center; sfCenter.LineAlignment = StringAlignment.Center; tm = new Timer(); tm.Interval = 50; //10frame; tm.Tick += Tm_Tick; arLastDetectIndex = -1; arFont_PortMessage = new Font("Consolas", 11, FontStyle.Bold); arFont_picker = new Font("Arial", 10, FontStyle.Bold); arFont_MotPosName = new Font("Consolas", 10, FontStyle.Bold); arUnloaderSeq = 0; arMotorLengthY = 400; arMotorLengthZL = 580; arMotorLengthZR = 590; arDI_Cv_Detect = new bool[8]; for (int i = 0; i < arDI_Cv_Detect.Length; i++) arDI_Cv_Detect[i] = false; bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime); if (designMode == false) tm.Start(); arFont_count = new Font("Consolas", 30, FontStyle.Bold); //기본수량설정됨 arVar_Port = new CPort[3]; arVar_Picker = new CPicker[1]; for (int i = 0; i < rect_zone.Length; i++) rect_zone[i] = RectangleF.Empty; for (int i = 0; i < zonetime.Length; i++) zonetime[i] = 0; //미리 10개를 생성한다. 슬롯에 10개이상 생기기 않는다. zitem = new List(10); for (int i = 0; i < zitem.Count; i++) zitem[i] = new CItem(); } public void ClearMessage() { } private List lkitemsF = new List(); private List lkitemsR = new List(); #region "Common Data & Device" DateTime UpdateTime = DateTime.Now.AddSeconds(-1); //public void SetFLAG(arUtil.IInterLock dio_) //{ // this.flag = dio_; // this.flag.ValueChanged += Flag_ValueChanged; //} public void SetDIO(arDev.DIO.IDIO dio_) { this.dio = dio_; this.dio.IOValueChanged += Dio_IOValueChanged; } public void SetMOT(arDev.MOT.IMotion dio_) { this.mot = dio_; this.mot.HomeStatusChanged += Mot_HomeStatusChanged; this.mot.PositionChanged += Mot_PositionChanged; this.mot.StatusChanged += Mot_StatusChanged; } private void Dio_IOValueChanged(object sender, arDev.DIO.IOValueEventArgs e) { var ts = DateTime.Now - UpdateTime; if (ts.TotalMilliseconds < 500) return; else UpdateTime = DateTime.Now; this.Invalidate(); } private void Mot_StatusChanged(object sender, arDev.MOT.StatusChangeEventArags e) { var ts = DateTime.Now - UpdateTime; if (ts.TotalMilliseconds < 500) return; else UpdateTime = DateTime.Now; this.Invalidate(); } private void Mot_PositionChanged(object sender, arDev.MOT.PositionChangeEventArgs e) { var ts = DateTime.Now - UpdateTime; if (ts.TotalMilliseconds < 500) return; else UpdateTime = DateTime.Now; this.Invalidate(); } private void Mot_HomeStatusChanged(object sender, arDev.MOT.HomeStatusChangeEventArgs e) { var ts = DateTime.Now - UpdateTime; if (ts.TotalMilliseconds < 500) return; else UpdateTime = DateTime.Now; this.Invalidate(); } //private void Flag_ValueChanged(object sender, arUtil.InterfaceValueEventArgs e) //{ // var ts = DateTime.Now - UpdateTime; // if (ts.TotalMilliseconds < 500) return; // else UpdateTime = DateTime.Now; // this.Invalidate(); //} public Boolean MotionHome { get; set; } bool GetBOOL(eVarBool idx) { return VAR.BOOL?[(int)idx] ?? false; } string GetSTR(eVarString idx) { return VAR.STR?[(int)idx] ?? string.Empty; } bool GetDOValue(eDOName pin) { return dio?.GetDOValue((int)pin) ?? false; } bool GetDIValue(eDIName pin) { return dio?.GetDIValue((int)pin) ?? false; } #endregion public void ClearLockItem(int idx) { if (idx == 0) { lock (lkitemsF) lkitemsF.Clear(); } else { lock (lkitemsR) lkitemsR.Clear(); } } public void AddLockItem(int idx, params string[] values) { if (idx == 0) { lock (lkitemsF) { foreach (var value in values) { if (lkitemsF.Contains(value) == false) lkitemsF.Add(value); } } } else { lock (lkitemsR) { foreach (var value in values) { if (lkitemsR.Contains(value) == false) lkitemsR.Add(value); } } } } public void RemoveLockItem(int idx, params string[] values) { if (idx == 0) { lock (lkitemsF) { foreach (var value in values) { if (lkitemsF.Contains(value) == true) lkitemsF.Remove(value); } } } else { lock (lkitemsR) { foreach (var value in values) { if (lkitemsR.Contains(value) == true) lkitemsR.Remove(value); } } } } protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); //if (this.icons == null || icons.Length < 1) return; //var item = this.icons.Where(t => t.Rect.Contains(e.Location)).FirstOrDefault(); ////선택된 것이 잇다면 모두 해제를 해준다. //icons.Where(t => t.Focus == true).ToList().ForEach(t => t.Focus = false); //if (item != null) //{ // item.Focus = true; // this.Cursor = Cursors.Hand; //} //else //{ // this.Cursor = Cursors.Arrow; //} } public class ZoneItemClickEventargs : EventArgs { public CItem item { get; private set; } public ZoneItemClickEventargs(CItem item_) { this.item = item_; } } public class IconClickEventargs : EventArgs { public CIcon item { get; private set; } public IconClickEventargs(CIcon item_) { this.item = item_; } } public class MenuItemClickEventargs : EventArgs { public CMenuButton item { get; private set; } public MenuItemClickEventargs(CMenuButton item_) { this.item = item_; } } public event EventHandler ButtonClick; public event EventHandler IConClick; public event EventHandler ZoneItemClick; protected override void OnMouseClick(MouseEventArgs e) { base.OnMouseClick(e); if (e.Button == MouseButtons.Left) { //var item = this.icons.Where(t => t.Rect.Contains(e.Location)).FirstOrDefault(); //if (item != null) //{ // //다른 메뉴가 선택되어잇다면 동작하지 않게 한다. // if (IConClick != null) // IConClick(this, new IconClickEventargs(item)); //} var zitem = this.zitem.Where(t => t.Rect.Contains(e.Location)).FirstOrDefault(); if (zitem != null) { //특정 존의 아이템을 선택했다 if (ZoneItemClick != null) ZoneItemClick(this, new ZoneItemClickEventargs(zitem)); } //메뉴의해 생성된 버튼 var zbbut = this.menuButtons.Where(t => t.Rect.Contains(e.Location)).FirstOrDefault(); if (zbbut != null) { //특정 존의 아이템을 선택했다 if (ButtonClick != null) ButtonClick(this, new MenuItemClickEventargs(zbbut)); } //아이콘 var zbut = this.Buttons.Where(t => t.Rect.Contains(e.Location)).FirstOrDefault(); if (zbut != null) { //특정 존의 아이템을 선택했다 if (ButtonClick != null) ButtonClick(this, new MenuItemClickEventargs(zbut)); } } } void Loader_Resize(object sender, EventArgs e) { bRemakeRect = true; } public void RemakeRect() { bRemakeRect = true; } /// /// 각 영역을 현재 크기대비하여 재계산 한다 /// void makeRect_Normal() { rect_main = new RectangleF( DisplayRectangle.Left + Padding.Left, DisplayRectangle.Top + Padding.Top, DisplayRectangle.Width - Padding.Left - Padding.Right, DisplayRectangle.Height - Padding.Top - Padding.Bottom); //X축 모션(셔틀) 표시 var xPos1 = rect_main.Left + (rect_main.Width * 0.175); var xPos2 = rect_main.Right - xPos1; var yposR = rect_main.Height * 0.15; var yposF = rect_main.Height * 0.85; var h0p5 = rect_main.Height * 0.03; var w0p5 = (rect_main.Width * 0.035) * ((rect_main.Height * 1.0) / rect_main.Width); //var conv_height = rect_main.Height * 0.3; var cx = (float)(rect_main.Top + (rect_main.Width / 2.0)); var cy = (float)(rect_main.Top + (rect_main.Height / 2.0)); var conv_height = CvtMMtoPX_H(350, 0); //컨베이어 높이 var conv_width = CvtMMtoPX_W(arMcLengthW, 0); //컨베어이어너비는 장비 너비와 같다 rect_conveyor = new RectangleF(rect_main.Left, (float)(rect_main.Top + (rect_main.Height - conv_height) / 2.0f), (float)conv_width, (float)conv_height); var h10p = rect_main.Height * 0.03; //프론트셔틀의 영역(가동 영역) - 아래서 450mm 떨어진곳 var xAxisLengthMM = arMcLengthW - 200; // 컨베어 길이에서 좌우 100mm 씩 리밋센서가 있다 var xAxisLengthPX = CvtMMtoPX_W(xAxisLengthMM, rect_conveyor.Left); //rect_frontShuttle = new RectangleF( // (float)(CvtMMtoPX_W(100, rect_conveyor.Left)), // (float)(CvtMMtoPX_H(100, rect_main.Top)), // (float)xAxisLengthPX, // (float)(CvtMMtoPX_H(20, 0))); //세로축 총길이 1400mm Y축 모터는 양끝에 100mm 의 여유가 있으며, Y축 var pickWidth = rect_main.Width * 0.6f; var pickerX = rect_main.Width / 2.0f;// CvtMMtoPX_W(750, rect_conveyor.Left); var YAxisLenWMM = arMcLengthW - 100 * 2; var YAxisLenHMM = 100;// var yAxisLenWPx = CvtMMtoPX_W(YAxisLenWMM, 0); //너비 var yAxisLenHPx = CvtMMtoPX_H(YAxisLenHMM, 0); //길이 var yAxisX = CvtMMtoPX_W(100, rect_main.Left); var yAxisY = CvtMMtoPX_H(200, rect_main.Top); rect_picker = new RectangleF( (float)(yAxisX), (float)(yAxisY), (float)(yAxisLenWPx), (float)(yAxisLenHPx) ); rect_printl = new RectangleF(rect_main.Left + 30, rect_picker.Bottom + 30, 30, rect_main.Height * 0.25f); rect_printr = new RectangleF(rect_main.Right - rect_printl.Width - rect_printl.Left, rect_printl.Top, rect_printl.Width, rect_printl.Height); //Y축 피커 관련 세부 영역 설정 (VAC 와 원) //전체영역의 80% 영역에 Y-로봇의 축을 그린다. //var motorMax = 400; //전체 가동 길이 400mm RectangleF rect = rect_picker; var MotPosPx = rect.Left + rect.Width * (this.arMotorPosition[0] / (this.arMotorLengthY * 1.0f)); cx = rect.Left + rect.Width / 2.0f; //상(Rear), 하(Front)로 영역을 그린다 var port_height = rect.Height * 0.25f; var port_width = port_height; //;// var port_width = rect.Width * 3f; //port_width = port_height; var port_space = CvtMMtoPX_H(350 / 2.0f, 0); var port_spacex = CvtMMtoPX_W(10, 0); ; var PickerSizeW = CvtMMtoPX_W(150, 0);// (float)(Math.Max(CvtMMtoPX_W(150, 0), CvtMMtoPX_H(15, 0))); var PickerSizeH = PickerSizeW;// CvtMMtoPX_H(130, 0);//(float)(Math.Max(CvtMMtoPX_W(150, 0), CvtMMtoPX_H(15, 0))); var PickerSpaceW = CvtMMtoPX_H(100, 0); rect_picker_left = new RectangleF( (float)(MotPosPx - PickerSpaceW), (float)(rect.Top + 50), (float)PickerSizeW, (float)PickerSizeH); var pointoffset = 5; //진공표시영역 rect_picker_front_vac1 = new RectangleF( (float)rect_picker_left.Left + pointoffset, (float)rect_picker_left.Top + pointoffset, (float)rect_picker_left.Width * 0.2f, (float)rect_picker_left.Height * 0.2f); rect_picker_front_vac2 = new RectangleF( (float)rect_picker_left.Right - rect_picker_front_vac1.Width - pointoffset, (float)rect_picker_front_vac1.Top, (float)rect_picker_front_vac1.Width, (float)rect_picker_front_vac1.Height); rect_picker_front_vac3 = new RectangleF( (float)rect_picker_left.Left + pointoffset, (float)rect_picker_left.Bottom - rect_picker_front_vac1.Height - pointoffset, (float)rect_picker_front_vac1.Width, (float)rect_picker_front_vac1.Height); rect_picker_front_vac4 = new RectangleF( (float)rect_picker_left.Right - rect_picker_front_vac1.Width - pointoffset, (float)rect_picker_left.Bottom - rect_picker_front_vac1.Height - pointoffset, (float)rect_picker_front_vac1.Width, (float)rect_picker_front_vac1.Height); //각 존의 영역 확인 //컨베어의 릴감지센서 위치를 표시한다 var senseW = rect_conveyor.Width * 0.02f; var senseH = rect_conveyor.Height * 0.05f; var slist = new double[] { 20, 340, 550, 890, 1110, 1440 };// new double[] { 0.02, 0.25, 0.4, 0.6, 0.75, 0.9 }; //센서의 위치정보(컨베어좌측기준) //센서가 포함된 존의 영역을 생성한다 for (int i = 0; i < slist.Length; i++) { //선으로 영역을 표시해준다. var PosMM = rect_conveyor.Width * (slist[i] / arMcLengthW); var x = (float)(rect_conveyor.Left + PosMM); var rx = x - senseW / 2.0f; rect_zone[i * 2] = new RectangleF(rx, rect_conveyor.Top, senseW, rect_conveyor.Height); } var arraylis = new int[] { 1, 3, 5, 7, 9 }; var zterm = 4; for (int i = 0; i < arraylis.Length; i++) { var idx = arraylis[i]; rect_zone[idx] = new RectangleF( rect_zone[idx - 1].Right + zterm, rect_zone[idx - 1].Top, rect_zone[idx + 1].Left - rect_zone[idx - 1].Right - zterm * 2, rect_zone[idx - 1].Height); } //입출력포트의 영역을 다시 계산한다 var portW = (int)(rect_main.Width * 0.125f); var portH = (int)(rect_main.Height * 0.35f); var portPad = (int)(rect_main.Width / 7f); var MarginX = (int)((rect_main.Width - portW * 3 - portPad * 2) / 2.0); var MarginY = (int)(rect_main.Height - portH - (portPad / 2f)); for (int i = 0; i < arVar_Port.Length; i++) { arVar_Port[i].Rect = new Rectangle( (int)rect_main.Left + MarginX + (i * portW) + (i * portPad), (int)rect_main.Top + MarginY+50, portW, portH); zitem.Add(new CItem { Rect = arVar_Port[i].Rect.toRect(), index = i, Tag = $"PORT{i}", }); } } void makeRect_xmove() { rect_main = new RectangleF( DisplayRectangle.Left + DisplayRectangle.Width * 0.05f, DisplayRectangle.Top + DisplayRectangle.Height * 0.05f, DisplayRectangle.Width * 0.9f, DisplayRectangle.Height * 0.9f); //화면에 꽉차도록 전체 영역을 할당한다. var cx = rect_main.Left + rect_main.Width / 2.0f; var cy = rect_main.Top + rect_main.Height / 2.0f; var padding = (int)(rect_main.Width * 0.03); var width = (int)((cx - rect_main.Left) - padding * 2); var height = (int)((cy - rect_main.Top) - padding * 2); arVar_Port[0].Rect = new Rectangle( (int)rect_main.Left + padding, (int)cy + padding, width, height); arVar_Port[1].Rect = new Rectangle( (int)cx + padding, (int)cy + padding, width, height); arVar_Port[2].Rect = new Rectangle( (int)(rect_main.Left + (rect_main.Width - width) / 2f), (int)rect_main.Top + padding, width, height); } void makeRect_MotHome() { rect_main = new RectangleF( DisplayRectangle.Left + DisplayRectangle.Width * 0.05f, DisplayRectangle.Top + DisplayRectangle.Height * 0.05f, DisplayRectangle.Width * 0.9f, DisplayRectangle.Height * 0.9f); } double CvtMMtoPX_W(double PosMM, double startPos) { //컨베어 기준으로 값을 반환한ㄷ. return startPos + rect_main.Width * (PosMM / arMcLengthW); } double CvtMMtoPX_H(double PosMM, double startPos) { //컨베어 기준으로 값을 반환한ㄷ. return startPos + rect_main.Height * (PosMM / arMcLengthH); } #region "Menu Method" public void ClearMenu() { _menus = null; this.Invalidate(); } public void AddMenu(CMenu menu) { var curCnt = 0; if (this._menus != null) curCnt = this._menus.Length; Array.Resize(ref _menus, curCnt + 1); _menus[curCnt] = menu; this.Invalidate(); } public void DelMenu(CMenu menu) { List newlist = new List(); for (int i = 0; i < _menus.Length; i++) { if (_menus[i] != menu) newlist.Add(_menus[i]); } this._menus = newlist.ToArray(); this.Invalidate(); } public void DelMenu(int idx) { List newlist = new List(); for (int i = 0; i < _menus.Length; i++) { if (i != idx) newlist.Add(_menus[i]); } this._menus = newlist.ToArray(); this.Invalidate(); } public void DelMenu() { //제거할 아이템이 없다 if (_menus == null || _menus.Length < 1) return; if (_menus.Length == 1) _menus = null; else { //마지막요소를 제거 해주낟 Array.Resize(ref _menus, _menus.Length - 1); } this.Invalidate(); } #endregion protected override void OnPaint(PaintEventArgs e) { e.Graphics.CompositingQuality = CompositingQuality.HighQuality; e.Graphics.InterpolationMode = InterpolationMode.High; e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; base.OnPaint(e); if (bRemakeRect) { this.zitem.Clear(); if (Scean == eScean.Nomal) makeRect_Normal(); else if (Scean == eScean.MotHome) makeRect_MotHome(); else if (Scean == eScean.xmove) makeRect_xmove(); bRemakeRect = false; } if (this.Scean == eScean.Nomal) Scean_Normal(e.Graphics); else if (this.Scean == eScean.MotHome) Scean_MotHome(e.Graphics); else if (this.Scean == eScean.xmove) Scean_XMove(e.Graphics); } /// /// Z축이 아이템을 내려놓은 시간(연속으로 놓는 증상이 발생하여, 일단 이것으로 2초이상 빠르게 놓는일이 없도록 한다) /// public DateTime LastDropTime = DateTime.Now; void RaiseMessage(string m, Boolean iserr, params object[] args) { if (args != null && args.Length > 0) m = string.Format(m, args); if (Message != null) Message(this, new MessageArgs(m, iserr)); } /// /// 아이템을 DROP해도 되는가? 존 3번 부터 아이템이 존재하면 drop 불가능으로 한다 /// void Scean_XMove(Graphics g) { //g.DrawRect(arVar_Port[0].Rect, Color.White, 3); Pen p = new Pen(Color.White, 5); var pts = new List(); pts.Add(new PointF(arVar_Port[0].Rect.Right, arVar_Port[0].Rect.Top)); pts.Add(new PointF(arVar_Port[0].Rect.Left, arVar_Port[0].Rect.Bottom - arVar_Port[0].Rect.Height / 2f)); pts.Add(new PointF(arVar_Port[0].Rect.Right, arVar_Port[0].Rect.Bottom)); g.FillPolygon(Brushes.Blue, pts.ToArray()); g.DrawPolygon(p, pts.ToArray()); g.DrawString("[START]\nLEFT", this.Font, Brushes.Gold, arVar_Port[0].Rect, new StringFormat { Alignment = StringAlignment.Far, LineAlignment = StringAlignment.Center }); pts.Clear(); pts.Add(new PointF(arVar_Port[1].Rect.Left, arVar_Port[1].Rect.Top)); pts.Add(new PointF(arVar_Port[1].Rect.Right, arVar_Port[1].Rect.Bottom - arVar_Port[1].Rect.Height / 2f)); pts.Add(new PointF(arVar_Port[1].Rect.Left, arVar_Port[1].Rect.Bottom)); g.FillPolygon(Brushes.Brown, pts.ToArray()); g.DrawPolygon(p, pts.ToArray()); g.DrawString("[STOP]\nRIGHT", this.Font, Brushes.Gold, arVar_Port[1].Rect, new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center }); if (arPickerSafeZone) g.FillEllipse(Brushes.Lime, arVar_Port[2].Rect); else g.FillEllipse(Brushes.Tomato, arVar_Port[2].Rect); g.DrawEllipse(new Pen(Color.White, 3), arVar_Port[2].Rect); g.DrawString("PICKER\nSAFTY\n" + (arPickerSafeZone ? "ON" : "OFF"), this.Font, Brushes.Black, arVar_Port[2].Rect, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }); //중앙에 메세지를 표시한다. var cpad = rect_main.Width * 0.1f; var cheigh = rect_main.Height * 0.20f; var crect = new RectangleF(rect_main.Left + cpad, rect_main.Top + (rect_main.Height - cheigh) / 2f, rect_main.Width - cpad * 2f, cheigh); g.FillRectangle(new SolidBrush(Color.FromArgb(20, 20, 20)), crect); if (arPickerSafeZone) g.DrawString("Home search is possible", new Font("Tahoma", 20, FontStyle.Bold), Brushes.Lime, crect, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }); else { if (MessageOn) g.DrawString("Move the picker to a safe position", new Font("Tahoma", 12, FontStyle.Bold), Brushes.Red, crect, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }); else g.DrawString("Move the picker to a safe position", new Font("Tahoma", 12, FontStyle.Bold), Brushes.White, crect, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }); } g.DrawRect(crect, Color.White, 5); p.Dispose(); var ts = DateTime.Now - ScreenUpdateTime; if (ts.TotalMilliseconds >= 200) { MessageOn = !MessageOn; ScreenUpdateTime = DateTime.Now; } } DateTime ScreenUpdateTime = DateTime.Now; Boolean MessageOn = false; void Scean_MotHome(Graphics g) { //g.DrawString("mot home", this.Font, Brushes.Black, 100, 100); g.DrawRectangle(new Pen(Color.SteelBlue, 10), this.rect_main.Left, rect_main.Top, rect_main.Width, rect_main.Height); Font f = new Font(this.Font.Name, 20f, FontStyle.Bold); var titleSize = g.MeasureString("HOME", f); var rectTitle = new RectangleF( rect_main.Left, rect_main.Top + 10, rect_main.Width, titleSize.Height * 1.2f); g.DrawString("MOTION HOME", f, Brushes.White, rectTitle, sfCenter); ; // g.DrawRectangle(Pens.Red, rectTitle.Left, rectTitle.Top, rectTitle.Width, rectTitle.Height); var rectBody = new RectangleF( rect_main.Left + 10, rectTitle.Bottom + 10, rect_main.Width - 20, rect_main.Height - rectTitle.Height - 10 - 20); //g.DrawRectangle(Pens.White, rectBody.Left, rectBody.Top, rectBody.Width, rectBody.Height); var rectT = new Rectangle( (int)(rectBody.Left + 20), (int)(rectBody.Top + 30), (int)(rectBody.Width * 0.3f), (int)(rectBody.Height * 0.07)); var rectXF = new Rectangle( (int)(rectT.Right + 20), (int)(rectBody.Top + 30), (int)(rectBody.Width - rectT.Width - rectT.Left - 10), (int)(rectBody.Height * 0.07)); //g.DrawRect(rectT, Color.White, 1); //g.DrawRect(rectXF, Color.Red, 1); var titles = new string[] { "[0] PICKER-Y", "[1] PICKER-Z", "[2] PRINTL-Y", "[3] PRINTL-Z", "[4] PRINTR-Y", "[5] PRINTR-Z", "[6] ANGLE" }; for (int i = 0; i < titles.Length; i++) { var perc = arHomeProgress[i]; var title = titles[i]; var offsetY = (rectBody.Height * 0.12f); //0번은 처리하지 않음 if (i > 0) { rectXF.Offset(0, (int)offsetY); rectT.Offset(0, (int)offsetY); } //g.DrawRectangle(Pens.Yellow, rectT.Left, rectT.Top, rectT.Width, rectT.Height); using (Font f2 = new Font(this.Font.Name, 10f, FontStyle.Bold)) { g.DrawString("* " + title, f2, Brushes.Lime, rectT, sfLeft); } LinearGradientBrush brProgr = new LinearGradientBrush(rectXF, Color.Gold, Color.Yellow, LinearGradientMode.Vertical); var rectXF_P = new Rectangle(rectXF.Left, rectXF.Top, (int)(rectXF.Width * (perc / 100.0)), rectXF.Height); g.FillRectangle(brProgr, rectXF_P); g.DrawRectangle(Pens.Gray, rectXF); brProgr.Dispose(); } f.Dispose(); } void Scean_Normal(Graphics g) { //전체 영역 테두리 //g.DrawRectangle(new Pen(Color.White, 2), rect_main.Left, rect_main.Top, rect_main.Width, rect_main.Height); //포트표시(셔틀위에 표시됨) Draw_Port(g); //front //프린터영역그리기 201228 var printareahei = 100; var printareaw = 100; var printbordersize = 5; var rectpl = new RectangleF(arVar_Port[0].Rect.Right + printbordersize, arVar_Port[0].Rect.Top - printareahei-20, printareaw, printareahei); var fColorPrn = arFGPrinter0END ? Color.Lime : (arFGPrinter0RDY ? Color.Gold : Color.Gray); g.DrawRect(rectpl, fColorPrn, printbordersize); var prnstrbase = "";// "Print Qty:" + arCountPrint0.ToString("000") + "\n"; var prnstr = prnstrbase + (arFGPrinter0END ? "Print Complete" : (arFGPrinter0RDY ? "Printing" : "Print Ready")); prnstr += "\n" + arCountPrint0.ToString("0000"); g.DrawString(prnstr, new Font("Tahoma", 10, FontStyle.Bold), new SolidBrush(fColorPrn), rectpl, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }); rectpl = new RectangleF(arVar_Port[2].Rect.Left - 90 - printbordersize, arVar_Port[2].Rect.Top - printareahei-20, printareaw, printareahei); fColorPrn = arFGPrinter1END ? Color.Lime : (arFGPrinter1RDY ? Color.Gold : Color.Gray); g.DrawRect(rectpl, fColorPrn, printbordersize); prnstrbase = "";// "Print Qty:" + arCountPrint1.ToString("000") + "\n"; prnstr = prnstrbase + (arFGPrinter1END ? "Print Complete" : (arFGPrinter1RDY ? "Printing" : "Print Ready")); prnstr += "\n" + arCountPrint1.ToString("0000"); g.DrawString(prnstr, new Font("Tahoma", 10, FontStyle.Bold), new SolidBrush(fColorPrn), rectpl, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }); //모터 Y/Z축 Draw_PickerY(g, rect_picker); //왼쪽 프린터 Draw_PickerPrinter(g, rect_printl, 2, 3, false, arMotILockPLM, arMotILockPLZ, arPLItemON, PrintLPICK, L_PICK_FW, L_PICK_BW); //오른쪽 프린터 Draw_PickerPrinter(g, rect_printr, 4, 5, true, arMotILockPRM, arMotILockPRZ, arPRItemON, PrintRPICK, R_PICK_FW, R_PICK_BW); //정보 표시 (나중에 제거해야함) 별도 인포박스형태를 취해야 함 Draw_Error(g); //메뉴는 최상위에 표시한다 Draw_Menu(g); if (arDebugMode) { var sb = new System.Text.StringBuilder(); sb.AppendLine("Debug Message"); sb.AppendLine(string.Format("Display {0}", rect_main)); sb.AppendLine(string.Format("Mot Name : {0}/{1}/{2}/{3}/{4}/{5}", arMotPosNamePX, arMotPosNamePZ, arMotPosNameLM, arMotPosNameLZ, arMotPosNameRM, arMotPosNameRZ)); updatetime = DateTime.Now; //작업 수량 및 전체수량을 표시함 var sb2 = new System.Text.StringBuilder(); if (arVar_Port != null && arVar_Port.Length > 0) { sb.AppendLine(string.Format("DIO:{4},BCD:{5},PLC:{6}\n" + "YP_RDY {7},{8},{9},{10}\n" + "YP_CMD {7},{8},{9},{10}\n", arVar_Port[0].reelCount, arVar_Port[1].reelCount, arVar_Port[2].reelCount, arConn_DIO, arConn_BCD, arConn_PLC, arFG_RDY_YP_FPICKON, arFG_RDY_YP_FPICKOF, arFG_RDY_YP_RPICKON, arFG_RDY_YP_RPICKOF, arFG_CMD_YP_FPICKON, arFG_CMD_YP_RPICKON)); } } } void Draw_Screw(Graphics g, Rectangle rect) { //모터표시(X축) g.FillRectangle(new SolidBrush(Color.FromArgb(50, 150, 150, 150)), rect); //해다 영역에 사선으로그림을 그린다. var termcount = 50; var lineterm = rect.Width / termcount; var skew = rect.Width * 0.01f; Pen p = new Pen(Color.FromArgb(50, 120, 120, 120), 2); for (int i = 0; i < termcount; i++) { var pt1 = new PointF(rect.Left + i * lineterm, rect.Top); var pt2 = new PointF(pt1.X + skew, rect.Bottom); g.DrawLine(p, pt1, pt2); } p.Dispose(); g.DrawRectangle(new Pen(Color.FromArgb(50, Color.Gray)), rect.Left, rect.Top, rect.Width, rect.Height); } void Draw_BallScrewRail(Graphics g, RectangleF rect, int divCount, int alpha, Boolean downDirection, Boolean MLock, Boolean Org, Boolean LimDn, Boolean LimUp) { //모터표시(X축) if (Org) g.FillRectangle(new SolidBrush(Color.FromArgb(alpha, Color.SkyBlue)), rect); else if (LimUp) g.FillRectangle(new SolidBrush(Color.FromArgb(alpha, Color.Red)), rect); else if (LimDn) g.FillRectangle(new SolidBrush(Color.FromArgb(alpha, Color.Blue)), rect); else g.FillRectangle(new SolidBrush(Color.FromArgb(alpha, 150, 150, 150)), rect); //해다 영역에 사선으로그림을 그린다. var baseSize = (downDirection == false ? rect.Width : rect.Height); var lineterm = baseSize / divCount; var skew = baseSize * 0.01f; Pen p = new Pen(Color.FromArgb(alpha, 120, 120, 120), 2); PointF pt1 = PointF.Empty; PointF pt2 = PointF.Empty; for (int i = 0; i < divCount; i++) { if (downDirection) { pt1 = new PointF(rect.Left, rect.Top + i * lineterm); pt2 = new PointF(rect.Right, pt1.Y + skew); } else { pt1 = new PointF(rect.Left + i * lineterm, rect.Top); pt2 = new PointF(pt1.X + skew, rect.Bottom); } g.DrawLine(p, pt1, pt2); } p.Dispose(); //limi이 걸려있다면 해당 영역에 적색으로 표시한다. var limwidth = 30; if (LimUp) { RectangleF rectlu; if (downDirection) rectlu = new RectangleF(rect.Left, rect.Top, rect.Width, limwidth); else rectlu = new RectangleF(rect.Right - limwidth, rect.Top, limwidth, rect.Height); g.FillRectangle(Brushes.Red, rectlu.Left, rectlu.Top, rectlu.Width, rectlu.Height); } if (LimDn) { RectangleF rectlu; if (downDirection) rectlu = new RectangleF(rect.Left, rect.Bottom - limwidth, rect.Width, limwidth); else rectlu = new RectangleF(rect.Left, rect.Top, limwidth, rect.Height); g.FillRectangle(Brushes.Red, rectlu.Left, rectlu.Top, rectlu.Width, rectlu.Height); } //전체 테두리 g.DrawRectangle(new Pen(Color.FromArgb(alpha, Color.Gray)), rect.Left, rect.Top, rect.Width, rect.Height); } Boolean NeedHomeSet() { return arConn_MOT && (this.arMOT_HSet[0] == false || this.arMOT_HSet[1] == false || this.arMOT_HSet[2] == false || this.arMOT_HSet[3] == false || this.arMOT_HSet[4] == false); } byte errstep = 0; bool errstepR = true; void Draw_Error(Graphics g) { //디자인 모드에서는 표시하지 않는다 200714 if (DesignMode == true) return; if (arConn_DIO && this.arDI_Emergency == true) ShowPopupMessage(g, "EMERGENCY BUTTON", "Check emergency stop\nEMERGENCY or POWER LOSS", Properties.Resources.error, true); else if (this.arDI_SaftyOk == false) ShowPopupMessage(g, "SAFTY SENSOR", "Check safety sensor", Properties.Resources.alert, true); else if (arConn_MOT && this.arMOT_Alm[0] == true) ShowPopupMessage(g, "SERVO ALARM", "Y-PICKER motor alarm occurred", Properties.Resources.error, true); else if (arConn_MOT && this.arMOT_Alm[1] == true) ShowPopupMessage(g, "SERVO ALARM", "Z-FRONT motor alarm occurred", Properties.Resources.error, true); else if (arConn_MOT && this.arMOT_Alm[2] == true) ShowPopupMessage(g, "SERVO ALARM", "Z-REAR motor alarm occurred", Properties.Resources.error, true); else if (arConn_MOT && this.arMOT_SVOn[0] == false) ShowPopupMessage(g, "SERVO ALARM", "Y-PICKER\nSERVO-OFF", Properties.Resources.alert, true); else if (arConn_MOT && this.arMOT_SVOn[1] == false) ShowPopupMessage(g, "SERVO ALARM", "Z-PICKER\nSERVO-OFF", Properties.Resources.alert, true); else if (arConn_MOT && this.arMOT_SVOn[2] == false) ShowPopupMessage(g, "SERVO ALARM", "L-PRINT-Y\nSERVO-OFF", Properties.Resources.alert, true); else if (arConn_MOT && this.arMOT_SVOn[3] == false) ShowPopupMessage(g, "SERVO ALARM", "L-PRINT-Z\nSERVO-OFF", Properties.Resources.alert, true); else if (arConn_MOT && this.arMOT_SVOn[4] == false) ShowPopupMessage(g, "SERVO ALARM", "R-PRINT-Y\nSERVO-OFF", Properties.Resources.alert, true); else if (arConn_DIO && this.arAIRDetect == false) ShowPopupMessage(g, "AIR DETECT", "*Press the blue AIR button on the front to supply AIR\n* Check the AIR line", Properties.Resources.error, true); else if (arConn_MOT && (this.arMOT_HSet[0] == false || this.arMOT_HSet[1] == false || this.arMOT_HSet[2] == false)) { //안전오류도 표시해줘야한다 var SaftyMessage = string.Empty; if (arVar_Port[0].SaftyErr == true) SaftyMessage += "DOOR:LEFT"; if (arVar_Port[1].SaftyErr == true) SaftyMessage += (string.IsNullOrEmpty(SaftyMessage) == false ? "," : string.Empty) + "DOOR:CENTER"; if (arVar_Port[2].SaftyErr == true) SaftyMessage += (string.IsNullOrEmpty(SaftyMessage) == false ? "," : string.Empty) + "DOOR:RIGHT"; if (arPickerSafeZone == false) SaftyMessage += (string.IsNullOrEmpty(SaftyMessage) == false ? "\n" : string.Empty) + "Picker safety position: OFF"; else SaftyMessage += "Picker safety position: ON"; ; ShowPopupMessage(g, "SYSTEM NOT READY", "Initialization required\n" + SaftyMessage, Properties.Resources.error, true); } else if (arConn_MOT && this.arMOT_HSet[0] == false) ShowPopupMessage(g, "SERVO ALARM", "Y-PICKER home search required", Properties.Resources.alert, true); else if (arConn_MOT && this.arMOT_HSet[1] == false) ShowPopupMessage(g, "SERVO ALARM", "Z-FRONT home search required", Properties.Resources.alert, true); else if (arConn_MOT && this.arMOT_HSet[2] == false) ShowPopupMessage(g, "SERVO ALARM", "Z-REAR home search required", Properties.Resources.alert, true); else if (arVar_Port[0].OverLoad) ShowPopupMessage(g, "## OVERLOAD ##", "FRONT-LEFT", Properties.Resources.alert, true); else if (arVar_Port[1].OverLoad) ShowPopupMessage(g, "## OVERLOAD ##", "FRONT-RIGHT", Properties.Resources.alert, true); } void Draw_Menu(Graphics g) { if (arMenus == null || arMenus.Length < 1) { this.HasPopupMenu = false; return; } else HasPopupMenu = true; ShowMaskLayer(g, Color.FromArgb(250, Color.Black)); var item = this.arMenus.Last();//.Peek(); //이 메뉴를 표시 합니다. PopupMenuRequireInput = item.RequireInput; var buttonSpace = 10; var hSpace = 5; var vSpace = 10; var iconSize = 80; var menuheight = 64; var padding = 10; var msgW = 900;// (int)(this.rect_main.Width * 0.65f);// 640;// (int)(rect_main.Width * 0.7f); var msgH = 400; var rect = new RectangleF( rect_main.Left + (rect_main.Width - msgW) / 2.0f, rect_main.Top + (rect_main.Height - msgH) / 2.0f, msgW, msgH); Rectangle rectT = Rectangle.Empty; //title Rectangle rectI = Rectangle.Empty; //icon Rectangle rectC = Rectangle.Empty; //content Rectangle rectB = Rectangle.Empty; //button rectT = new Rectangle((int)rect.Left + padding, (int)rect.Top + padding, (int)rect.Width - (padding * 2), (int)(rect.Height * 0.1)); rectI = new Rectangle((int)rect.Left + padding + 10, (int)rectT.Bottom + vSpace, iconSize, iconSize); //icon size rectB = new Rectangle((int)(rect.Left + padding * 2), (int)(rect.Bottom - menuheight - padding), (int)rect.Width - (padding * 4), menuheight); rectC = new Rectangle((int)rectI.Right + 20 + hSpace * 2, (int)rectT.Bottom + 10 + vSpace, (int)(rect.Width - hSpace - (padding * 2) - rectI.Width), (int)(rect.Height - rectT.Height - rectB.Height - (padding * 2) - vSpace * 2)); g.FillRectangle(new SolidBrush(Color.FromArgb(220, item.BackColor)), rect); //제목줄 표시 using (LinearGradientBrush sb = new LinearGradientBrush(rectT, Color.FromArgb(160, 160, 160), Color.FromArgb(180, 180, 180), LinearGradientMode.Vertical)) { g.FillRectangle(sb, rectT); } g.DrawString(item.Title, item.Font, new SolidBrush(item.ForeColor), rectT, sfCenter); //버튼표시 if (item.buttons != null && item.buttons.Length > 0) { //현재 버튼 영역의 갯수가 다르면 다시 생성한다. if (menuButtons.Count != item.buttons.Length) { menuButtons = new List(); foreach (var bt in item.buttons) menuButtons.Add(bt); g.DrawString("!!", this.Font, Brushes.Red, rectB.Left + 10, rectB.Top + 10); } else { for (int i = 0; i < menuButtons.Count; i++) menuButtons[i] = item.buttons[i]; } g.DrawString(item.buttons.Length.ToString() + "/" + menuButtons.Count.ToString(), this.Font, Brushes.Red, rectB); var butidx = 0; var butwid = (rectB.Width - (item.buttons.Length - 1) * buttonSpace) / item.buttons.Length; foreach (var but in item.buttons) { but.menutag = item.Tag; but.Rect = new Rectangle(rectB.Left + butwid * butidx + buttonSpace * butidx, rectB.Top, butwid, rectB.Height); g.FillRectangle(new SolidBrush(but.BackColor), but.Rect); g.DrawRectangle(new Pen(but.BorderColor, but.BorderSize), but.Rect); g.DrawString(but.Text, item.Font, new SolidBrush(but.ForeColor), but.Rect, sfCenter); butidx++; } } else menuButtons.Clear(); //아이콘 영역에 그림표시 if (rectI.IsEmpty == false) { g.DrawImage(Properties.Resources.info, rectI); } //본문데이터표시 if (string.IsNullOrEmpty(item.Text) == false) //contec { g.DrawString(item.Text, item.Font, new SolidBrush(item.ForeColor), rectC); } g.DrawRectangle(new Pen(Color.FromArgb(180, 180, 180), 10) { Alignment = PenAlignment.Center }, rect.Left, rect.Top, rect.Width, rect.Height); } void ShowMaskLayer(Graphics g, Color maskColor) { g.FillRectangle(new SolidBrush(maskColor), this.DisplayRectangle.Left, DisplayRectangle.Top, DisplayRectangle.Width, DisplayRectangle.Height); } public Font MessageBody { get; set; } = new Font("Tahoma", 20, FontStyle.Bold); public Font MessageTitle { get; set; } = new Font("Tahoma", 10, FontStyle.Bold); void ShowPopupMessage(Graphics g, string title, string msg, Image icon, Boolean isError) { if (isError == false) { //팝업표시할때마다 배경 마스킹을 한다 var maskColor = Color.FromArgb(50, Color.Gray); ShowMaskLayer(g, maskColor); var msgW = (int)(this.rect_main.Width * 0.65f);// 640;// (int)(rect_main.Width * 0.7f); var msgH = 105; var rect = new RectangleF( rect_main.Left + (rect_main.Width - msgW) / 2.0f, rect_main.Top + (rect_main.Height - msgH) / 2.0f, msgW, msgH); var TitleHeight = 25; var rectT = new Rectangle((int)rect.Left, (int)rect.Bottom - TitleHeight, (int)rect.Width, TitleHeight); var rectI = new Rectangle((int)rect.Left, (int)rect.Top, (int)rect.Width, (int)rect.Height - rectT.Height); //g.FillRectangle(new SolidBrush(Color.FromArgb(220, Color.Black)), rect); g.FillRectangle(new SolidBrush(Color.FromArgb(120, Color.White)), rect); var rectTL = new RectangleF(rectT.Left, rectT.Top, rectT.Width / 2.0f, rectT.Height); var rectTR = new RectangleF(rectTL.Right, rectT.Top, rectTL.Width, rectTL.Height); using (var sb = new LinearGradientBrush(rectT, Color.Transparent, Color.White, LinearGradientMode.Horizontal)) g.FillRectangle(sb, rectTL); using (var sb = new LinearGradientBrush(rectT, Color.White, Color.Transparent, LinearGradientMode.Horizontal)) g.FillRectangle(sb, rectTR); //g.DrawImage(icon, // (int)(rect.Left + 20), // (int)(rect.Top + (rect.Height - icon.Height) / 2.0f)); g.DrawString(title, MessageTitle, Color.Black, rectT, ContentAlignment.MiddleCenter); g.DrawString(msg, MessageBody, Color.White, rectI, ContentAlignment.MiddleCenter, Color.FromArgb(24, 24, 24)); if (errstep % 5 == 0) errstepR = !errstepR; if (errstepR) g.DrawRectangle(new Pen(Color.Gold, 2), rect.Left, rect.Top, rect.Width, rect.Height); else g.DrawRectangle(new Pen(Color.White, 2), rect.Left, rect.Top, rect.Width, rect.Height); if (errstep < 255) errstep += 1; else errstep = 0; } else { //팝업표시할때마다 배경 마스킹을 한다 var maskColor = Color.FromArgb(253, 15, 15, 15); ShowMaskLayer(g, maskColor); var msgW = (int)(this.rect_main.Width * 0.8f);// 640;// (int)(rect_main.Width * 0.7f); var msgH = (int)(this.rect_main.Height * 0.8f);// var rect = new RectangleF( rect_main.Left + (rect_main.Width - msgW) / 2.0f, rect_main.Top + (rect_main.Height - msgH) / 2.0f, msgW, msgH); var rectT = new Rectangle((int)rect.Left, (int)rect.Bottom - 200, (int)rect.Width, 200); var rectI = new Rectangle((int)rect.Left, (int)rect.Top, (int)rect.Width, (int)rect.Height - rectT.Height); //g.FillRectangle(new SolidBrush(Color.FromArgb(220, Color.Black)), rect); g.FillRectangle(new SolidBrush(Color.FromArgb(253, Color.Black)), rect); g.DrawImage(icon, (int)(rectI.Left + rectI.Width / 2.0f) - 40, (int)(rectI.Top + rectI.Height / 2.0f) + 10); g.DrawString(msg, MessageBody, Brushes.Gold, rectT, sfCenter); if (errstep % 5 == 0) errstepR = !errstepR; if (errstepR) g.DrawRectangle(new Pen(Color.Red, 10), rect.Left, rect.Top, rect.Width, rect.Height); else g.DrawRectangle(new Pen(Color.Gold, 10), rect.Left, rect.Top, rect.Width, rect.Height); if (errstep < 255) errstep += 1; else errstep = 0; } } void Draw_Port(Graphics g) { var fSizeCnt = 20; var convmode = VAR.BOOL?[eVarBool.Use_Conveyor] ?? false; using (Font fCnt = new Font("consolas", fSizeCnt, FontStyle.Bold)) { using (Font fMSg = new Font("Tahoma", 15, FontStyle.Bold)) { if (convmode) this.arVar_Port[0].DisplayConv(g, fCnt, fMSg, arMagnet0, arFGVision0RDY, arFGVision0END, arPortLItemOn, arMotILockVS0, arCountV0, CVLeftBusy, CVLeftReady); else this.arVar_Port[0].Display(g, fCnt, fMSg, arMagnet0, arFGVision0RDY, arFGVision0END, arPortLItemOn, arMotILockVS0, arCountV0); this.arVar_Port[1].Display(g, fCnt, fMSg, arMagnet1, arFGVision1RDY, arFGVision1END, false, arMotILockVS1, arCountV1); if (convmode) this.arVar_Port[2].DisplayConv(g, fCnt, fMSg, arMagnet2, arFGVision2RDY, arFGVision2END, arPortRItemOn, arMotILockVS2, arCountV2, CVRightBusy, CVRightReady); else this.arVar_Port[2].Display(g, fCnt, fMSg, arMagnet2, arFGVision2RDY, arFGVision2END, arPortRItemOn, arMotILockVS2, arCountV2); } } } private void Tm_Tick(object sender, EventArgs e) { if (ConveyorRunPoint < (AnimationStepConv - 3)) ConveyorRunPoint += 1; else ConveyorRunPoint = 1; for (int i = 0; i < 3; i++) { if (this.arVar_Port[i].arrowIndex < (arVar_Port[i].AnimationStepPort - 3)) this.arVar_Port[i].arrowIndex += 1; else this.arVar_Port[i].arrowIndex = 1; } this.Invalidate(); } } }