WPF canvas Draw line , ellipse and rectangle, save canvas and contents as picture

//xaml
<Window x:Class="WpfApp417.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:WpfApp417"
        mc:Ignorable="d"
        WindowState="Maximized"
        KeyDown="Window_KeyDown"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <ToolBar Grid.Row="0">
            <Button Content="Set Background" Click="SetBackgroundClick" Width="150" Background="Cyan"/>
            <RadioButton x:Name="drawLinesRadio" IsChecked="True" Content="Draw Lines" GroupName="DrawShapeGroup"/>
            <RadioButton x:Name="drawEllipseRadio" Content="Draw Ellipse" GroupName="DrawShapeGroup"/>
            <RadioButton x:Name="drawRectRadio" Content="Draw Rect" GroupName="DrawShapeGroup"/>
            <Button Content="Save As Picture" Click="SavePicClick" Width="150" Background="Cyan"/>
        </ToolBar>
        <Canvas Grid.Row="1" x:Name="cvs"
                MouseDown="cvs_MouseDown"
                MouseMove="cvs_MouseMove"
                MouseUp="cvs_MouseUp">
            <Canvas.Background>
                <ImageBrush ImageSource="Images/1.jpg"/>
            </Canvas.Background>
            <Canvas.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="Save As Picture" 
                              Click="SavePicClick"/>
                </ContextMenu>
            </Canvas.ContextMenu>
        </Canvas>
    </Grid>
</Window>


//xaml.cs

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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;
using System.IO;

namespace WpfApp417
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.S)
            {
                SaveCvsAsPicture();
            }
        }

        private void SaveCvsAsPicture()
        {
            SaveCanvasAndContentAsPicture();
        }


        Point oldPt { get; set; }
        Point newPt { get; set; }

        bool isDrawing = false;
        private void cvs_MouseDown(object sender, MouseButtonEventArgs e)
        {
            oldPt = e.GetPosition(cvs);
        }

        private void cvs_MouseMove(object sender, MouseEventArgs e)
        {
            isDrawing = true;
        }

        private void cvs_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (drawLinesRadio.IsChecked == true)
            {
                DrawLineInCanvas(e);
            }
            else if(drawEllipseRadio.IsChecked==true)
            {
                DrawEllipseInCanvas(e);
            }
            else if(drawRectRadio.IsChecked==true)
            {
                DrawRectangleInCanvas(e);
            }
        }

        private void DrawRectangleInCanvas(MouseButtonEventArgs e)
        {
            Rectangle rect = new Rectangle();
            newPt = e.GetPosition(cvs);
            double rectWidth = newPt.X - oldPt.X;
            double rectHeight=newPt.Y - oldPt.Y;

            rect.Width = Math.Abs(rectWidth);
            rect.Height =Math.Abs(rectHeight);
            rect.Stroke = new SolidColorBrush(Colors.Blue);
            rect.StrokeThickness = 5;
            rect.Fill = new SolidColorBrush(Colors.Red);
            Canvas.SetLeft(rect, e.GetPosition(cvs).X - rectWidth);
            Canvas.SetTop(rect, e.GetPosition(cvs).Y - rectHeight);
            if (!cvs.Children.Contains(rect))
            {
                cvs.Children.Add(rect);
            }
        }

        private void DrawEllipseInCanvas(MouseButtonEventArgs e)
        {
            Ellipse elp = new Ellipse();
            newPt = e.GetPosition(cvs);
            double elpWidth= (newPt.X - oldPt.X)*2;
            double elpHeight=(newPt.Y - oldPt.Y)*2;
            elp.Width =Math.Abs(elpWidth);
            elp.Height =Math.Abs(elpHeight);
            elp.Stroke = new SolidColorBrush(Colors.Blue);
            elp.StrokeThickness = 5;
            elp.Fill = new SolidColorBrush(Colors.Red);
            Canvas.SetLeft(elp, e.GetPosition(cvs).X - elp.Width/2);
            Canvas.SetTop(elp, e.GetPosition(cvs).Y-elp.Height/2);
            if (!cvs.Children.Contains(elp))
            {
                cvs.Children.Add(elp);
            }
        }

        private void DrawLineInCanvas(MouseButtonEventArgs e)
        {
            if (e.ChangedButton == MouseButton.Left
                && e.ButtonState == MouseButtonState.Released
                && isDrawing)
            {
                newPt = e.GetPosition(cvs);
                Line ln = new Line();
                ln.X1 = oldPt.X;
                ln.Y1 = oldPt.Y;
                ln.X2 = newPt.X;
                ln.Y2 = newPt.Y;
                ln.Stroke = new SolidColorBrush(Colors.Red);
                ln.StrokeThickness = 5;
                ln.StrokeEndLineCap = PenLineCap.Triangle;
                if (!cvs.Children.Contains(ln))
                {
                    cvs.Children.Add(ln);
                }
                isDrawing = false;
            }
        }

        private void SavePicClick(object sender, RoutedEventArgs e)
        {
            SaveCanvasAndContentAsPicture();           
        }

        private void SaveCanvasAndContentAsPicture()
        {
            RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap((int)cvs.ActualWidth,
               (int)cvs.ActualHeight, 96d, 96d, PixelFormats.Pbgra32);
            renderTargetBitmap.Render(cvs);

            SaveFileDialog dialog = new SaveFileDialog();
            dialog.Filter = "JPG Files|*.jpg|PNG Files|*.png|All Files|*.*";
            dialog.FileName = $"Pic{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.jpg";
            if (dialog.ShowDialog() == true)
            {
                using (FileStream fs = new FileStream(dialog.FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    JpegBitmapEncoder encoder = new JpegBitmapEncoder();
                    encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
                    encoder.Save(fs);
                    MessageBox.Show($"Saved in{dialog.FileName}", "Save Succesfully!", MessageBoxButton.OK);
                }
            }
        }

        private void SetBackgroundClick(object sender, RoutedEventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "Jpg Files|*.jpg|Png Files|*.png|All Files|*.*";
            if (dialog.ShowDialog() == true)
            {
                if (File.Exists(dialog.FileName))
                {
                    BitmapImage bmp = new BitmapImage();
                    bmp.BeginInit();
                    bmp.UriSource=new Uri(dialog.FileName);
                    bmp.EndInit();
                    bmp.Freeze();
                    ImageBrush imgBrush = new ImageBrush(bmp);
                    cvs.Background = imgBrush;
                }
            }
        }
    }
}

 

Draw line

 

 

Draw Ellipse

 

 

 

Draw rectangles

 

posted @ 2024-09-26 17:52  FredGrit  阅读(33)  评论(0编辑  收藏  举报