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(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 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 图片操作 /// /// 载入图片 /// /// public void LoadImage(Bitmap map) { cvImage.LoadImage(map); OnImageChanged?.Invoke(); } public void Clear() { cvImage.Clear(); } /// /// 设置图片为原始尺寸 /// public void SetMapSize() { cvImage.SetMapSize(); } /// /// 设置图片为适配尺寸 /// 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 SetElementDevicePara; public Action 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 pair in eleDict) // { // } //} public void SetNewROIType(IShapeElement element) { cvImage.DrawTemplate = element; } #endregion #region 事件 public event Action 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 } }