如何"取消"从对话框加载事件

时间:2015-01-12 22:15:52

标签: c# image winforms modal-dialog

我试图创建一个来自可视化和编辑图像,简单的东西,如:

  • 绘制矩形
  • 写东西
  • 裁剪矩形

但我遇到了很多困难,例如:如果我尝试加载的文件不存在或者无法打开(它不是图像),我想显示一个MessageBox,然后关闭表单。 但表单不会立即关闭(这可能会导致错误,因为我可能会尝试访问未打开的文件的属性)。你能告诉我为什么吗? (查看Abort()方法)源代码在帖子的末尾。

我使用以下事件在里面创建我的表单:

private void button2_Click(object sender, EventArgs e)
        {
            Forms.AreaSelector areaSelector = new Forms.AreaSelector(LabelInput);
            areaSelector.ShowDialog();
        }

我希望将表单显示为对话框,以便用户无法返回主窗口'没有捕获对图像的修改,这就是为什么我使用.ShowDialog()而不是Show() 我尝试在我的" Abort"中调用Close()甚至Dispose()。方法,但表单继续加载(通过继续加载我的意思是UpdateWindowSize()和UpdatePictureBox()被调用,无论我在Abort()中做什么。)

这是实际的表单代码。

来源:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PeeAlyser.Forms
{
    public partial class AreaSelector : Form
    {
        #region Variables

        Bitmap originalImage, modifiedImage;
        string fileName;

        #endregion


        #region Constructors

        public AreaSelector(string fileName)
        {
            InitializeComponent();

            this.fileName = fileName;
        }

        #endregion

        private void AreaSelector_Load(object sender, EventArgs e)
        {
            TryToLoadImage();
            UpdateWindowSize();
            UpdatePictureBox();
        }

        #region Private Methods

        private void Abort()
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
            this.BeginInvoke(new MethodInvoker(this.Close));
            //this.Close();
            //this.Dispose();
            // GODAMNIT!
        }

        private void TryToLoadImage()
        {
            if (!System.IO.File.Exists(fileName))
            {
                MessageBox.Show("File not found.");
                Abort();
            }


            try { originalImage = (Bitmap)Bitmap.FromFile(fileName); }
            catch (Exception error)
            {
                MessageBox.Show("Error: " + Environment.NewLine +
                                error.ToString());
                Abort();
            }


            this.modifiedImage = new Bitmap(originalImage);
        }

        private void UpdateWindowSize()
        {
            int widthDifference = this.Width - pictureBox1.Width;
            int heightDifference = this.Height - pictureBox1.Height;

            Size windowSize = originalImage.Size;
            windowSize.Width += widthDifference;
            windowSize.Height += heightDifference;

            this.Size = this.MinimumSize = this.MaximumSize = windowSize;
            this.pictureBox1.Size = originalImage.Size;

            this.AdjustFormScrollbars(true);
        }

        private void UpdatePictureBox()
        {
            this.pictureBox1.Image = modifiedImage;
            this.Refresh();
        }

        #endregion
    }
}

编辑:我收到很多建议解决它。但汉斯的回答不仅纠正了我的正确设计缺陷(也解决了这个问题),而且还解释了为什么会出现这种问题(查看他的链接)。所以我选择他的答案。 随意关闭这个问题,mods。谢谢你的帮助!

3 个答案:

答案 0 :(得分:4)

Load事件在Winforms中过度使用 。它是从它的前身VB6继承的一个挂断,它非常重要,因为它是你放置任何初始化代码的地方。这使它成为默认事件,太容易使用了。

但不是在.NET中,初始化是在类的构造函数中完成的。 Load事件为时已晚,火车离开了火车站并且已经聚集了相当快的速度。试图阻止它是困难的,例如抛出异常没有效果。实际上是very dangerous。只有在需要知道窗口的大小和位置时才应使用Load事件。这很罕见,虽然看起来你有用。

你需要在它开始前停止该列车,你的TryToLoadImage()调用属于构造函数。现在它很简单,当你正常工作的东西无法正常工作时,你可以在C#中做正常的事情,抛出异常。并在ShowDialog()调用站点捕获它。容易腻。

答案 1 :(得分:0)

你可以使TryToLoadImage布尔值(通过返回false替换Adort)并像这样运行它:

if(TryToLoadImage())
{
        UpdateWindowSize();
        UpdatePictureBox();
}
else Close();

答案 2 :(得分:0)

最好的选择是避免加载事件中的"怀疑部分"

但是,如果您想在加载活动本身中执行操作,我建议使用简单程序

使用名为访问的整数变量,并将其默认设置为 1

如您所述,您希望显示消息框,然后将其关闭。在消息框行之前,将访问变量的值设置为0

将post-messagebox代码封装到If-Else块中。

您需要的代码是: -

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;

    namespace PeeAlyser.Forms
    {
      public partial class AreaSelector : Form
       {
    #region Variables

    Bitmap originalImage, modifiedImage;
    string fileName;

    #endregion


    #region Constructors

    public AreaSelector(string fileName)
    {
        InitializeComponent();

        this.fileName = fileName;
    }

    #endregion

public int access=1;

    private void AreaSelector_Load(object sender, EventArgs e)
    {
        TryToLoadImage();
        if(access==1)
    {
        UpdateWindowSize();
            UpdatePictureBox();
    }
    }

    #region Private Methods

    private void Abort()
    {
        this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
        this.BeginInvoke(new MethodInvoker(this.Close));
        //this.Close();
        //this.Dispose();
        // GODAMNIT!
    }

    private void TryToLoadImage()
    {
        if (!System.IO.File.Exists(fileName))
        {
    access=0;
            MessageBox.Show("File not found.");
            Abort();
        }


        try { originalImage = (Bitmap)Bitmap.FromFile(fileName); }
        catch (Exception error)
        {
            MessageBox.Show("Error: " + Environment.NewLine +
                            error.ToString());
            Abort();
        }


        this.modifiedImage = new Bitmap(originalImage);
    }

    private void UpdateWindowSize()
    {
        int widthDifference = this.Width - pictureBox1.Width;
        int heightDifference = this.Height - pictureBox1.Height;

        Size windowSize = originalImage.Size;
        windowSize.Width += widthDifference;
        windowSize.Height += heightDifference;

        this.Size = this.MinimumSize = this.MaximumSize = windowSize;
        this.pictureBox1.Size = originalImage.Size;

        this.AdjustFormScrollbars(true);
    }

    private void UpdatePictureBox()
    {
        this.pictureBox1.Image = modifiedImage;
        this.Refresh();
    }

    #endregion
}
}