WPF InkCanvas绘制矩形和椭圆

前面说到了InkCanvas的基本操作,这里用一个实例来说明具体应用:绘制矩形和椭圆。

效果图

xaml代码

<Window x:Class="WPF_InkCanvas.ROI_InkCanvas"
    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:WPF_InkCanvas"
    mc:Ignorable="d"
    Title="ROI_InkCanvas" Height="450" Width="800">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition/>
      <RowDefinition Height="auto"/>
    </Grid.RowDefinitions>
    <Image Name="imgMeasure" HorizontalAlignment="Center" Stretch="Uniform"/>
    <InkCanvas Name="inkCanvasMeasure" EditingMode="None" Background="Transparent" Strokes="{Binding InkStrokes, Mode=TwoWay}" HorizontalAlignment="Center"
          Width="{Binding ElementName=imgMeasure, Path=ActualWidth}" Height="{Binding ElementName=imgMeasure, Path=ActualHeight}"
          MouseDown="InkCanvasMeasure_MouseDown" MouseMove="InkCanvasMeasure_MouseMove">
      <Label Content="{Binding MeaInfo}" Background="Transparent" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10"
          FontSize="18" Foreground="Red" IsHitTestVisible="False"/>
    </InkCanvas>
    <StackPanel Grid.Row="1" Orientation="Horizontal">
      <Button Content="OpenFile" Margin="5" HorizontalAlignment="Left" FontSize="20" Click="OpenFile_Click"/>
      <ToggleButton Name="btnSquare" Content="Draw Square" Margin="5" HorizontalAlignment="Left" FontSize="20" Click="DrawSquare_Click"/>
      <ToggleButton Name="btnEllipse" Content="Draw Ellipse" Margin="5" HorizontalAlignment="Left" FontSize="20" Click="DrawEllipse_Click"/>
    </StackPanel>
  </Grid>
</Window>

后台代码

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.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace WPF_InkCanvas
{
  /// <summary>
  /// ROI_InkCanvas.xaml 的交互逻辑
  /// </summary>
  public partial class ROI_InkCanvas : Window
  {
    private ViewModel viewModel;
    private System.Windows.Point iniP;
    public ROI_InkCanvas()
    {
      InitializeComponent();

      DrawingAttributes drawingAttributes = new DrawingAttributes
      {
        Color = Colors.Red,
        Width = 2,
        Height = 2,
        StylusTip = StylusTip.Rectangle,
        //FitToCurve = true,
        IsHighlighter = false,
        IgnorePressure = true,

      };
      inkCanvasMeasure.DefaultDrawingAttributes = drawingAttributes;

      viewModel = new ViewModel
      {
        MeaInfo = "测试······",
        InkStrokes = new StrokeCollection(),
      };

      DataContext = viewModel;
    }

    private void OpenFile_Click(object sender, RoutedEventArgs e)
    {
      OpenFileDialog openDialog = new OpenFileDialog
      {
        Filter = "Image Files (*.jpg)|*.jpg|Image Files (*.png)|*.png|Image Files (*.bmp)|*.bmp",
        Title = "Open Image File"
      };
      if (openDialog.ShowDialog() == true)
      {
        BitmapImage image = new BitmapImage();
        image.BeginInit();
        image.UriSource = new Uri(openDialog.FileName, UriKind.RelativeOrAbsolute);
        image.EndInit();
        imgMeasure.Source = image;
      }
    }

    private void DrawSquare_Click(object sender, RoutedEventArgs e)
    {
      if (btnSquare.IsChecked == true)
      {
        btnEllipse.IsChecked = false;
      }
    } 

    private void DrawEllipse_Click(object sender, RoutedEventArgs e)
    {
      if (btnEllipse.IsChecked == true)
      {
        btnSquare.IsChecked = false;
      }
    }

    private List<System.Windows.Point> GenerateEclipseGeometry(System.Windows.Point st, System.Windows.Point ed)
    {
      double a = 0.5 * (ed.X - st.X);
      double b = 0.5 * (ed.Y - st.Y);
      List<System.Windows.Point> pointList = new List<System.Windows.Point>();
      for (double r = 0; r <= 2 * Math.PI; r = r + 0.01)
      {
        pointList.Add(new System.Windows.Point(0.5 * (st.X + ed.X) + a * Math.Cos(r), 0.5 * (st.Y + ed.Y) + b * Math.Sin(r)));
      }
      return pointList;
    }
    private void InkCanvasMeasure_MouseDown(object sender, MouseButtonEventArgs e)
    {
      if (e.LeftButton == MouseButtonState.Pressed)
      {
        iniP = e.GetPosition(inkCanvasMeasure);
      }
    }

    private void InkCanvasMeasure_MouseMove(object sender, MouseEventArgs e)
    {
      if (e.LeftButton == MouseButtonState.Pressed)
      {
        // Draw square
        if (btnSquare.IsChecked == true)
        {
          System.Windows.Point endP = e.GetPosition(inkCanvasMeasure);
          List<System.Windows.Point> pointList = new List<System.Windows.Point>
          {
            new System.Windows.Point(iniP.X, iniP.Y),
            new System.Windows.Point(iniP.X, endP.Y),
            new System.Windows.Point(endP.X, endP.Y),
            new System.Windows.Point(endP.X, iniP.Y),
            new System.Windows.Point(iniP.X, iniP.Y),
          };
          StylusPointCollection point = new StylusPointCollection(pointList);
          Stroke stroke = new Stroke(point)
          {
            DrawingAttributes = inkCanvasMeasure.DefaultDrawingAttributes.Clone()
          };
          viewModel.InkStrokes.Clear();
          viewModel.InkStrokes.Add(stroke);
        }
        // Draw Eclipse
        else if (btnEllipse.IsChecked == true)
        {
          System.Windows.Point endP = e.GetPosition(inkCanvasMeasure);
          List<System.Windows.Point> pointList = GenerateEclipseGeometry(iniP, endP);
          StylusPointCollection point = new StylusPointCollection(pointList);
          Stroke stroke = new Stroke(point)
          {
            DrawingAttributes = inkCanvasMeasure.DefaultDrawingAttributes.Clone()
          };
          viewModel.InkStrokes.Clear();
          viewModel.InkStrokes.Add(stroke);
        }
      }
    }
  }
}

ViewModel.cs代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Ink;

namespace WPF_InkCanvas
{
  class ViewModel : INotifyPropertyChanged
  {
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName = null)
    {
      if (PropertyChanged != null)
        PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private string meaInfo;
    public string MeaInfo
    {
      get => meaInfo;
      set
      {
        meaInfo = value;
        OnPropertyChanged("MeaInfo");
      }
    }

    private StrokeCollection inkStrokes;
    public StrokeCollection InkStrokes
    {
      get { return inkStrokes; }
      set
      {
        inkStrokes = value;
        OnPropertyChanged("InkStrokes");
      }
    }
  }
}

补充说明:为什么要注释掉画笔属性//FitToCurve = true,可以自行体会下不注释会是个什么效果;将InkCanvas的Strokes绑定到变量有好处,在别的窗口也能获取到这个对象的哦,因为它是在viewModel里的,传viewModel参数就可以了;椭圆绘制完成后设置InkCanvas的EdittingMode为Select就可以修改大小和形状。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • WPF InkCanvas基本操作方法详解

    WPF的InkCanvas就是一个画板,可以在上面随意涂鸦,每写上一笔,InkCanvas的Strokes集合里就新增一个涂鸦对象,下面的代码演示了基本的操作. 效果图 xaml代码 <Window x:Class="WPF_InkCanvas.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.mi

  • WPF InkCanvas绘制矩形和椭圆

    前面说到了InkCanvas的基本操作,这里用一个实例来说明具体应用:绘制矩形和椭圆. 效果图 xaml代码 <Window x:Class="WPF_InkCanvas.ROI_InkCanvas" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  • OpenCV 轮廓周围绘制矩形框和圆形框的方法

    轮廓周围绘制介绍 没什么概念,就是给得出来的轮廓绘制周围图形,例如下图给左侧得出的轮廓去绘图得到右侧图像: 相关API 减少多边形轮廓点数:approxPolyDP 函数作用:基于RDP算法实现,目的是减少多边形轮廓点数 函数原型: //减少多边形轮廓点数 approxPolyDP( InputArray curve, // 一般是由图像的轮廓点组成的点集 Mat(vector) OutputArray approxCurve, // 表示输出的多边形点集 double epsilon, //

  • opencv绘制矩形和圆的实现

    目录 绘制图形 绘制矩形 绘制圆 绘制图形 利用opencv提供的绘制图形api可以轻松在图像上绘制各种图形,比如直线,矩形,圆,椭圆等图形. line(img,pt1,pt2,color,thickness,lineType,shift)画直线 img:在那个图像上画线 pt1,pt2:开始点,结束点,指定先的开始与结束的位置 color:颜色 thickness:线宽 lineType:线型,线型为-1,4,8,16,默认为8 shift:坐标缩放比例 rectangle()参数同上,画矩形

  • js+canvas绘制矩形的方法

    本文实例讲述了js+canvas绘制矩形的方法.分享给大家供大家参考,具体如下: 运行效果截图如下: 具体代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtm

  • C#使用GDI绘制矩形的方法

    本文实例讲述了C#使用GDI绘制矩形的方法.分享给大家供大家参考.具体实现方法如下: Pen p = new Pen(Color.Black,2); Graphics g = CreateGraphics(); g.DrawRectangle(p,200,200,100,100); 希望本文所述对大家的C#程序设计有所帮助.

  • PyQt5 在label显示的图片中绘制矩形的方法

    在利用QT编写GUI程序时经常需要一些交互操作,常见的有鼠标事件.键盘事件等.今天我们要实现的是在label中已经显示的图像中绘制矩形框,以便进行下一步操作(如放大细节,选中感兴趣区域等)程序主要参考了知乎的小杨老师的专栏. 核心点是重写Label,使其实现相应的功能,看下面的一个小例子 from PyQt5.QtWidgets import QWidget, QApplication, QLabel from PyQt5.QtCore import QRect, Qt from PyQt5.Q

  • vue canvas绘制矩形并解决由clearRec带来的闪屏问题

    起因:在cavnas绘制矩形时 鼠标移动一直在监测中,所以鼠标移动的轨迹会留下一个个的矩形框, 要想清除矩形框官方给出了ctx.clearRect() 但是这样是把整个画布给清空了,因此需要不断 向画布展示新的图片,这样就出现了不断闪屏的问题. 那么怎么解决呢? microsoft提供了双缓冲图形技术,可以点击看看这边文章. 具体就是画图的时候做两个canvas层,一个临时层 一个显示层,鼠标的监听事件放在显示层处理, 每次清空的时候只清空临时层,这样就可以解决闪屏问题了. 部分代码如下: <!

  • OpenCV鼠标绘制矩形和截取矩形区域图像

    本文实例为大家分享了OpenCV鼠标绘制截取矩形区域图像的具体代码,供大家参考,具体内容如下 在opencv中利用鼠标绘制矩形,代码如下: #include <cv.h> #include <highgui.h> #include <stdio.h> #pragma comment( lib, "cv.lib" ) #pragma comment( lib, "cxcore.lib" ) #pragma comment( lib,

  • Java实现画线、矩形、椭圆、字符串功能

    本文讲述了Java实现画线.矩形.椭圆.字符串功能的实例代码.分享给大家供大家参考,具体如下: import java.awt.Frame; import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; /** * 增加窗口 画线.矩形.椭圆.字符串 * @author Lixiangjian * */ public class BallGame extends Frame{ //Image sun 代表所得到

  • Vue使用鼠标在Canvas上绘制矩形

    本文实例为大家分享了Vue使用鼠标在Canvas上绘制矩形的具体代码,供大家参考,具体内容如下 1.代码 <template> <div class="test" style="background-color: burlywood;"> <canvas id="myCanvas" ref="myCanvas" width="460" height="240"

随机推荐