При нажатии на Сумма в примере ArbitraryMethod из Лекция 7, VS 2013 выдается ошибка: Необработанное исключение типа "System.InvalidOperationException" в System.Windows.Forms.dll Дополнительные сведения: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления "lblResult" не из того потока, в котором он был создан. Затем: Необработанное исключение типа "System.InvalidOperationException" в mscorlib.dll Дополнительные сведения: Для каждой асинхронной операции метод EndInvoke может вызываться только один раз. |
Работа с элементами управления
Работа с файловой системой Windows
В рассмотренном выше примере мы проверяли наличие файла в папке Bin/Debug, где находится само приложение. В практических случаях подобная директория не может нас устраивать — требуется просматривать заданные каталоги и папки. В C# можно работать с файлами и каталогами, используя классы DirectoryInfo и FileInfo, предоставляющие всю информацию о файлах и папках.
Класс DirectoryInfo обычно применяется для таких операций, как копирование, перемещение, переименование, создание и удаление папок. Этот класс содержит метод GetFiles(), который возвращает список файлов из текущего каталога.
Класс FileInfo предоставляет методы для создания, копирования, удаления, перемещения и открытия файлов, а также является вспомогательным классом при создании объекта FileStream.
Cоздайте новое консольное приложение и назовите его DirectoryInfo. Следующий простой код выводит список всех файлов, содержащихся на диске С:
using System; using System.IO; namespace DirectoryInformation { class Class1 { [STAThread] static void Main(string[] args) { //Создаем экземпляр di класса DirectoryInfo и указываем диск С в качестве директории DirectoryInfo directoriya = new DirectoryInfo("C:\\"); // Получаем список всех папок, содержащихся на диске С:\ DirectoryInfo[] poddirectoriya = directoriya.GetDirectories(); foreach (DirectoryInfo dd in poddirectoriya) { //Проверяем наличие доступа к каталогу if(dd.Attributes == FileAttributes.Directory) { // Получаем список всех файлов из каталога FileInfo[] spisokfile= dd.GetFiles(); foreach (FileInfo fi in spisokfile) { //Выводим список файлов Console.WriteLine(fi.ToString()); } } } } } }Листинг 2.16.
На диске, прилагаемом к книге, вы найдете приложение DirectoryInfo — Code\Glava2\DirectoryInfo.
Чтение и запись двоичных файлов
Для более общего способа чтения и записи файлов используются классы BinaryReader и BinaryWriter, предназначенные для чтения двоичных данных. Любой файл в конечном итоге представляет собой набор двоичных данных, следовательно, эти данные можно считывать и записывать во внутреннем, двоичном формате. Класс BinaryWriter представляет собой оболочку для байтового потока, управляющей записью двоичных данных. Класс BinaryReader является оболочкой, содержащей байтовый поток, и выполняет чтение двоичных данных.
Рассмотрим приложение, позволяющее считывать файл формата MP3 и записывать фрагмент этого файла. Создайте новое консольное приложение и назовите его BinaryReadWrite. В папку bin/Debug поместите любой музыкальный файл формата MP3, имеющийся на вашем компьютере.
Подключаем пространство имен:
using System.IO;
Добавляем код:
[STAThread] static void Main(string[] args) { //Добавляем блок обработки исключений try { //Создаем новый поток Chtenie и указываем файл для чтения — music.mp3 FileStream Chtenie = new FileStream("music.mp3", FileMode.Open); //Создаем экземпляр br класса BinaryReader и //связываем его с потоком Chtenie BinaryReader br = new BinaryReader(Chtenie); // Создаем массив типа байтов и //передаем ему размер в байтах – (например, 1000000) записываемого файла byte[] n = br.ReadBytes(1000000); //Закрываем поток br.Close(); //Создаем новый поток Zapis и указываем название //файла для записи sozdanajamuzika.mp3 FileStream Zapis = new FileStream("newmusic.mp3", FileMode.CreateNew, FileAccess.Write); //Создаем экземпляр wr класса BinaryWriter и //связываем его с потоком Zapis BinaryWriter wr = new BinaryWriter(Zapis); // Можно связывать объект wr с потоком создавая его без названия: //BinaryWriter wr = new BinaryWriter(new FileStream("sozdanajamuzika.mp3", //FileMode.CreateNew, FileAccess.Write)); //Передаем в поток массив байтов n wr.Write(n); //Закрываем поток br.Close(); } catch (Exception ex) { Console.WriteLine(ex.Message); } }Листинг 2.17.
Запускаем приложение. Если все сработает без ошибок — на экране появится станадртное сообщение Press any key to continue, в противном случае — поскольку мы включили блок исключений — выйдет диагностическое сообщение. Перейдем в папку bin/Debug. В ней появился файл newmusic.mp3, прослушать который мы можем с помощью любого музыкального проигрывателя.
Рассмотрим перечисления в конструкторах FileStream. Параметр FileMode определяет, каким образом открывается файл (рис. 2.36):
Значения перечисления FileMode указаны в таблице 2.4.
Параметр FileAccess определяет для пользователя разрешение на доступ к файлу (рис. 2.37):
Значения перечисления FileAccess указаны в таблице 2.5.
Значение | Описание |
---|---|
Read | Доступ на чтение из файла |
ReadWrite | Разрешается чтение из файла и запись данных в файл |
Write | Доступ для записи в файл |
Дополнительно для управления режимом доступа при одновременной работе с файлами нескольких потоков используется перечисление FileShare (рис. 2.38). Например, при создании потока для чтения файла мы могли полностью определить все параметры следующим образом:
FileStream Chtenie = new FileStream("music.mp3", FileMode.Open, FileAccess.Read, FileShare.Read);
Значения перечисления FileShare указаны в таблице 2.6.
Значение | Описание |
---|---|
Inheritable | Дает доступ к файлам, образованных текущим потоком |
None | Запрещает совместное использование текущего файла. Пока файл открыт, доступ к нему будет блокирован |
Read | Позволяет открывать текущей файл для чтения |
ReadWrite | Позволяет открывать текущий файл для чтения или записи |
Write | Позволяет открывать текущий файл для записи |
На диске, прилагаемом к книге, вы найдете приложение BinaryReadWrite (Code\Glava2\ BinaryReadWrite).
Запуск программ из приложения
Иногда в приложениях требуется запускать программы, входящие в состав операционной системы или установленные на данном компьютере. Создайте новое Windows-приложение и назовите его RunProgramm. На появившейся форме расположите три кнопки:
Располагаем кнопки в центре формы и выравниваем их, используя пункт меню Format. В коде формы подключаем пространство имен Diagnostics, позволяющее запускать приложения:
using System.Diagnostics;
Добавляем обработчики кнопок:
private void btnSystemInfo_Click(object sender, System.EventArgs e) { //Добавляем блок обработки исключений — по разным причинам (например, //система установлена на другом диске) приложение может быть недоступным. try { //Создаем новый экземпляр SysInfo класса Process Process SysInfo = new Process(); // Если приложение не будет работать корректно — вызываем диалоговое окно ошибок. SysInfo.StartInfo.ErrorDialog = true; //Указываем путь к запускаемому приложению "Сведения о системе" SysInfo.StartInfo.FileName = "C:\\Program Files\\Common Files\\Microsoft Shared\\MSInfo\\msinfo32.exe"; //Запускаем SysInfo SysInfo.Start(); } catch (Exception ex) { MessageBox.Show (ex.Message); } } private void btnRegEdit_Click(object sender, System.EventArgs e) { try { Process RegEdit = new Process(); RegEdit.StartInfo.ErrorDialog = true; //Указываем путь к запускаемому приложению "Редактор реестра" RegEdit.StartInfo.FileName = "C:\\Windows\\regedit.exe"; RegEdit.Start(); } catch (Exception ex) { MessageBox.Show (ex.Message); } } private void btnExplorer_Click(object sender, System.EventArgs e) { try { Process Explorer = new Process(); Explorer.StartInfo.ErrorDialog = true; //Указываем путь к запускаемому приложению "Проводник" Explorer.StartInfo.FileName = "C:\\Windows\\explorer.exe"; Explorer.Start(); } catch (Exception ex) { MessageBox.Show (ex.Message); } }Листинг 2.18.
Запускаем приложение. При нажатии на кнопки запускаются соответствующие приложения (рис. 2.39).
Для запуска других программ или отдельных исполняемых файлов вашего приложения следует указывать их название и адрес, по которому они будут отыскиваться на клиентском компьютере.
На диске, прилагаемом к книге, вы найдете приложение RunProgramm (Code\Glava2\RunProgramm).
Листинг форм frmmain и blank проекта NotepadCSharp
using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.IO; namespace NotepadCSharp { public class frmmain : System.Windows.Forms.Form { private System.Windows.Forms.MainMenu mainMenu1; private System.Windows.Forms.MenuItem menuItem5; private System.Windows.Forms.MenuItem menuItem12; private System.Windows.Forms.MenuItem mnuFile; private System.Windows.Forms.MenuItem mnuNew; private System.Windows.Forms.MenuItem mnuOpen; private System.Windows.Forms.MenuItem mnuSave; private System.Windows.Forms.MenuItem mnuExit; private System.Windows.Forms.MenuItem mnuEdit; private System.Windows.Forms.OpenFileDialog openFileDialog1; private System.Windows.Forms.MenuItem mnuCut; private System.Windows.Forms.MenuItem mnuCopy; private System.Windows.Forms.MenuItem mnuPaste; private System.Windows.Forms.MenuItem mnuDelete; private System.Windows.Forms.MenuItem mnuSelectAll; private System.Windows.Forms.MenuItem mnuHelp; private System.Windows.Forms.MenuItem mnuAbout; private System.Windows.Forms.MenuItem mnuArrangeIcons; private System.Windows.Forms.MenuItem mnuCascade; private System.Windows.Forms.MenuItem mnuTileHorizontal; private System.Windows.Forms.MenuItem mnuTileVertical; private System.Windows.Forms.MenuItem mnuWindow; private int openDocuments = 0; private System.Windows.Forms.MenuItem mnuFormat; private System.Windows.Forms.SaveFileDialog saveFileDialog1; private System.Windows.Forms.MenuItem mnuSaveAs; private System.Windows.Forms.FontDialog fontDialog1; private System.Windows.Forms.MenuItem mnuFont; private System.Windows.Forms.MenuItem mnuColor; private System.Windows.Forms.ColorDialog colorDialog1; private System.Windows.Forms.MenuItem menuItem1; private System.Windows.Forms.MenuItem mnuFind; private System.Windows.Forms.ToolBarButton tbNew; private System.Windows.Forms.ToolBarButton tbOpen; private System.Windows.Forms.ToolBarButton tbSave; private System.Windows.Forms.ToolBarButton tbCut; private System.Windows.Forms.ToolBarButton tbCopy; private System.Windows.Forms.ToolBarButton tbPaste; private System.Windows.Forms.ImageList imageList1; private System.Windows.Forms.ToolBar toolBarMain; private System.ComponentModel.IContainer components; public frmmain() { // // Required for Windows Form Designer support // InitializeComponent(); mnuSave.Enabled = false; // // TODO: Add any constructor code after InitializeComponent call // } /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } region Windows Form Designer generated code [STAThread] static void Main() { Application.Run(new frmmain()); } private void mnuNew_Click(object sender, System.EventArgs e) { //Создаем новый экземпляр формы frm blank frm = new blank(); frm.DocName = "Untitled " + ++openDocuments; //Указываем, что родительским контейнером //нового экземпляра будет эта, главная форма. frm.MdiParent = this; frm.Text = frm.DocName; //Вызываем форму frm.Show(); } private void mnuArrangeIcons_Click(object sender, System.EventArgs e) { this.LayoutMdi(MdiLayout.ArrangeIcons); } private void mnuCascade_Click(object sender, System.EventArgs e) { this.LayoutMdi(MdiLayout.Cascade); } private void mnuTileHorizontal_Click(object sender, System.EventArgs e) { this.LayoutMdi(MdiLayout.TileHorizontal); } private void mnuTileVertical_Click(object sender, System.EventArgs e) { this.LayoutMdi(MdiLayout.TileVertical); } private void mnuCut_Click(object sender, System.EventArgs e) { blank frm = (blank)this.ActiveMdiChild; frm.Cut(); } private void mnuCopy_Click(object sender, System.EventArgs e) { blank frm = (blank)this.ActiveMdiChild; frm.Copy(); } private void mnuPaste_Click(object sender, System.EventArgs e) { blank frm = (blank)this.ActiveMdiChild; frm.Paste(); } private void mnuDelete_Click(object sender, System.EventArgs e) { blank frm = (blank)this.ActiveMdiChild; frm.Delete(); } private void mnuSelectAll_Click(object sender, System.EventArgs e) { blank frm = (blank)this.ActiveMdiChild; frm.SelectAll(); } private void mnuOpen_Click(object sender, System.EventArgs e) { //Можно программно задавать доступные для обзора расширения файлов. //openFileDialog1.Filter = "Text Files (*.txt)|*.txt|All Files(*.*)|*.*"; //Если выбран диалог открытия файла, выполняем условие if (openFileDialog1.ShowDialog() == DialogResult.OK) { //Создаем новый документ blank frm = new blank(); //Вызываем метод Open формы blank frm.Open(openFileDialog1.FileName); //Указываем, что родительской формой является форма frmmain frm.MdiParent = this; //Присваиваем переменной DocName имя открываемого файла frm.DocName = openFileDialog1.FileName; //Свойству Text формы присваиваем переменную DocName frm.Text = frm.DocName; //Вызываем форму frm frm.Show(); mnuSave.Enabled = true; } } private void mnuSave_Click(object sender, System.EventArgs e) { //Переключаем фокус на данную форму. blank frm = (blank)this.ActiveMdiChild; //Вызываем метод Save формы blank frm.Save(frm.DocName); frm.IsSaved = true; } private void mnuSaveAs_Click(object sender, System.EventArgs e) { mnuSave.Enabled = true; //Можно программно задавать доступные для обзора расширения файлов //openFileDialog1.Filter = "Text Files (*.txt)|*.txt|All Files(*.*)|*.*"; //Если выбран диалог открытия файла, выполняем условие if (saveFileDialog1.ShowDialog() == DialogResult.OK) { //Переключаем фокус на данную форму. blank frm = (blank)this.ActiveMdiChild; //Вызываем метод Save формы blank frm.Save(saveFileDialog1.FileName); //Указываем, что родительской формой является форма frmmain frm.MdiParent = this; //Присваиваем переменной FileName имя сохраняемого файла frm.DocName = saveFileDialog1.FileName; //Свойству Text формы присваиваем переменную DocName frm.Text = frm.DocName; frm.IsSaved = true; } } private void mnuExit_Click(object sender, System.EventArgs e) { this.Close(); } private void mnuFont_Click(object sender, System.EventArgs e) { //Переключаем фокус на данную форму. blank frm = (blank)this.ActiveMdiChild; //Указываем, что родительской формой является форма frmmain frm.MdiParent = this; //Вызываем диалог fontDialog1.ShowColor = true; //Связываем свойства SelectionFont и SelectionColor элемента RichTextBox //с соответствующими свойствами диалога fontDialog1.Font = frm.richTextBox1.SelectionFont; fontDialog1.Color = frm.richTextBox1.SelectionColor; //Если выбран диалог открытия файла, выполняем условие if (fontDialog1.ShowDialog() == DialogResult.OK) { frm.richTextBox1.SelectionFont = fontDialog1.Font; frm.richTextBox1.SelectionColor = fontDialog1.Color; } //Показываем форму frm.Show(); } private void mnuColor_Click(object sender, System.EventArgs e) { blank frm = (blank)this.ActiveMdiChild; frm.MdiParent = this; colorDialog1.Color = frm.richTextBox1.SelectionColor; if (colorDialog1.ShowDialog() == DialogResult.OK) { frm.richTextBox1.SelectionColor = colorDialog1.Color; } frm.Show(); } private void mnuFind_Click(object sender, System.EventArgs e) { //Создаем новый экземпляр формы FindForm FindForm frm = new FindForm(); //Если выбран результат DialogResult.Cancel, закрываем форму (до этого //мы использовали DialogResult.OK if(frm.ShowDialog(this) == DialogResult.Cancel) return; ////Переключаем фокус на данную форму. blank form = (blank)this.ActiveMdiChild; ////Указываем, что родительской формой является форма frmmain form.MdiParent = this; //Вводим переменную для поиска в определенной части текста — //поиск слова будет осуществляться от текущей позиции курсора int start = form.richTextBox1.SelectionStart; //Вызываем предопределенный метод Find элемента richTextBox1. form.richTextBox1.Find(frm.FindText, start, frm.FindCondition); } private void mnuAbout_Click(object sender, System.EventArgs e) { //Создаем новый экземпляр формы About About frm = new About(); frm.Show(); } private void toolBarMain_ButtonClick(object sender, System.Windows.Forms.ToolBarButtonClickEventArgs e) { //New if (e.Button.Equals(tbNew)) { mnuNew_Click(this, new EventArgs()); } //Open if (e.Button.Equals(tbOpen)) { mnuOpen_Click(this, new EventArgs()); } //Save if (e.Button.Equals(tbSave)) { mnuSave_Click(this, new EventArgs()); } //Cut if (e.Button.Equals(tbCut)) { mnuCut_Click(this, new EventArgs()); } //Copy if (e.Button.Equals(tbCopy)) { mnuCopy_Click(this, new EventArgs()); } //Paste if (e.Button.Equals(tbPaste)) { mnuPaste_Click(this, new EventArgs()); } } } }Листинг 2.19. Форма frmmain
using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.IO; namespace NotepadCSharp { /// <summary> /// Summary description for blank. /// </summary> public class blank : System.Windows.Forms.Form { public System.Windows.Forms.RichTextBox richTextBox1; public string DocName = ""; private string BufferText = ""; private System.Windows.Forms.ContextMenu contextMenu1; private System.Windows.Forms.MenuItem cmnuCut; private System.Windows.Forms.MenuItem cmnuCopy; private System.Windows.Forms.MenuItem cmnuPaste; private System.Windows.Forms.MenuItem cmnuDelete; private System.Windows.Forms.MenuItem menuItem6; private System.Windows.Forms.MenuItem cmnuSelectAll; public bool IsSaved = false; private System.Windows.Forms.StatusBar statusBar1; private System.Windows.Forms.StatusBarPanel sbAmount; private System.Windows.Forms.StatusBarPanel sbTime; /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; public blank() { InitializeComponent(); //Свойству Text панели sbTime устанавливаем системное время, // конвертировав его в тип String sbTime.Text = Convert.ToString(System.DateTime.Now.ToLongTimeString()); //В тексте всплывающей подсказки выводим текущую дату sbTime.ToolTipText = Convert.ToString(System.DateTime.Today.ToLongDateString()); } protected override void Dispose( bool disposing ) { if( disposing ) { if(components != null) { components.Dispose(); } } base.Dispose( disposing ); } region Windows Form Designer generated code // Вырезание текста public void Cut() { this.BufferText = richTextBox1.SelectedText; richTextBox1.SelectedText = ""; } // Копирование текста public void Copy() { this.BufferText = richTextBox1.SelectedText; } // Вставка public void Paste() { richTextBox1.SelectedText = this.BufferText; } // Выделение всего текста — используем свойство SelectAll элемента управления RichTextBox public void SelectAll() { richTextBox1.SelectAll(); } // Удаление. public void Delete() { richTextBox1.SelectedText = ""; this.BufferText = ""; } //Создаем метод Open, в качестве параметра объявляем строку адреса файла. public void Open(string OpenFileName) { //Если файл не выбран, возвращаемся назад (появится встроенное предупреждение) if (OpenFileName == "") { return; } else { //Создаем новый объект StreamReader и передаем ему переменную OpenFileName StreamReader sr = new StreamReader(OpenFileName); //Читаем весь файл и записываем его в richTextBox1 richTextBox1.Text = sr.ReadToEnd(); // Закрываем поток sr.Close(); //Переменной DocName присваиваем адресную строку. DocName = OpenFileName; } } private void cmnuCut_Click(object sender, System.EventArgs e) { Cut(); } private void cmnuCopy_Click(object sender, System.EventArgs e) { Copy(); } private void cmnuPaste_Click(object sender, System.EventArgs e) { Paste(); } private void cmnuDelete_Click(object sender, System.EventArgs e) { Delete(); } private void cmnuSelectAll_Click(object sender, System.EventArgs e) { SelectAll(); } //Создаем метод Save, в качестве параметра объявляем строку адреса файла. public void Save(string SaveFileName) { //Если файл не выбран, возвращаемся назад (появится встроенное предупреждение) if (SaveFileName == "") { return; } else { //Создаем новый объект StreamWriter и передаем ему переменную OpenFileName StreamWriter sw = new StreamWriter(SaveFileName); //Содержимое richTextBox1 записываем в файл sw.WriteLine(richTextBox1.Text); //Закрываем поток sw.Close(); //Устанавливаем в качестве имени документа название сохраненного файла DocName = SaveFileName; } } private void blank_Closing(object sender, System.ComponentModel.CancelEventArgs e) { //Если переменная IsSaved имеет значение true, т. е. документ новый документ //был сохранен (Save As) или в открытом документе были сохранены изменения (Save), то выполняется условие if(IsSaved ==true) //Появляется диалоговое окно, предлагающее сохранить документ. if (MessageBox.Show("Do you want save changes in " + this.DocName + "?", "Message", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) //Если была нажата кнопка Yes, вызываем метод Save { this.Save(this.DocName); } } private void richTextBox1_TextChanged(object sender, System.EventArgs e) { //Свойству Text панели sbAmount устанавливаем надпись "Аmount of symbols " //и длину текста в RichTextBox. sbAmount.Text = "Аmount of symbols " + richTextBox1.Text.Length.ToString(); } } }Листинг 2.20. Форма blank