当前位置: 首页 > news >正文

WPF Canvas draw circle,triangle,rectangle such as mark

image

 

 

 

 

 

 

image

 

 

 

 

 

 

image

 

 

 

 

 

 

 

image

 

 

 

//Window.xaml
<Window x:Class="WpfApp15.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfApp15"mc:Ignorable="d"WindowState="Maximized"Title="MainWindow" Height="450" Width="800"><Grid><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="*"/></Grid.RowDefinitions><StackPanel Grid.Row="0"Orientation="Horizontal"><StackPanel.Resources><Style TargetType="CheckBox"><Setter Property="FontSize" Value="50"/></Style></StackPanel.Resources><CheckBox Content="Triangle" x:Name="triangleChx"                      Checked="triangleCbx_Checked"/><CheckBox Content="Circle" x:Name="circleChx" Checked="circleCbx_Checked"/><CheckBox Content="Rectangle" x:Name="rectangleChx"Checked="rectangleChx_Checked"/></StackPanel><Canvas Grid.Row="1"x:Name="cvs"HorizontalAlignment="Stretch"VerticalAlignment="Stretch"Background="Transparent"MouseLeftButtonDown="cvs_MouseLeftButtonDown"/></Grid>
</Window>//Window.xaml.cs
using Microsoft.Win32;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;namespace WpfApp15
{/// <summary>/// Interaction logic for MainWindow.xaml/// </summary>public partial class MainWindow : Window{private double sideLength = 100.0d;int idx = 0;public MainWindow(){InitializeComponent();}private void cvs_MouseLeftButtonDown(object sender, MouseButtonEventArgs e){var pt = Mouse.GetPosition(cvs);if (triangleChx.IsChecked == true){DrawTriangle(pt);}else if (circleChx.IsChecked == true){DrawCircle(pt);}else if (rectangleChx.IsChecked == true){DrawRectangle(pt);}}private void DrawRectangle(Point pt){Rectangle rect = new Rectangle();rect.Fill = new SolidColorBrush(Colors.Blue);rect.Stroke = Brushes.Black;  rect.StrokeThickness = 2;rect.Width= sideLength;rect.Height= sideLength;rect.ToolTip = $"{++idx},Center.X:{pt.X},Center.Y:{pt.Y}";Canvas.SetLeft(rect, pt.X - sideLength / 2);Canvas.SetTop(rect, pt.Y - sideLength / 2);cvs.Children.Add(rect);}private void DrawCircle(Point pt){Ellipse elp=new Ellipse();elp.Width= sideLength;elp.Height= sideLength;elp.Stroke = Brushes.Black;elp.StrokeThickness = 2;            elp.Fill = new SolidColorBrush(Colors.Cyan);elp.ToolTip =$"{++idx},Center.X:{pt.X},Center.Y:{pt.Y}";Canvas.SetLeft(elp, pt.X - sideLength / 2);Canvas.SetTop(elp, pt.Y - sideLength / 2);cvs.Children.Add(elp);}private void DrawTriangle(Point centerPt){try{double centerX = centerPt.X;double centerY = centerPt.Y;double height = (Math.Sqrt(3) / 2) * sideLength;Point topPt = new Point(centerX, centerY - height / 2);Point leftPt = new Point(centerX - sideLength / 2, centerY + height / 2);Point rightPt = new Point(centerX + sideLength / 2, centerY + height / 2);var triangle = new Polygon(){Stroke = Brushes.Black,StrokeThickness = 2,Fill = Brushes.Red};triangle.Points.Add(topPt);triangle.Points.Add(leftPt);triangle.Points.Add(rightPt);triangle.ToolTip = $"Id:{++idx},Center.X:{centerPt.X},Center.Y:{centerPt.Y}";CreateTriagnleWithContextMenu(triangle);cvs.Children.Add(triangle);}catch (Exception ex){MessageBox.Show(ex.Message);}}private void CreateTriagnleWithContextMenu(Polygon triangle){ContextMenu contextMenu = new ContextMenu();//Save As Picture menu item.MenuItem saveMenuItem = new MenuItem();saveMenuItem.Header = "Save As Picture";saveMenuItem.Tag = triangle;saveMenuItem.Click += (s, e) => SaveTriangleAsPicture(s, e);//RemoveMenuItem removeItem = new MenuItem();removeItem.Header = "Remove Triangle";removeItem.Tag = triangle;removeItem.Click += (s, e) => RemoveTriangle(s, e);contextMenu.Items.Add(saveMenuItem);contextMenu.Items.Add(removeItem);triangle.ContextMenu = contextMenu;triangle.MouseRightButtonDown += (s, e) =>{triangle.ContextMenu.IsOpen = true;e.Handled = true;};}private void RemoveTriangle(object sender, RoutedEventArgs e){try{var triangle = (sender as MenuItem)?.Tag as Polygon;if (triangle != null){cvs.Children.Remove(triangle);triangle = null;MessageBox.Show("Triangle has been removed!");}}catch (Exception ex){MessageBox.Show(ex.Message);}}private void SaveTriangleAsPicture(object sender, RoutedEventArgs e){var triangle = (sender as MenuItem)?.Tag as Polygon;if (triangle == null){MessageBox.Show("No triangle to save!");return;}try{SaveFileDialog dialog = new SaveFileDialog(){Filter = "PNG Image|*.png|Jpeg Image|*.jpg|BMP Image|*.bmp",Title = "Save Triangle as Picture",FileName = $"Triangle_{DateTime.Now:yyyyMMddHHmmssffff}.png"};if (dialog.ShowDialog() == true){BitmapEncoder bmpEncoder = System.IO.Path.GetExtension(dialog.FileName).ToLower() switch{".jpg" or ".jpeg" => new JpegBitmapEncoder(),".bmp" => new BmpBitmapEncoder(),_ => new PngBitmapEncoder()};// Calculate the bounds of the triangleRect bounds = GetTriangleBounds(triangle);// Add some padding around the triangledouble padding = 10;bounds = new Rect(bounds.X - padding,bounds.Y - padding,bounds.Width + padding * 2,bounds.Height + padding * 2);// Create a visual for the triangle onlyDrawingVisual drawingVisual = new DrawingVisual();using (DrawingContext drawingContext = drawingVisual.RenderOpen()){// Draw white backgrounddrawingContext.DrawRectangle(Brushes.White, null, bounds);// Draw the triangle
                        DrawTriangleGeometry(drawingContext, triangle, bounds);}var dpi = VisualTreeHelper.GetDpi(this);// Render the visual to bitmapRenderTargetBitmap rtb = new RenderTargetBitmap((int)(bounds.Width * dpi.DpiScaleX),(int)(bounds.Height * dpi.DpiScaleY),dpi.PixelsPerInchX,dpi.PixelsPerInchY,PixelFormats.Pbgra32);rtb.Render(drawingVisual);// Save to fileusing (FileStream fileStream = new FileStream(dialog.FileName, FileMode.Create)){bmpEncoder.Frames.Add(BitmapFrame.Create(rtb));bmpEncoder.Save(fileStream);}MessageBox.Show($"Triangle saved as {dialog.FileName} successfully!");}}catch (Exception ex){MessageBox.Show(ex.Message);}}private Rect GetTriangleBounds(Polygon triangle){if (triangle.Points.Count == 0){return new Rect(0, 0, sideLength, sideLength);}double minX = triangle.Points[0].X;double maxX = triangle.Points[0].X;double minY = triangle.Points[0].Y;double maxY = triangle.Points[0].Y;foreach (Point point in triangle.Points){if (point.X < minX){minX = point.X;}if (point.X > maxX){maxX = point.X;}if (point.Y < minY){minY = point.Y;}if (point.Y > maxY){maxY = point.Y;}}return new Rect(minX, minY, maxX - minX, maxY - minY);}private void DrawTriangleGeometry(DrawingContext drawingContext,Polygon triangle, Rect bounds){// Create a stream geometry for the triangleStreamGeometry geometry = new StreamGeometry();using (StreamGeometryContext streamGeoContext = geometry.Open()){streamGeoContext.BeginFigure(triangle.Points[0], true, true);streamGeoContext.PolyLineTo(new List<Point>(triangle.Points), true, true);}// Apply translation to position the triangle correctlyTransformGroup transformGroup = new TransformGroup();transformGroup.Children.Add(new TranslateTransform(-bounds.X, -bounds.Y));geometry.Transform = transformGroup;geometry.Freeze();// Draw the triangle with the same properties as the originaldrawingContext.DrawGeometry(triangle.Fill, new Pen(triangle.Stroke,triangle.StrokeThickness), geometry);}private void triangleCbx_Checked(object sender, RoutedEventArgs e){circleChx.IsChecked = false;rectangleChx.IsChecked = false;}private void circleCbx_Checked(object sender, RoutedEventArgs e){triangleChx.IsChecked = false;rectangleChx.IsChecked = false;}private void rectangleChx_Checked(object sender, RoutedEventArgs e){circleChx.IsChecked = false;triangleChx.IsChecked = false;}}
}

 

http://www.jsqmd.com/news/5128/

相关文章:

  • 论文解读-《Less is More on the Over-Globalizing Problem in Graph Transformers》 - zhang
  • loguru 日志库快速入门
  • MATLAB工具箱
  • 内存访问流程
  • .NET操作Word实现智能文档处理 - 内容查找替换与书签操作
  • day19_添加 修改
  • day18_查询功能 合并servlet
  • NOIP模拟赛 十七
  • day22_用户模块
  • 2025 丹东店推荐:丽格门窗,用 20 年技术沉淀守护家的舒适
  • NOIP2025模拟赛23
  • step
  • 2025 呼和浩特店推荐:丽格门窗,用 20 年技术沉淀守护家的温度
  • 深入解析:浏览器端音视频处理新选择:Mediabunny 让 Web 媒体开发飞起来
  • 2025 宁波门窗店推荐:丽格门窗,甬城品质家居的安心之选
  • 移动硬盘上的文件消失了?以下是Mac电脑解除方法
  • 2025 贵阳门窗店优选:丽格门窗,用 20 年匠心适配高原宜居需求
  • 2025 济南门窗店选购指南:丽格门窗凭硬实力圈粉品质家庭
  • “鹏云杯”第十二届山东省大学生网络安全技能大赛 -- Crypto -- WriteUp
  • 服务器系统时间不对?Linux系统时间修改与同步全面指南
  • 处理限流、缓存与数据一致性:1688 API 实时数据采集的强大的技术细节
  • 9/27
  • 2025 常熟门窗店优选:丽格门窗,20 年技术沉淀的品质之选
  • 2025上海门窗店选购选丽格!20 年系统门窗经验,徐汇宜山路店品质之选
  • 2025GUI工程实践:Unity编辑模式下GUI运行
  • 哦好多天没写了水一下吧
  • 实用指南:Apache、Nginx 和 Tomcat 的区别
  • python+uniapp基于微信小程序美食点餐实用的系统
  • parted command for linuxg
  • 如何在不绑定Apple账号的情况下备份florr.io