我是WPF的新手,我正在尝试创建一个图片裁剪应用程序。该程序有一个矩形,可以拖动来裁剪图片(如在Microsoft Paint中)。它的设置方式是包含矩形的图像和画布都是网格容器的子代。 Grid具有mousemove,mouseleftbuttondown和up以计算裁剪图像的事件。我的程序正在裁剪图像,但是当窗口最大化时会出现问题,这会引发下面的异常错误:
PresentationCore.dll中出现未处理的“System.ArgumentException”类型异常
其他信息:价值不在预期范围内。
此异常是由我的Go_Click方法中的一行引起的:
BitmapSource bs = new CroppedBitmap(LoadedImage.Source as BitmapSource,rcFrom);
我进入程序并发现起初它是由Image(LoadedImage.Width和LoadedImage.Height)的宽度和高度设置为auto或NAN引起的。这使得值NAN会扰乱计算并抛出异常。我将它更改为ActualWidth(LoadedImage.ActualWidth和ActualHeight),我只是部分工作,因为它在窗口最大化时裁剪图像时仍会抛出异常。
以下是我项目的源代码。
XAML:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow">
<Grid ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<GroupBox Header="Loaded Image:" Grid.Column="0">
<Grid x:Name="LoadedImage" MouseLeftButtonDown="image1_MouseLeftButtonDown" MouseMove="image1_MouseMove" MouseLeftButtonUp="image1_MouseLeftButtonUp" ShowGridLines="True">
<Image x:Name="loaded" Margin="10" Stretch="Fill"/>
<Canvas x:Name="BackPanel" Margin="10">
<Rectangle x:Name="selectionRectangle" Stroke="LightBlue" Fill="#220000FF" Visibility="Collapsed"/>
</Canvas>
</Grid>
</GroupBox>
<StackPanel Grid.Column="1" x:Name="MyPanel" HorizontalAlignment="Left" Orientation="Vertical" Height="340" Width="262">
<GroupBox x:Name="Box2" Header="Preview Box:">
<Image x:Name="PreviewImage" MaxWidth="240" MaxHeight="240" Stretch="Fill" MinWidth="240" MinHeight="240"/>
</GroupBox>
<StackPanel Height="61" Orientation="Horizontal" HorizontalAlignment="Center">
<Button MinWidth="93" Height="32" Click="Import_Click">Import</Button>
<Button Name="Crop" MinWidth="93" Height="32" Margin="10,0,0,0" Click="Go_Click">Crop</Button>
</StackPanel>
</StackPanel>
</Grid>
这就是背后的代码:
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 Microsoft.Win32;
using System.IO;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private bool isDragging = false;
private Point anchorPoint = new Point();
public MainWindow()
{
InitializeComponent();
}
//Import Button event handler which opens an open file dialog
//to choose an image file. If the return value from ShowDialog
//is true (user choose image and click's OK)it will store the image to file,
//else it would exit open file dialog.
private void Go_Click(object sender, RoutedEventArgs e)
{
if (loaded.Source != null)
{
Rect rect1 = new Rect(Canvas.GetLeft(selectionRectangle), Canvas.GetTop(selectionRectangle), selectionRectangle.Width, selectionRectangle.Height);
Int32Rect rcFrom = new Int32Rect();
rcFrom.X = (int)((rect1.X) * (loaded.Source.Width) / `enter code here`(loaded.ActualWidth));
rcFrom.Y = (int)((rect1.Y) * (loaded.Source.Height) / (loaded.ActualHeight));
rcFrom.Width = (int)((rect1.Width) * (loaded.Source.Width) / (loaded.ActualWidth));
rcFrom.Height = (int)((rect1.Height) * (loaded.Source.Height) / (loaded.ActualHeight));
BitmapSource bs = new CroppedBitmap(loaded.Source as BitmapSource, rcFrom);
PreviewImage.Source = bs;
}
}
private void image1_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
double x = e.GetPosition(BackPanel).X;
double y = e.GetPosition(BackPanel).Y;
selectionRectangle.SetValue(Canvas.LeftProperty, Math.Min(x, anchorPoint.X));
selectionRectangle.SetValue(Canvas.TopProperty, Math.Min(y, anchorPoint.Y));
selectionRectangle.Width = Math.Abs(x - anchorPoint.X);
selectionRectangle.Height = Math.Abs(y - anchorPoint.Y);
if (selectionRectangle.Visibility != Visibility.Visible)
selectionRectangle.Visibility = Visibility.Visible;
}
}
private void image1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (isDragging == false)
{
anchorPoint.X = e.GetPosition(BackPanel).X;
anchorPoint.Y = e.GetPosition(BackPanel).Y;
isDragging = true;
}
}
private void image1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (isDragging)
{
isDragging = false;
if (selectionRectangle.Width > 0)
{
Crop.Visibility = System.Windows.Visibility.Visible;
Crop.IsEnabled = true;
}
if (selectionRectangle.Visibility != Visibility.Visible)
selectionRectangle.Visibility = Visibility.Visible;
}
}
private void RestRect()
{
selectionRectangle.Visibility = Visibility.Collapsed;
isDragging = false;
}
private void Import_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.FileName = "Picture";
dlg.Filter = "All Pictures (*.jpeg)|*.jpg";
if (dlg.ShowDialog() == true)
{
loaded.Source = new BitmapImage(new Uri(dlg.FileName));
}
}
}
}
就像我说我是编程WPF的新手一样,如果我编写代码的方式可能不是最好的,我道歉。但任何建议都有助于我如何处理这个问题。
提前致谢。
答案 0 :(得分:0)
你需要获得相对于GridLoadedImage的LoadedImage位置,并在创建crop时使用它:
private void Go_Click(object sender, RoutedEventArgs e)
{
if (LoadedImage.Source != null)
{
var imagePosition = loaded.TransformToAncestor(LoadedImage).Transform(new Point(0, 0));
Rect rect1 = new Rect(Math.Max(Canvas.GetLeft(selectionRectangle) - imagePosition.X, 0), Canvas.GetTop(selectionRectangle), selectionRectangle.Width, selectionRectangle.Height);
Int32Rect rcFrom = new Int32Rect();
rcFrom.X = (int)((rect1.X) * (LoadedImage.Source.Width) / (LoadedImage.ActualWidth));
rcFrom.Y = (int)((rect1.Y) * (LoadedImage.Source.Height) / (LoadedImage.ActualHeight));
rcFrom.Width = (int)((rect1.Width) * (LoadedImage.Source.Width) / (LoadedImage.ActualWidth));
rcFrom.Height = (int)((rect1.Height) * (LoadedImage.Source.Height) / (LoadedImage.ActualHeight));
BitmapSource bs = new CroppedBitmap(LoadedImage.Source as BitmapSource, rcFrom);
PreviewImage.Source = bs;
}
}