WPF Canvas mark triangle, circle, and retangle, then save the whole canvas as jpg file

news/2025/9/28 14:30:32/文章来源:https://www.cnblogs.com/Fred1987/p/19116605
Install-Package Wpf.Prism;

 

 

 private void SaveAsJpgCommandExecuted(){var dpi=VisualTreeHelper.GetDpi(this);RenderTargetBitmap rtb=new RenderTargetBitmap((int)(cvs.ActualWidth*dpi.DpiScaleY), (int)(cvs.ActualHeight*dpi.DpiScaleY),dpi.PixelsPerInchX,dpi.PixelsPerInchY,PixelFormats.Pbgra32);rtb.Render(cvs);SaveFileDialog dialog = new SaveFileDialog();dialog.Filter = $"JPG Files|*.jpg";dialog.FileName = $"Canvas{DateTime.Now.ToString("yyyyMMddHHmmssffff")}.jpg";if(dialog.ShowDialog()==true){using (FileStream fs = new FileStream(dialog.FileName, FileMode.Create)){JpegBitmapEncoder encoder = new JpegBitmapEncoder();encoder.Frames.Add(BitmapFrame.Create(rtb));encoder.Save(fs);MessageBox.Show($"Saved in {dialog.FileName}!");}}            }

 

 

 

 

 

 

 

image

 

 

 

 

 

 

image

 

 

 

 

 

 

 

 

 

 

//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"><Canvas.ContextMenu><ContextMenu><MenuItem Header="Save As Picture"Command="{Binding SaveAsJpgCommand}"/></ContextMenu></Canvas.ContextMenu></Canvas></Grid>
</Window>//cs
using Microsoft.Win32;
using System.Diagnostics.Tracing;
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;Image img;public DelegateCommand SaveAsJpgCommand { get; set; }public MainWindow(){InitializeComponent();this.DataContext = this;this.Loaded += MainWindow_Loaded;this.SizeChanged += MainWindow_SizeChanged;SaveAsJpgCommand = new DelegateCommand(SaveAsJpgCommandExecuted);}private void SaveAsJpgCommandExecuted(){var dpi=VisualTreeHelper.GetDpi(this);RenderTargetBitmap rtb=new RenderTargetBitmap((int)(cvs.ActualWidth*dpi.DpiScaleY), (int)(cvs.ActualHeight*dpi.DpiScaleY),dpi.PixelsPerInchX,dpi.PixelsPerInchY,PixelFormats.Pbgra32);rtb.Render(cvs);SaveFileDialog dialog = new SaveFileDialog();dialog.Filter = $"JPG Files|*.jpg";dialog.FileName = $"Canvas{DateTime.Now.ToString("yyyyMMddHHmmssffff")}.jpg";if(dialog.ShowDialog()==true){using (FileStream fs = new FileStream(dialog.FileName, FileMode.Create)){JpegBitmapEncoder encoder = new JpegBitmapEncoder();encoder.Frames.Add(BitmapFrame.Create(rtb));encoder.Save(fs);MessageBox.Show($"Saved in {dialog.FileName}!");}}            }private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e){if (img != null && cvs.ActualWidth > 0 && cvs.ActualHeight > 0){img.Width = cvs.ActualWidth;img.Height = cvs.ActualHeight;}}private void MainWindow_Loaded(object sender, RoutedEventArgs e){InitImg();}private void InitImg(){BitmapImage bmi = new BitmapImage();bmi.BeginInit();bmi.UriSource = new Uri(@"../../../Images/1.jpg", UriKind.RelativeOrAbsolute);bmi.EndInit();bmi.Freeze();img = new Image();img.Stretch = Stretch.UniformToFill;img.Source = bmi;img.Width = cvs.ActualWidth;img.Height = cvs.ActualHeight;// Add to canvas at position (0,0)Canvas.SetLeft(img, 0);Canvas.SetTop(img, 0);// Ensure image is at the back (z-index)Panel.SetZIndex(img, -1);cvs.Children.Add(img);}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.mzph.cn/news/920731.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网站开发毕业设计周志wordpress sae 主题

BP神经网络 答案&#xff1a;是的&#xff0c;BP神经网络需要像深度学习一次次的迭代训练。总结&#xff08;BP神经网络和深度学习在本质上有以下区别&#xff09; 答案&#xff1a;是的&#xff0c;BP神经网络需要像深度学习一次次的迭代训练。 BP神经网络&#xff08;误差反…

北京牛鼻子网站建设公司m3u8插件 wordpress

重点&#xff1a; 1.程序项目做出来了&#xff0c;需要打包发布给用户。如何打包是关键。 2.采用InstallShield软件进行发布。 步骤一&#xff1a;创建一个依赖三方库配置环境的bat文件的项目。 &#xff08;主要测试三方库打包 和如果有bat文件&#xff0c;需要先创建环境&…

自动遍历测试利器:开源工具AppCrawler 配置全解析

Appcrawler是一个基于自动遍历的App爬虫工具,支持Android和IOS,支持真机和模拟器。最大的特点是灵活性高,可通过配置来设定遍历的规则。 配置文件格式 执行参数与配置文件 capability设置:与appium完全一致 testca…

得帆云ETL全新版本升级驱动数据高效流转

在数字化浪潮持续深化的背景下,数据已成为企业核心战略资产,高效的数据处理与集成能力,更是企业在数据驱动时代构筑竞争优势的关键支撑。 得帆云基于对技术创新的持续深耕及客户业务需求的深度洞察,正式推出ETL系统…

集成微信的企业网站管理系统凌河建设网站

一、Hadoop 1.x 和 2.x 的区别 二、HDFS架构 1&#xff09;NameNode&#xff08;nn&#xff09;&#xff1a;存储文件的元数据&#xff0c;如文件名&#xff0c;文件目录结构&#xff0c;文件属性&#xff08;生成时间、副本数、文件权限&#xff09;&#xff0c;以及每个文件…

挖同行墙脚!有稳定供应商的客户怎么下手构建?

挖同行墙脚!有稳定供应商的客户怎么下手构建?pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &…

兰州网站优化服务企业建立网站

闭包是功能性自包含模块,可以在代码中被传递和使用。 Swift 中的闭包与 C 和 Objective-C 中的 blocks 以及其他一些编程语言中的 lambdas 比较相似。 闭包的形式主要有三种&#xff1a; 1. 全局函数是一个有名字但不会捕获任何值的闭包 2. 嵌套函数是一个有名字并可以捕获其封…

开源技术崛起:中国如何构建数字经济时代的创新基础设施

开源技术崛起:中国如何构建数字经济时代的创新基础设施 在数字经济成为全球竞争新赛道的今天,开源技术已从单纯的软件开发模式跃升为国家战略级创新基础设施。中国开发者群体规模突破900万大关,本土代码托管平台通过…

250928

目录JT-JY5T2S1-1JT-JY5T2S1-2FT-(JY&VOAs) JT-JY5T2S1-1Good morning, North College Library, How can i help you? I was wondering if it will possible to join the library? Are you a student in North C…

解析网站dnshtml5做网站心得体会

232.用栈实现队列 232. 用栈实现队列 简单 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; 实现 MyQueue 类&#xff1a; void push(int x) 将元素 x 推到队列的末尾int pop() 从队列…

北京做网站比较好的公司兼容ie8的网站模板

文章目录 1 SQLite1.1 世界上最流行的数据库1.1 SQLite简介1.2 插入语句1.3 查询数据1.4 更新数据1.5 删除数据2 DuckDB2.1 DuckDB简介2.2 DuckDB与Python结合使用2.2.1 创建表2.2.2 分析语句2.2.3 导出为parquet文件2.3 Windows中使用DuckDB3 参考附录1 SQLite Python的一个特…

地图商业授权共享 - no

地图商业授权共享 百度、高德、腾讯三大地图商业授权起步都是:5万元/年。 小企业难顶。 有需要的老铁,可以付费共享,好商量。加WX:E2E188

DevOps平台选型指南:数字化转型中的技术决策关键

DevOps平台选型指南:数字化转型中的技术决策关键 在数字化转型浪潮席卷全球的当下,DevOps平台已经从单纯的技术工具演变为企业技术架构的战略性组成部分。随着云计算、微服务架构和持续交付理念的普及,企业面临着如…

window 安全模式卸载任何软件

win+R 命令行 输入msconfig 打开系统配置 切换到引导页签,勾选安全引导后选择重启,重启后即为安全模式 安全模式下找到软件所在的文件目录,暴力删除即可,一次删除不干净,多重启几次删除就好了I have a dream : San…

定制笔记本电脑工厂排名:从基础代工到联合设计全面分析 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

题解:qoj1261 Inv

题意:给出 \(n,k\),求满足 \(p(p(i)) = i\) 且逆序对数等于 \(k\) 的排列数量对 \(2\) 取模。 做法: 对 \(2\) 取模,很神秘的东西,考虑找找性质。 注意到 \(p,p^{-1}\) 逆序对数一样,且满足条件的 \(p\) 满足 \(…

sv 去除字符串行尾空格函数

字符串去除行尾空格 函数 // 去除字符串末尾的换行符和空格符 function string remove_trailing_whitespace(string str);int len = str.len();int last_valid_index = -1;// 空字符串直接返回if (len == 0) return &q…

这么做3d展示网站展示网站欣赏

昨晚帮师姐整理测试&#xff0c;没有时间写日志&#xff0c;今天一大早补上。 十一长假之后的第一个工作日&#xff0c;老师回来了。详细汇报了整个假期的学习之后&#xff0c;老师整理了以后我的学习任务。本来觉得没多少事情&#xff0c;可是细数了一下&#xff0c;竟然光论文…

可以直接进入的网站正能量大豆网怎么用apache做网站

深度学习推理速度优化指南 简介一、显卡频率设置二、查看当前显卡频率三、调整显卡频率范围注意事项总结 简介 本文旨在探讨深度学习推理过程中 CUDA 或 TensorRT 推理速度变慢的问题&#xff0c;并提供实用的解决策略。我们将从显卡频率设置、模型权重优化等方面出发&#xf…