using HalconDotNet; using Rs.Framework; using Rs.MotionPlat.Commom; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Data.Common; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using System.Xml.Serialization; using static System.Windows.Forms.VisualStyles.VisualStyleElement; namespace Rs.Controls { public enum ESortDir { LeftToRight, RightToLeft, RightTopToBottom, LeftBottomToTop } public enum ESlotStatus { Have, NotHave, Ok, Ng, Disable, Null } public partial class RsTray : UserControl { public event Action> DrawTrayAfterEvent; public string ItemName { get; set; } private ESortDir sortDir = ESortDir.LeftToRight; public ESortDir SortDir { get { return sortDir; } set { sortDir = value; UpdateSlotPos(); } } public event Action SlotClickEvent; #region 是否显示状态 private bool mShowStatus = true; /// /// 是否显示状态 /// public bool ShowStatus { get { return mShowStatus; } set { mShowStatus = value; lblStatus.Visible = mShowStatus; if(!mShowStatus) { tableLayoutPanel1.SetColumnSpan(label1, 2); } } } #endregion private string mStatus; public string Status { get { return mStatus; } set { mStatus = value; lblStatus.Text = mStatus; if(mStatus=="Empty" || mStatus == "Unloaded") { lblStatus.BackColor = Color.Gray; } else if(mStatus=="Loaded") { lblStatus.BackColor = Color.Green; } else { lblStatus.BackColor = Color.Red; } Invalidate(); } } private bool _ShowRowNumber; /// /// 是否显示行号 /// public bool ShowRowNumber { get { return _ShowRowNumber; } set { _ShowRowNumber = value; } } private bool _ShowColNumber; /// /// 是否显示列号 /// public bool ShowColNumber { get { return _ShowColNumber; } set { _ShowColNumber = value; } } public RsTray() { InitializeComponent(); DoubleBuffered = true; InitSlot(InitSlotStatus); this.SizeChanged += (s, e) => { UpdateSlotPos(); }; } public void ResetTray() { } private ESlotStatus _InitSlotStatus = ESlotStatus.Have; public ESlotStatus InitSlotStatus { get { return _InitSlotStatus; } set { _InitSlotStatus = value; InitSlot(InitSlotStatus); Invalidate(); } } public TraySlot GetSlot(ESlotStatus status,bool reverse=false) { if(reverse) { for (int row = 0; row < RowNum; row++) { for (int col = ColumnNum; col > 0; col--) { int index = row * (ColumnNum) + col; if (traySlotsDic[index].SlotStatus == status) return traySlotsDic[index]; } } } else { foreach (KeyValuePair kv in traySlotsDic) { if (kv.Value.SlotStatus == status) return kv.Value; } } return null; } /// /// 根据穴位的状态获取穴位 /// /// /// public List GetSlots(ESlotStatus status) { List slots = new List(); foreach (KeyValuePair item in traySlotsDic) { if (item.Value.SlotStatus == status) slots.Add(item.Value); } return slots; } /// /// 通过穴位的索引获取穴位 /// /// /// public TraySlot GetSlot(int slotIndex) { foreach (KeyValuePair kv in traySlotsDic) { if (kv.Key == slotIndex) return kv.Value; } return null; } public bool CanDraw { get; set; } = true; private Dictionary traySlotsDic = new Dictionary(); private string _HeadText; public string HeadText { get { return _HeadText; } set { _HeadText = value; this.label1.Text = value; } } private int _RowNum = 16; /// /// 行数 /// public int RowNum { get { return _RowNum; } set { _RowNum = value; InitSlot(InitSlotStatus); Invalidate(); } } private int _ColumnNum = 16; /// /// 列数量 /// public int ColumnNum { get { return _ColumnNum; } set { _ColumnNum = value; InitSlot(InitSlotStatus); Invalidate(); } } private int _TopSpaceHeight = 20; /// /// 料盘上部留白高度 /// public int TopSpaceHeight { get { return _TopSpaceHeight; } set { _TopSpaceHeight = value; } } private int _LeftSpaceWidth = 20; /// /// 料盘左边留白宽度 /// public int LeftSpaceWidth { get { return _LeftSpaceWidth; } set { _LeftSpaceWidth = value; } } private int _RowSpace = 3; public int RowSpace { get { return _RowSpace; } set { _RowSpace = value; } } private int _ColSpace = 5; public int ColSpace { get { return _ColSpace; } set { _ColSpace = value; } } private bool _ShowText; public bool ShowText { get { return _ShowText; } set { _ShowText = value; } } private float _OffsetX; /// /// X方向偏移 /// public float OffsetX { get { return _OffsetX; } set { _OffsetX = value; } } private float _OffsetY; /// /// Y方向偏移 /// public float OffsetY { get { return _OffsetY; } set { _OffsetY = value; } } private float _OffsetYEven; /// /// Y方向偏移(偶数行) /// public float OffsetYEven { get { return _OffsetYEven; } set { _OffsetYEven = value; } } private bool _SinglePoint=false; /// /// 单点定位 /// public bool SinglePoint { get { return _SinglePoint; } set { _SinglePoint = value; } } private Bitmap drawImage; private void InitSlot(ESlotStatus status) { int index = 0; traySlotsDic.Clear(); for (int r = 0; r < RowNum; r++) { for (int c = 0; c < ColumnNum; c++) { index++; TraySlot slot = new TraySlot(); slot.Index = index; slot.Row = r; slot.Column = c; slot.SlotStatus = status; traySlotsDic.Add(index, slot); } } UpdateSlotPos(); } public void Fill() { foreach (KeyValuePair kv in traySlotsDic) { ChangeStatus(kv.Value.Index, ESlotStatus.Have); } } public void Clear() { foreach (KeyValuePair kv in traySlotsDic) { ChangeStatus(kv.Value.Index, ESlotStatus.NotHave); } } public void ChangeStatus(ESlotStatus status) { foreach (KeyValuePair kv in traySlotsDic) { ChangeStatus(kv.Value.Index,status); } } public void ChangeStatus(int index, ESlotStatus status) { if (traySlotsDic.ContainsKey(index)) { traySlotsDic[index].SlotStatus = status; traySlotsDic[index].Refresh(this.panel2.CreateGraphics(), ShowText); } } private void UpdateSlotPos() { float slotWidth = (this.panel2.Width - LeftSpaceWidth) / ColumnNum; float slotHeight = (this.panel2.Height - TopSpaceHeight) / RowNum; int index = 0; if (SortDir == ESortDir.LeftToRight) { for (int r = 0; r < RowNum; r++) { for (int c = 0; c < ColumnNum; c++) { index++; if (traySlotsDic.ContainsKey(index)) { traySlotsDic[index].Bound = new RectangleF((LeftSpaceWidth + slotWidth * c), (TopSpaceHeight + slotHeight * r), (int)slotWidth - ColSpace, (int)slotHeight - RowSpace); } } } } else if (SortDir == ESortDir.RightToLeft) { ShowColNumber = ShowRowNumber = false; slotWidth = (this.panel2.Width) / ColumnNum; slotHeight = (this.panel2.Height) / RowNum; for (int r = 0; r < RowNum; r++) { for (int c = 0; c < ColumnNum; c++) { index++; if (traySlotsDic.ContainsKey(index)) { traySlotsDic[index].Bound = new RectangleF((LeftSpaceWidth + slotWidth * (ColumnNum-1-c)), (TopSpaceHeight + slotHeight * r), (int)slotWidth - ColSpace, (int)slotHeight - RowSpace); } } } } else if (sortDir == ESortDir.RightTopToBottom) { ShowColNumber = ShowRowNumber = false; slotWidth = (this.panel2.Width) / ColumnNum; slotHeight = (this.panel2.Height) / RowNum; //从列开始画 for (int c = ColumnNum; c > 0; c--) { for (int r = 0; r < RowNum; r++) { index++; if (traySlotsDic.ContainsKey(index)) { float x = slotWidth * (c-1); float y = slotHeight * r; traySlotsDic[index].Bound = new RectangleF(x, y, (int)slotWidth - ColSpace, (int)slotHeight - RowSpace); } } } } else if (sortDir == ESortDir.LeftBottomToTop) { ShowColNumber = ShowRowNumber = false; slotWidth = (this.panel2.Width ) / ColumnNum; slotHeight = (this.panel2.Height ) / RowNum; //从列开始画 for (int c = 0; c < ColumnNum; c++) { for (int r = RowNum; r > 0; r--) { index++; if (traySlotsDic.ContainsKey(index)) { float x = slotWidth * c; float y = slotHeight * (r-1); traySlotsDic[index].Bound = new RectangleF(x, y, (int)slotWidth - ColSpace, (int)slotHeight - RowSpace); } //index++; //if (traySlotsDic.ContainsKey(index)) //{ // float y = 0; // float x = LeftSpaceWidth + slotWidth * r; // if(!ShowColNumber) // { // y = slotHeight * c - TopSpaceHeight / 2; // } // else // { // y = slotHeight * c; // } // traySlotsDic[index].Bound = new RectangleF(x, y, (int)slotWidth - ColSpace, (int)slotHeight - RowSpace); //} } } } panel2.Refresh(); } private void panel2_Paint(object sender, PaintEventArgs e) { if(this.panel2.Width<=0 || this.panel2.Height<=0) { return; } this.DoubleBuffered = true; Graphics g = this.panel2.CreateGraphics(); drawImage = new Bitmap(this.panel2.Width, this.panel2.Height); Graphics g2 = Graphics.FromImage(drawImage); g2.Clear(BackColor); //先计算出每一个料仓中穴位占用的宽度和高度 float widthPer = (this.panel2.Width - LeftSpaceWidth) / ColumnNum; float heightPer = (this.panel2.Height - TopSpaceHeight) / RowNum; //先画列,再画行 int index = 0; for (int c = 0; c < ColumnNum; c++) { for (int r = 0; r < RowNum; r++) { index++; if (r == 0) { if(ShowRowNumber) { //画料盘的列号 if (SortDir == ESortDir.LeftToRight) { g2.DrawString((c + 1).ToString(), new Font("宋体", 7.0F), new SolidBrush(Color.White), new PointF(LeftSpaceWidth + (widthPer * c) + 5, 5)); } else if (SortDir == ESortDir.RightToLeft) { g2.DrawString((ColumnNum - c).ToString(), new Font("宋体", 7.0F), new SolidBrush(Color.White), new PointF(LeftSpaceWidth + (widthPer * c) + 5, 5)); } else if (SortDir == ESortDir.LeftBottomToTop) { //g2.DrawString((ColumnNum - c).ToString(), new Font("宋体", 7.0F), new SolidBrush(Color.White), new PointF(LeftSpaceWidth + (widthPer * c) + 5, 5)); } } } if (c == 0) { if(ShowColNumber) { //画料盘的行号 g2.DrawString((r + 1).ToString(), new Font("宋体", 7.0F), new SolidBrush(Color.White), new PointF(5, TopSpaceHeight + (heightPer * r))); } } if (traySlotsDic.ContainsKey(index)) { traySlotsDic[index].Draw(g2, ShowText); } } } g2.Flush(); g.DrawImage(drawImage, 0, 0, drawImage.Width, drawImage.Height); if (drawRegion) { g.FillRectangle(new SolidBrush(Color.FromArgb(200, Color.Pink)), drawRect); } g.Flush(); g.Dispose(); g2.Dispose(); } bool drawRegion = false; RectangleF drawRect = new RectangleF(); private void panel2_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left && drawRegion == false) { if (CanDraw) { drawRegion = true; drawRect.X = e.X; drawRect.Y = e.Y; } } } private void panel2_MouseMove(object sender, MouseEventArgs e) { if (drawRegion) { drawRect.Width = e.X - drawRect.X; drawRect.Height = e.Y - drawRect.Y; panel2_Paint(null, null); } } private List drawSlots = new List(); private void panel2_MouseUp(object sender, MouseEventArgs e) { drawRegion = false; drawSlots.Clear(); foreach (KeyValuePair kvSlot in traySlotsDic) { if (drawRect.IntersectsWith(kvSlot.Value.Bound)) { drawSlots.Add(kvSlot.Value); } } } public List GetDrawSlots() { return drawSlots; } public TraySlot SelectSlot { get; set; } private void panel2_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { if (!drawRect.IsEmpty && drawRect.Contains(e.Location)) { contextMenuStrip1.Show(panel2, e.Location); } else { SelectSlot = null; bool find = false; foreach (KeyValuePair kvSlot in traySlotsDic) { if (kvSlot.Value.Bound.Contains(e.Location)) { find = true; SelectSlot = kvSlot.Value; break; } } if (find) { if (SlotClickEvent != null) SlotClickEvent(SelectSlot, e); } } } } private void 禁用ToolStripMenuItem_Click(object sender, EventArgs e) { ChangeSlotStatus(ESlotStatus.Disable); List slots = new List(); foreach (KeyValuePair kvSlot in traySlotsDic) { if (drawRect.IntersectsWith(kvSlot.Value.Bound)) { slots.Add(kvSlot.Value); } } DrawTrayAfterEvent?.Invoke(this, ESlotStatus.Disable, slots); } private void ChangeSlotStatus(ESlotStatus status) { foreach (KeyValuePair kvSlot in traySlotsDic) { if (drawRect.IntersectsWith(kvSlot.Value.Bound)) { kvSlot.Value.SlotStatus = status; } } UpdateSlotPos(); } private void 设置有料ToolStripMenuItem_Click(object sender, EventArgs e) { ChangeSlotStatus(ESlotStatus.Have); List slots = new List(); foreach (KeyValuePair kvSlot in traySlotsDic) { if (drawRect.IntersectsWith(kvSlot.Value.Bound)) { slots.Add(kvSlot.Value); } } DrawTrayAfterEvent?.Invoke(this, ESlotStatus.Have,slots); } private void 设置无料ToolStripMenuItem_Click(object sender, EventArgs e) { ChangeSlotStatus(ESlotStatus.NotHave); List slots = new List(); foreach (KeyValuePair kvSlot in traySlotsDic) { if (drawRect.IntersectsWith(kvSlot.Value.Bound)) { slots.Add(kvSlot.Value); } } DrawTrayAfterEvent?.Invoke(this, ESlotStatus.NotHave,slots); } private void RsTray_Load(object sender, EventArgs e) { UpdateSlotPos(); } } /// /// 料盘槽位 /// public class TraySlot { public ESlotStatus SlotStatus { get; set; } = ESlotStatus.Have; private int _Index; public int Index { get { return _Index; } set { _Index = value; } } private int _Row; public int Row { get { return _Row; } set { _Row = value; } } private int _Column; public int Column { get { return _Column; } set { _Column = value; } } private string _SN; public string SN { get { return _SN; } set { _SN = value; } } private RectangleF _Bound; [XmlIgnore] public RectangleF Bound { get { return _Bound; } set { _Bound = value; } } public void Refresh(Graphics g, bool isShowText) { Draw(g, isShowText); } public void Draw(Graphics g, bool isShowText) { if (_Bound != null) { StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Center; switch (SlotStatus) { case ESlotStatus.Have: g.FillRectangle(new SolidBrush(Color.Blue), Bound.X, Bound.Y, Bound.Width - 1, Bound.Height - 1); break; case ESlotStatus.NotHave: g.FillRectangle(new SolidBrush(Color.FromArgb(11, 16, 36)), Bound.X, Bound.Y, Bound.Width - 1, Bound.Height - 1); break; case ESlotStatus.Ok: g.FillRectangle(new SolidBrush(Color.Green), Bound.X, Bound.Y, Bound.Width - 1, Bound.Height - 1); break; case ESlotStatus.Ng: g.FillRectangle(new SolidBrush(Color.Red), Bound.X, Bound.Y, Bound.Width - 1, Bound.Height - 1); break; case ESlotStatus.Disable: g.FillRectangle(new SolidBrush(Color.Gray), Bound.X, Bound.Y, Bound.Width - 1, Bound.Height - 1); break; case ESlotStatus.Null: g.FillRectangle(new SolidBrush(Color.FromArgb(11, 16, 36)), Bound.X, Bound.Y, Bound.Width - 1, Bound.Height - 1); break; default: break; } if(SlotStatus!= ESlotStatus.Null) { g.DrawRectangle(Pens.White, Bound.X, Bound.Y, Bound.Width, Bound.Height); if (isShowText) { g.DrawString(Index.ToString(), new Font("宋体", 8), new SolidBrush(Color.Yellow), _Bound, sf); } } else { g.DrawRectangle(new Pen(new SolidBrush(Color.FromArgb(11, 16, 36))), Bound.X, Bound.Y, Bound.Width, Bound.Height); } } } } }