c# - 如何从对话框加载事件 "Cancel"

标签 c# image winforms modal-dialog

我正在尝试创建一个 from 来可视化和编辑图像,简单的东西比如:

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

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

我使用以下事件在内部创建我的表单:

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

我想将我的表单显示为一个对话框,这样用户就无法在不获取对图像的修改的情况下返回“主窗口”,这就是我使用 .ShowDialog() 的原因,而不是显示() 我尝试在我的“中止”方法中调用 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。并感谢您的帮助!

最佳答案

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

但不是在 .NET 中,初始化是在类的构造函数中完成的。 Load 事件来不及了,火车离开了车站并且已经达到了相当大的速度。试图阻止它很困难,例如抛出异常没有任何效果。事实上是very dangerous .只有在需要知道窗口的大小和位置时才应使用 Load 事件。这种情况很少见,尽管看起来您很有用。

您需要在火车开始前停止它,您的 TryToLoadImage() 调用属于构造函数。现在它非常简单,当正常工作的东西不能工作时,你做你在 C# 中做的正常事情,你抛出一个异常。并在 ShowDialog() 调用站点捕获它。简单易行。

关于c# - 如何从对话框加载事件 "Cancel",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27911683/

相关文章:

c# - @Html.DropDownListFor 基本用法

c# - Entity Framework ObjectQuery.Include()

c++ - 为什么图像像素要平铺在内存中的WORD单元中?

c# - 只打印一页

c# - 在不同的String字典上做benchmark,普通的比较快,不知道为什么

c# - 如何在 Itext7 中合并时向 PDF 添加书签

c# - 如何将 JPEG 图像转换为具有透明背景的 PNG 图像?

ios - YPDrawSignatureView,在 iOS 应用程序中捕获/保存签名

c# - 悬停事件错误触发

C# Windows 应用程序窗体到 Html 窗体