Я пытаюсь создать от визуализировать и редактировать изображения, простые вещи, такие как:
Но я сталкиваюсь с множеством трудностей, например: если я пытаюсь загрузить файл, который не существует или который не может быть открыт (это не изображение), я бы хотел показать 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, моды. И спасибо за помощь, ребята!
Событие Load сильно перегружается в Winforms. Повреждение, которое оно унаследовало от VB6, его предшественника, где это было очень важно, потому что там, где вы поместили любой код инициализации. Это сделало его событием по умолчанию, слишком простым в использовании.
Но не в.NET, инициализация выполняется в конструкторе класса. Событие загрузки слишком поздно, поезд покинул станцию и уже собрал значительную скорость. Пытаться остановить это сложно, например, выброс исключения не имеет никакого эффекта. И на самом деле это очень опасно. Событие Load должно использоваться только когда вам нужно знать размер и расположение окна. Это довольно редко, хотя похоже, что вы используете.
Вам нужно остановить этот поезд до его начала, ваш TryToLoadImage() будет принадлежать конструктору. Теперь это мертво-просто, вы делаете обычную вещь, которую делаете на С#, когда что-то, что обычно работает, не может работать, вы делаете исключение. И поймать его на сайте вызова ShowDialog(). Очень просто.
Лучшим вариантом было бы избежать "сомнительной части" в событии загрузки.
Однако, если вы хотите выполнить операции в самом Событии загрузки, я бы предложил простую процедуру.
Используйте целочисленную переменную с именем 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
}
}
Вы можете сделать TryToLoadImage boolean (заменить Adort на return false) и запустить его следующим образом:
if(TryToLoadImage())
{
UpdateWindowSize();
UpdatePictureBox();
}
else Close();
Load
. Поместите свою логику обнаружения ошибок в событие загрузки.