You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

774 lines
24 KiB
C#

2 years ago
using HalconDotNet;
using Rs.Framework;
using Rs.MotionPlat.Commom;
2 years ago
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;
2 years ago
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Serialization;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
2 years ago
namespace Rs.Controls
{
2 years ago
public enum ESortDir
{
LeftToRight,
RightToLeft,
RightTopToBottom,
LeftBottomToTop
2 years ago
}
public enum ESlotStatus
{
Have,
NotHave,
Ok,
Ng,
Disable,
Null
2 years ago
}
public partial class RsTray : UserControl
{
public event Action<RsTray,ESlotStatus,List<TraySlot>> DrawTrayAfterEvent;
public string ItemName { get; set; }
private ESortDir sortDir = ESortDir.LeftToRight;
public ESortDir SortDir
{
get { return sortDir; }
set { sortDir = value;
UpdateSlotPos();
}
}
public event Action<TraySlot, MouseEventArgs> SlotClickEvent;
#region 是否显示状态
private bool mShowStatus = true;
/// <summary>
/// 是否显示状态
/// </summary>
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;
/// <summary>
/// 是否显示行号
/// </summary>
public bool ShowRowNumber
{
get { return _ShowRowNumber; }
set { _ShowRowNumber = value; }
}
private bool _ShowColNumber;
/// <summary>
/// 是否显示列号
/// </summary>
public bool ShowColNumber
{
get { return _ShowColNumber; }
set { _ShowColNumber = value; }
}
2 years ago
public RsTray()
{
InitializeComponent();
DoubleBuffered = true;
InitSlot(InitSlotStatus);
this.SizeChanged += (s, e) => {
UpdateSlotPos();
};
}
public void ResetTray()
{
2 years ago
}
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)
2 years ago
{
if(reverse)
2 years ago
{
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<int, TraySlot> kv in traySlotsDic)
{
if (kv.Value.SlotStatus == status)
return kv.Value;
}
2 years ago
}
return null;
}
/// <summary>
/// 根据穴位的状态获取穴位
/// </summary>
/// <param name="status"></param>
/// <returns></returns>
public List<TraySlot> GetSlots(ESlotStatus status)
{
List<TraySlot> slots = new List<TraySlot>();
foreach (KeyValuePair<int,TraySlot> item in traySlotsDic)
{
if (item.Value.SlotStatus == status)
slots.Add(item.Value);
}
return slots;
}
/// <summary>
/// 通过穴位的索引获取穴位
/// </summary>
/// <param name="slotIndex"></param>
/// <returns></returns>
public TraySlot GetSlot(int slotIndex)
{
foreach (KeyValuePair<int, TraySlot> kv in traySlotsDic)
{
if (kv.Key == slotIndex)
return kv.Value;
}
2 years ago
return null;
}
public bool CanDraw { get; set; } = true;
private Dictionary<int, TraySlot> traySlotsDic = new Dictionary<int, TraySlot>();
private string _HeadText;
public string HeadText
{
get { return _HeadText; }
set { _HeadText = value; this.label1.Text = value; }
}
private int _RowNum = 16;
2 years ago
/// <summary>
/// 行数
/// </summary>
public int RowNum
{
get { return _RowNum; }
set { _RowNum = value; InitSlot(InitSlotStatus); Invalidate(); }
}
private int _ColumnNum = 16;
2 years ago
/// <summary>
/// 列数量
/// </summary>
public int ColumnNum
{
get { return _ColumnNum; }
set { _ColumnNum = value; InitSlot(InitSlotStatus); Invalidate(); }
}
private int _TopSpaceHeight = 20;
/// <summary>
/// 料盘上部留白高度
/// </summary>
public int TopSpaceHeight
{
get { return _TopSpaceHeight; }
set { _TopSpaceHeight = value; }
}
private int _LeftSpaceWidth = 20;
/// <summary>
/// 料盘左边留白宽度
/// </summary>
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;
/// <summary>
/// X方向偏移
/// </summary>
public float OffsetX
{
get { return _OffsetX; }
set { _OffsetX = value; }
}
private float _OffsetY;
/// <summary>
/// Y方向偏移
/// </summary>
public float OffsetY
{
get { return _OffsetY; }
set { _OffsetY = value; }
}
private float _OffsetYEven;
/// <summary>
/// Y方向偏移偶数行
/// </summary>
public float OffsetYEven
{
get { return _OffsetYEven; }
set { _OffsetYEven = value; }
}
private bool _SinglePoint=false;
/// <summary>
/// 单点定位
/// </summary>
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++)
2 years ago
{
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);
2 years ago
}
}
UpdateSlotPos();
}
public void Fill()
{
foreach (KeyValuePair<int, TraySlot> kv in traySlotsDic)
2 years ago
{
ChangeStatus(kv.Value.Index, ESlotStatus.Have);
2 years ago
}
}
public void Clear()
{
foreach (KeyValuePair<int, TraySlot> kv in traySlotsDic)
2 years ago
{
ChangeStatus(kv.Value.Index, ESlotStatus.NotHave);
2 years ago
}
}
public void ChangeStatus(ESlotStatus status)
{
foreach (KeyValuePair<int, TraySlot> kv in traySlotsDic)
{
ChangeStatus(kv.Value.Index,status);
}
}
2 years ago
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)
2 years ago
{
for (int r = 0; r < RowNum; r++)
2 years ago
{
for (int c = 0; c < ColumnNum; c++)
2 years ago
{
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)
2 years ago
{
ShowColNumber = ShowRowNumber = false;
slotWidth = (this.panel2.Width) / ColumnNum;
slotHeight = (this.panel2.Height) / RowNum;
2 years ago
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);
2 years ago
}
}
}
}
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);
//}
}
}
}
2 years ago
panel2.Refresh();
}
private void panel2_Paint(object sender, PaintEventArgs e)
{
if(this.panel2.Width<=0 || this.panel2.Height<=0) { return; }
2 years ago
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));
}
}
2 years ago
}
if (c == 0)
{
if(ShowColNumber)
{
//画料盘的行号
g2.DrawString((r + 1).ToString(), new Font("宋体", 7.0F), new SolidBrush(Color.White), new PointF(5, TopSpaceHeight + (heightPer * r)));
}
2 years ago
}
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<TraySlot> drawSlots = new List<TraySlot>();
2 years ago
private void panel2_MouseUp(object sender, MouseEventArgs e)
{
drawRegion = false;
drawSlots.Clear();
foreach (KeyValuePair<int, TraySlot> kvSlot in traySlotsDic)
{
if (drawRect.IntersectsWith(kvSlot.Value.Bound))
{
drawSlots.Add(kvSlot.Value);
}
}
}
public List<TraySlot> GetDrawSlots()
{
return drawSlots;
2 years ago
}
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<int,TraySlot> kvSlot in traySlotsDic)
2 years ago
{
if (kvSlot.Value.Bound.Contains(e.Location))
2 years ago
{
find = true;
SelectSlot = kvSlot.Value;
2 years ago
break;
}
}
if (find)
{
if (SlotClickEvent != null)
SlotClickEvent(SelectSlot, e);
}
}
}
}
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
ChangeSlotStatus(ESlotStatus.Disable);
List<TraySlot> slots = new List<TraySlot>();
foreach (KeyValuePair<int, TraySlot> kvSlot in traySlotsDic)
{
if (drawRect.IntersectsWith(kvSlot.Value.Bound))
{
slots.Add(kvSlot.Value);
}
}
DrawTrayAfterEvent?.Invoke(this, ESlotStatus.Disable, slots);
2 years ago
}
private void ChangeSlotStatus(ESlotStatus status)
{
foreach (KeyValuePair<int, TraySlot> kvSlot in traySlotsDic)
2 years ago
{
if (drawRect.IntersectsWith(kvSlot.Value.Bound))
2 years ago
{
kvSlot.Value.SlotStatus = status;
2 years ago
}
}
UpdateSlotPos();
}
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
ChangeSlotStatus(ESlotStatus.Have);
List<TraySlot> slots = new List<TraySlot>();
foreach (KeyValuePair<int, TraySlot> kvSlot in traySlotsDic)
{
if (drawRect.IntersectsWith(kvSlot.Value.Bound))
{
slots.Add(kvSlot.Value);
}
}
DrawTrayAfterEvent?.Invoke(this, ESlotStatus.Have,slots);
2 years ago
}
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
ChangeSlotStatus(ESlotStatus.NotHave);
List<TraySlot> slots = new List<TraySlot>();
foreach (KeyValuePair<int, TraySlot> kvSlot in traySlotsDic)
{
if (drawRect.IntersectsWith(kvSlot.Value.Bound))
{
slots.Add(kvSlot.Value);
}
}
DrawTrayAfterEvent?.Invoke(this, ESlotStatus.NotHave,slots);
2 years ago
}
private void RsTray_Load(object sender, EventArgs e)
{
UpdateSlotPos();
}
2 years ago
}
/// <summary>
/// 料盘槽位
/// </summary>
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; }
}
2 years ago
private string _SN;
public string SN
{
get { return _SN; }
set { _SN = value; }
}
2 years ago
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;
2 years ago
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
2 years ago
{
g.DrawRectangle(new Pen(new SolidBrush(Color.FromArgb(11, 16, 36))), Bound.X, Bound.Y, Bound.Width, Bound.Height);
2 years ago
}
}
}
}
}