如果窗口最大化WPF,则在裁剪图像时引发异常

时间:2015-02-12 23:59:16

标签: c# wpf xaml

我是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的新手一样,如果我编写代码的方式可能不是最好的,我道歉。但任何建议都有助于我如何处理这个问题。

提前致谢。

1 个答案:

答案 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;
        }
    }