630 lines
19 KiB
C#
630 lines
19 KiB
C#
|
||
using DH.Commons.Enums;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Collections.ObjectModel;
|
||
using System.ComponentModel;
|
||
using System.Data;
|
||
using System.Drawing;
|
||
using System.Drawing.Drawing2D;
|
||
using System.Drawing.Imaging;
|
||
using System.Linq;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using System.Windows.Forms;
|
||
using static DH.Commons.Enums.EnumHelper;
|
||
|
||
|
||
|
||
namespace DH.UI.Model.Winform
|
||
{
|
||
public partial class Canvas : UserControl
|
||
{
|
||
readonly CanvasImage cvImage = new CanvasImage();
|
||
|
||
#region Grid
|
||
readonly GridCtrl gridCtrl = new GridCtrl();
|
||
|
||
private void GridValueChanged(int gridValue)
|
||
{
|
||
cvImage.GridValue = gridValue;
|
||
}
|
||
|
||
private void ShowGridChanged(bool isShowGrid)
|
||
{
|
||
cvImage.ShowGrid = isShowGrid;
|
||
}
|
||
|
||
private void GridColorChanged(Color obj)
|
||
{
|
||
cvImage.Pen_Grid.Color = obj;
|
||
}
|
||
#endregion
|
||
|
||
public Canvas()
|
||
{
|
||
InitializeComponent();
|
||
DoubleBuffered = true;
|
||
SetStyle(ControlStyles.OptimizedDoubleBuffer |
|
||
ControlStyles.ResizeRedraw |
|
||
ControlStyles.AllPaintingInWmPaint, true);
|
||
|
||
cvImage.Dock = DockStyle.Fill;
|
||
scMain.Panel1.Controls.Add(cvImage);
|
||
|
||
dgElements.AutoGenerateColumns = false;
|
||
|
||
var checkHead = new DataGridViewCheckboxHeaderCell();
|
||
checkHead.OnCheckBoxClicked += CheckHead_OnCheckBoxClicked;
|
||
dgElements.Columns[0].HeaderCell = checkHead;
|
||
dgElements.Columns[0].HeaderCell.Value = string.Empty;
|
||
|
||
Elements.CollectionChanged += Elements_CollectionChanged;
|
||
|
||
cvImage.OnMouseLocationUpdated = OnMouseLocationUpdated;
|
||
cvImage.OnMouseStateChanged += OnMouseStateChanged;
|
||
|
||
gridCtrl.IsShowGridChanged = ShowGridChanged;
|
||
gridCtrl.GridValueChanged = GridValueChanged;
|
||
gridCtrl.GridColorChanged = GridColorChanged;
|
||
gridCtrl.Padding = new Padding(0, 5, 0, 5);
|
||
tsTool.Items.Add(new GridCtrlHost(gridCtrl));
|
||
tsTool.Invalidate();
|
||
|
||
_eleCollectionChangedTimer = new System.Threading.Timer(OnElementCollectionChangedBufferTimer, null, -1, -1);
|
||
|
||
//tsmiShowStatusBar.Checked = tsmiShowToolBar.Checked = IsShowElementList = IsShowROITool = IsShowStatusBar = IsShowToolBar = false;
|
||
}
|
||
|
||
private void OnMouseStateChanged(MouseState ms)
|
||
{
|
||
if (ms != MouseState.SelectionZone && ms != MouseState.SelectionZoneDoing)
|
||
{
|
||
if (this.IsHandleCreated)
|
||
{
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
tsBtnModeSelection.Checked = false;
|
||
tsBtnModeNormal.Checked = true;
|
||
}));
|
||
}
|
||
}
|
||
}
|
||
|
||
#region 底部状态栏
|
||
public bool IsShowStatusBar
|
||
{
|
||
get => stsStatus.Visible;
|
||
set => stsStatus.Visible = value;
|
||
}
|
||
|
||
private void OnMouseLocationUpdated(Point screenPoint, PointF imagePoint, string colorDesc)
|
||
{
|
||
//await Task.Run(() => tsslLocation.Text = $"屏幕坐标X:{screenPoint.X},Y:{screenPoint.Y} 图片坐标X:{imagePoint.X},Y:{imagePoint.Y} 颜色:{colorDesc}");
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
tsslLocation.Text = $"屏幕坐标X:{screenPoint.X},Y:{screenPoint.Y} 图片坐标X:{imagePoint.X.ToString("f2")},Y:{imagePoint.Y.ToString("f2")} 颜色:{colorDesc}";
|
||
}));
|
||
}
|
||
|
||
//private void MouseLocationUpdated(Point screenPoint, Point imagePoint, string colorDesc)
|
||
//{
|
||
// if (InvokeRequired)
|
||
// {
|
||
// Invoke(new Action<Point, Point, string>(MouseLocationUpdated), screenPoint, imagePoint);
|
||
// }
|
||
// else
|
||
// {
|
||
// tsslLocation.Text = $"屏幕坐标X:{screenPoint.X},Y:{screenPoint.Y} 图片坐标X:{imagePoint.X},Y:{imagePoint.Y} 颜色:{colorDesc}";
|
||
// }
|
||
//}
|
||
#endregion
|
||
|
||
#region 属性
|
||
#region CanvasImage相关
|
||
//private MouseState mouseState = MouseState.Normal;
|
||
//public MouseState MouseState
|
||
//{
|
||
// get
|
||
// {
|
||
// return mouseState;
|
||
// }
|
||
// set
|
||
// {
|
||
// if (mouseState != value)
|
||
// {
|
||
// mouseState = value;
|
||
|
||
// tsslMouseState.Text = mouseState.ToString();
|
||
|
||
// if (mouseState >= MouseState.SelectionZone)
|
||
// {
|
||
// tsBtnModeSelection.Checked = true;
|
||
// }
|
||
// else
|
||
// {
|
||
// tsBtnModeNormal.Checked = true;
|
||
// }
|
||
// }
|
||
// }
|
||
//}
|
||
|
||
public string ImageFilePath { get; set; }
|
||
|
||
public Bitmap MAP
|
||
{
|
||
get => cvImage.MAP;
|
||
set => cvImage.MAP = value;
|
||
}
|
||
public Matrix Matrix
|
||
{
|
||
get => cvImage.Matrix;
|
||
set => cvImage.Matrix = value;
|
||
}
|
||
public MouseState MouseState
|
||
{
|
||
get => cvImage.MouseState;
|
||
set => cvImage.MouseState = value;
|
||
}
|
||
public ObservableCollection<IShapeElement> Elements
|
||
{
|
||
get => cvImage.Elements;
|
||
}
|
||
#endregion
|
||
|
||
private bool isShowElementList = false;
|
||
public bool IsShowElementList
|
||
{
|
||
get => isShowElementList;
|
||
set
|
||
{
|
||
//if (isShowElementList != value)
|
||
{
|
||
isShowElementList = value;
|
||
scMain.Panel2Collapsed = !value;
|
||
}
|
||
}
|
||
}
|
||
|
||
private bool isShowROITool = false;
|
||
public bool IsShowROITool
|
||
{
|
||
get => isShowROITool;
|
||
set
|
||
{
|
||
tsROIs.Visible = isShowROITool = value;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 图片操作
|
||
/// <summary>
|
||
/// 载入图片
|
||
/// </summary>
|
||
/// <param name="map"></param>
|
||
public void LoadImage(Bitmap map)
|
||
{
|
||
cvImage.LoadImage(map);
|
||
OnImageChanged?.Invoke();
|
||
}
|
||
public void Clear()
|
||
{
|
||
cvImage.Clear();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置图片为原始尺寸
|
||
/// </summary>
|
||
public void SetMapSize()
|
||
{
|
||
cvImage.SetMapSize();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置图片为适配尺寸
|
||
/// </summary>
|
||
public void SetScreenSize()
|
||
{
|
||
cvImage.SetScreenSize();
|
||
}
|
||
#endregion
|
||
|
||
#region 基元列表
|
||
private void chkShowChecked_CheckedChanged(object sender, EventArgs e)
|
||
{
|
||
dgElements.DataSource = null;
|
||
|
||
if (Elements != null && Elements.Count > 0)
|
||
{
|
||
if (chkShowChecked.Checked)
|
||
{
|
||
dgElements.DataSource = Elements.Where(u => u.IsEnabled && u.IsShowing).ToList();
|
||
}
|
||
else
|
||
{
|
||
dgElements.DataSource = Elements.Where(u => u.IsShowing).ToList();
|
||
}
|
||
}
|
||
}
|
||
|
||
private void CheckHead_OnCheckBoxClicked(object sender, DataGridViewCheckboxHeaderEventArgs e)
|
||
{
|
||
//foreach (IShapeElement ele in Elements)
|
||
//{
|
||
// ele.IsEnabled = e.CheckedState;
|
||
//}
|
||
for (int i = 0; i < Elements.Count; i++)
|
||
{
|
||
Elements[i].IsEnabled = e.CheckedState;
|
||
}
|
||
OnElementChanged(null);
|
||
}
|
||
|
||
private void dgElements_SelectionChanged(object sender, EventArgs e)
|
||
{
|
||
if (dgElements.SelectedRows.Count > 0)
|
||
{
|
||
var ele = Elements.FirstOrDefault(u => u.ID == dgElements.SelectedRows[0].Cells["colID"].Value.ToString());
|
||
propGridElement.SelectedObject = ele;
|
||
}
|
||
}
|
||
|
||
private void dgElements_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
|
||
{
|
||
if (dgElements.SelectedRows.Count > 0)
|
||
{
|
||
var ele = Elements.FirstOrDefault(u => u.ID == dgElements.SelectedRows[0].Cells["colID"].Value.ToString());
|
||
|
||
for (int i = 0; i < Elements.Count; i++)
|
||
{
|
||
Elements[i].State = ElementState.Normal;
|
||
}
|
||
|
||
ele.State = ElementState.Selected;
|
||
|
||
SetDeviceByElement?.Invoke(ele);
|
||
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
System.Threading.Timer _eleCollectionChangedTimer = null;
|
||
|
||
private void OnElementCollectionChangedBufferTimer(object state)
|
||
{
|
||
OnElementChanged(null);
|
||
for (int i = 0; i < Elements.Count; i++)
|
||
{
|
||
Elements[i].PropertyChanged -= Ele_PropertyChanged;
|
||
Elements[i].PropertyChanged += Ele_PropertyChanged;
|
||
}
|
||
//foreach (IShapeElement ele in Elements)
|
||
//{
|
||
// ele.PropertyChanged -= Ele_PropertyChanged;
|
||
// ele.PropertyChanged += Ele_PropertyChanged;
|
||
//}
|
||
}
|
||
|
||
private void Elements_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||
{
|
||
//_eleCollectionChangedTimer?.Change(200, -1);
|
||
OnElementChanged(null);
|
||
for (int i = 0; i < Elements.Count; i++)
|
||
{
|
||
Elements[i].PropertyChanged -= Ele_PropertyChanged;
|
||
Elements[i].PropertyChanged += Ele_PropertyChanged;
|
||
}
|
||
}
|
||
|
||
private void Ele_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||
{
|
||
if (e.PropertyName == "IsEnabled")
|
||
{
|
||
OnElementChanged(sender as IShapeElement);
|
||
}
|
||
else
|
||
{
|
||
Invoke(new Action(() =>
|
||
{
|
||
cvImage.Invalidate();
|
||
}));
|
||
}
|
||
}
|
||
|
||
private void OnElementChanged(IShapeElement ele)
|
||
{
|
||
if (ele != null)
|
||
OnElementChangedHandle?.Invoke(ele);
|
||
|
||
if (InvokeRequired)
|
||
{
|
||
Invoke(new Action(() => OnElementChanged(ele)));
|
||
}
|
||
else
|
||
{
|
||
if (isShowElementList)
|
||
{
|
||
dgElements.DataSource = null;
|
||
if (Elements != null && Elements.Count > 0)
|
||
{
|
||
if (chkShowChecked.Checked)
|
||
{
|
||
dgElements.DataSource = Elements.ToList().Where(u => u.IsEnabled && u.IsShowing).ToList();
|
||
}
|
||
else
|
||
{
|
||
dgElements.DataSource = Elements.ToList().Where(u => u.IsShowing).ToList();
|
||
}
|
||
}
|
||
Invalidate();
|
||
}
|
||
}
|
||
}
|
||
|
||
private void propGridElement_SelectedObjectsChanged(object sender, EventArgs e)
|
||
{
|
||
propGridElement.ExpandAllGridItems();
|
||
}
|
||
|
||
#region 基元列表右键菜单
|
||
private void tsmiResort_Click(object sender, EventArgs e)
|
||
{
|
||
//Elements.Sort();
|
||
}
|
||
|
||
private void tsmiClearActualValue_Click(object sender, EventArgs e)
|
||
{
|
||
//foreach (IShapeElement ele in Elements)
|
||
//{
|
||
// if (ele.IsEnabled)
|
||
// {
|
||
// ele.SetActualValue(0.0);
|
||
// }
|
||
//}
|
||
}
|
||
|
||
private void tsmiInitialState_Click(object sender, EventArgs e)
|
||
{
|
||
//foreach (IShapeElement ele in Elements)
|
||
//{
|
||
// if (ele.IsEnabled)
|
||
// {
|
||
// ele.State = ElementState.Normal;
|
||
// ele.InitialMeasureResult();
|
||
// }
|
||
//}
|
||
}
|
||
|
||
private void tsmiClearStandardValue_Click(object sender, EventArgs e)
|
||
{
|
||
//foreach (IShapeElement ele in Elements)
|
||
//{
|
||
// if (ele.IsEnabled)
|
||
// {
|
||
// ele.SetStandardValue(0.0);
|
||
// }
|
||
//}
|
||
}
|
||
#endregion
|
||
#endregion
|
||
|
||
#region 图像区域右键菜单
|
||
private void tsmiKeepUnselected_Click(object sender, EventArgs e)
|
||
{
|
||
KeepElements(false);
|
||
}
|
||
|
||
private void tsmiKeepSelected_Click(object sender, EventArgs e)
|
||
{
|
||
KeepElements(true);
|
||
}
|
||
|
||
private void KeepElements(bool isKeepSelected)
|
||
{
|
||
for (int i = 0; i < Elements.Count; i++)
|
||
{
|
||
var ele = Elements[i];
|
||
if (ele.IsEnabled)
|
||
{
|
||
if (ele.State == ElementState.Selected)
|
||
{
|
||
ele.IsEnabled = isKeepSelected;
|
||
}
|
||
else
|
||
{
|
||
ele.IsEnabled = !isKeepSelected;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void tsmiUnselectElements_Click(object sender, EventArgs e)
|
||
{
|
||
//if (MouseState == MouseState.SelectedElement)
|
||
//{
|
||
// MouseState = MouseState.Normal;
|
||
|
||
// //Elements.ForEach(ele =>
|
||
// foreach (IShapeElement ele in Elements)
|
||
// {
|
||
// ele.State = ElementState.Normal;
|
||
// }
|
||
// //);
|
||
//}
|
||
}
|
||
#endregion
|
||
|
||
#region 基元的设备属性 运动设置和相机设置
|
||
public Action<IShapeElement> SetElementDevicePara;
|
||
|
||
public Action<IShapeElement> SetDeviceByElement;
|
||
#endregion
|
||
|
||
#region 一般操作工具条
|
||
public bool IsShowToolBar
|
||
{
|
||
get => tsTool.Visible;
|
||
set => tsTool.Visible = value;
|
||
}
|
||
|
||
private void tsBtnLoadImage_Click(object sender, EventArgs e)
|
||
{
|
||
Thread InvokeThread = new Thread(new ThreadStart(OpenLoadImage));
|
||
InvokeThread.SetApartmentState(ApartmentState.STA);
|
||
InvokeThread.Start();
|
||
InvokeThread.Join();
|
||
}
|
||
|
||
private void OpenLoadImage()
|
||
{
|
||
ImageFilePath = "";
|
||
OpenFileDialog ofd = new OpenFileDialog();
|
||
if (ofd.ShowDialog() == DialogResult.OK)
|
||
{
|
||
ImageFilePath = ofd.FileName;
|
||
LoadImage((Bitmap)Bitmap.FromFile(ImageFilePath));
|
||
}
|
||
}
|
||
|
||
private void tsBtnSaveImage_Click(object sender, EventArgs e)
|
||
{
|
||
if (MAP == null)
|
||
return;
|
||
|
||
SaveFileDialog sfd = new SaveFileDialog();
|
||
sfd.Filter = "JPG文件|*.jpg|BMP文件|*.bmp";
|
||
if (sfd.ShowDialog() == DialogResult.OK)
|
||
{
|
||
string filePath = sfd.FileName;
|
||
if (filePath.EndsWith("bmp"))
|
||
{
|
||
MAP.Save(filePath, ImageFormat.Bmp);
|
||
}
|
||
else
|
||
{
|
||
MAP.Save(filePath, ImageFormat.Jpeg);
|
||
}
|
||
MessageBox.Show("图片保存成功!");
|
||
}
|
||
}
|
||
|
||
private void tsBtnSaveImageWithElements_Click(object sender, EventArgs e)
|
||
{
|
||
if (MAP == null)
|
||
return;
|
||
|
||
SaveFileDialog sfd = new SaveFileDialog();
|
||
sfd.Filter = "JPG文件|*.jpg|BMP文件|*.bmp";
|
||
if (sfd.ShowDialog() == DialogResult.OK)
|
||
{
|
||
string filePath = sfd.FileName;
|
||
|
||
Bitmap bmp = new Bitmap(MAP.Width, MAP.Height, PixelFormat.Format32bppArgb);
|
||
//Bitmap bmp = new Bitmap(MAP.Width, MAP.Height, MAP.PixelFormat);
|
||
//Bitmap bmp = new Bitmap(MAP.Width, MAP.Height);
|
||
using (Graphics g = Graphics.FromImage(bmp))
|
||
{
|
||
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
|
||
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
|
||
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
|
||
g.DrawImage(MAP, 0, 0);
|
||
|
||
for (int i = 0; i < Elements.Count; i++)
|
||
{
|
||
var ele = Elements[i];
|
||
if (ele.IsEnabled)
|
||
ele.Draw(g);
|
||
}
|
||
}
|
||
|
||
if (filePath.EndsWith("bmp"))
|
||
{
|
||
bmp.Save(filePath, ImageFormat.Bmp);
|
||
}
|
||
else
|
||
{
|
||
bmp.Save(filePath, ImageFormat.Jpeg);
|
||
}
|
||
MessageBox.Show("带基元图片保存成功!");
|
||
}
|
||
}
|
||
|
||
private void tsBtnMapSize_Click(object sender, EventArgs e)
|
||
{
|
||
SetMapSize();
|
||
}
|
||
|
||
private void tsBtnModeNormal_CheckedChanged(object sender, EventArgs e)
|
||
{
|
||
var btn = sender as ToolStripButton;
|
||
if (btn.Checked)
|
||
{
|
||
btn.BackColor = SystemColors.ActiveCaption;
|
||
|
||
foreach (ToolStripItem c in tsTool.Items)
|
||
{
|
||
if (c is ToolStripButton)
|
||
{
|
||
if (c.Name.StartsWith("tsBtnMode") && c.Name != btn.Name)
|
||
{
|
||
var temp = c as ToolStripButton;
|
||
temp.Checked = false;
|
||
temp.BackColor = SystemColors.Control;
|
||
}
|
||
}
|
||
}
|
||
|
||
switch (btn.Name)
|
||
{
|
||
case "tsBtnModeNormal":
|
||
MouseState = MouseState.Normal;
|
||
break;
|
||
case "tsBtnModeSelection":
|
||
MouseState = MouseState.SelectionZone;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
private void tsBtnScreenSize_Click(object sender, EventArgs e)
|
||
{
|
||
SetScreenSize();
|
||
}
|
||
#endregion
|
||
|
||
#region 基元工具条
|
||
//private void LoadElementTools()
|
||
//{
|
||
// var eleDict = ElementFactory.GetAllElementsInfo();
|
||
|
||
// foreach (KeyValuePair<ElementAttribute, Type> pair in eleDict)
|
||
// {
|
||
|
||
// }
|
||
//}
|
||
|
||
public void SetNewROIType(IShapeElement element)
|
||
{
|
||
cvImage.DrawTemplate = element;
|
||
}
|
||
#endregion
|
||
|
||
#region 事件
|
||
public event Action<IShapeElement> OnElementChangedHandle;
|
||
public event Action OnImageChanged;
|
||
#endregion
|
||
|
||
#region 工具栏显示/隐藏右键菜单
|
||
private void tsmiShowToolBar_CheckedChanged(object sender, EventArgs e)
|
||
{
|
||
//IsShowToolBar = tsmiShowToolBar.Checked;
|
||
}
|
||
|
||
private void tsmiShowStatusBar_CheckedChanged(object sender, EventArgs e)
|
||
{
|
||
//IsShowStatusBar = tsmiShowStatusBar.Checked;
|
||
}
|
||
#endregion
|
||
}
|
||
}
|