Как «отменить» загрузку события из диалога

1

Я пытаюсь создать от визуализировать и редактировать изображения, простые вещи, такие как:

  • Рисование прямоугольников
  • Письменные принадлежности
  • Обрезка прямоугольников

Но я сталкиваюсь с множеством трудностей, например: если я пытаюсь загрузить файл, который не существует или который не может быть открыт (это не изображение), я бы хотел показать MessageBox, а затем закрыть форма. Но форма не закрывается немедленно (что может вызвать ошибки, так как я могу попытаться получить доступ к свойствам файла, который не был открыт). Не могли бы вы рассказать мне, почему? (проверьте методы Abort()). Исходный код находится в конце сообщения.

Я создаю свою форму внутри со следующим событием:

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

Я хотел бы показать свою форму в виде диалогового окна, чтобы пользователь не мог вернуться в "главное окно", не подвергая изменениям изображения, поэтому я использую.ShowDialog() вместо Show() я попытался вызвать Close() и даже Dispose() в моем методе "Abort", но форма продолжает загружаться (продолжая загружаться, я имею в виду, что 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
    }
}

Редактирование: я получил много предложений, чтобы обойти это. Но Ханс ответил не только исправил дефект дизайна в моем правильном (что также решило эту проблему), но и объяснил, почему этот вид проблемы (проверьте его ссылку). Поэтому я выбираю его ответ. Не стесняйтесь закрыть этот quesiton, моды. И спасибо за помощь, ребята!

  • 0
    Вы не должны делать это в событии Load . Поместите свою логику обнаружения ошибок в событие загрузки.
  • 0
    Как ... Могу ли я сделать это? Я имею в виду. Должен ли я установить источник данных моего изображения вне события Load? В каком случае, тогда?
Показать ещё 4 комментария
Теги:
modal-dialog
winforms
image

3 ответа

4
Лучший ответ

Событие Load сильно перегружается в Winforms. Повреждение, которое оно унаследовало от VB6, его предшественника, где это было очень важно, потому что там, где вы поместили любой код инициализации. Это сделало его событием по умолчанию, слишком простым в использовании.

Но не в.NET, инициализация выполняется в конструкторе класса. Событие загрузки слишком поздно, поезд покинул станцию и уже собрал значительную скорость. Пытаться остановить это сложно, например, выброс исключения не имеет никакого эффекта. И на самом деле это очень опасно. Событие Load должно использоваться только когда вам нужно знать размер и расположение окна. Это довольно редко, хотя похоже, что вы используете.

Вам нужно остановить этот поезд до его начала, ваш TryToLoadImage() будет принадлежать конструктору. Теперь это мертво-просто, вы делаете обычную вещь, которую делаете на С#, когда что-то, что обычно работает, не может работать, вы делаете исключение. И поймать его на сайте вызова ShowDialog(). Очень просто.

  • 0
    Спасибо за метафору и предложение. Я перенесу свой TryToLoadImage () в конструктор и вскоре отвечу результатами. Но почему именно «поезд не может быть остановлен»? Кстати ... Это имеет смысл. выделить вещи в конструкторе ... мой плохой, хе-хе
  • 0
    Поезд является родным окном, которое создает операционная система. Он был создан и инициализирован, но пока не виден. Событие Load - это уведомление «Я собираюсь стать видимым». Вы можете вызвать Close () или установить свойство DialogResult, но это не мешает кратковременному миганию окна на экране. И инициируйте некоторые другие события, которые могут бомбить, потому что ваше растровое изображение не загружается. Windows не имеет возможности отменить уведомление, наиболее заметное в событии Load без аргумента CancelEventArgs.
0

Лучшим вариантом было бы избежать "сомнительной части" в событии загрузки.

Однако, если вы хотите выполнить операции в самом Событии загрузки, я бы предложил простую процедуру.

Используйте целочисленную переменную с именем access и установите по умолчанию значение 1

Как вы упомянули, вы хотите отобразить сообщение и закрыть его. Перед линией сообщений установите значение переменной доступа равным 0.

Включите код почтового ящика в блок 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
}
}
0

Вы можете сделать TryToLoadImage boolean (заменить Adort на return false) и запустить его следующим образом:

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню