При нажатии на Сумма в примере ArbitraryMethod из Лекция 7, VS 2013 выдается ошибка: Необработанное исключение типа "System.InvalidOperationException" в System.Windows.Forms.dll Дополнительные сведения: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления "lblResult" не из того потока, в котором он был создан. Затем: Необработанное исключение типа "System.InvalidOperationException" в mscorlib.dll Дополнительные сведения: Для каждой асинхронной операции метод EndInvoke может вызываться только один раз. |
Работа с элементами управления
Создание MDI-приложений
Такие программы, как блокнот и Microsoft Paint, относятся к SDI (Single — Document Interface) приложениям, способным работать только с одним документом. Другие, такие как Microsoft Word или Adobe Photoshop, поддерживают работу сразу с несколькими документами и называются MDI (Multiple — Document Interface) приложениями (рис. 2.3 и 2.4).
В MDI-приложениях главная форма содержит в себе несколько документов, каждый из которых является холстом в графических программах или полем для текста в редакторах. Продолжим работу над приложением Notepad C#. В окне Solution Explorer щелкаем правой кнопкой на имени проекта и в появившемся контекстном меню выбираем Add/ Add Windows Form… . В появившемся окне называем форму – blank.cs. В нашем проекте появилась новая форма — будем называть ее дочерней. В режиме дизайна перетаскиваем на нее элемент управления RichTextBox: в отличие от элемента textBox, размер содержимого текста в нем не ограничивается 64 Кб; кроме того, RichTextBox позволяет редактировать цвет текста, добавлять изображения. Свойству Dock этого элемента устанавливаем значение Fill (рис. 2.5):
Переходим в режим дизайна формы Frmmain и устанавливаем свойству IsMdiContainer значение true. Цвет формы при этом становится темно-серым. Новые документы будут у нас появляться при нажатии пункта меню New (которому мы установили сочетание клавиш Ctrl+N), поэтому дважды щелкаем в этом пункте и переходим в код:
private void mnuNew_Click(object sender, System.EventArgs e) { //Создаем новый экземпляр формы frm blank frm = new blank(); //Указываем, что родительским контейнером //нового экземпляра будет эта, главная форма. frm.MdiParent = this; //Вызываем форму frm.Show(); }
Запускаем приложение. Теперь при нажатии клавиш Ctrl+N или выборе пункта меню New появляется несколько окон, расположенных каскадом. Однако заголовок у них всех одинаковый — blank. При создании нескольких документов, например в Microsoft Word, они называются ДокументN, где N — номер документа. Переключаемся в код формы blank, и в классе blank объявляем переменную DocName:
public string DocName = "";
Переключаемся в код формы frmmain и в классе frmmain объявляем переменную openDocuments:
private int openDocuments = 0;
Присваиваем переменной DocName часть названия по шаблону, в который включен счетчик числа открываемых документов, затем это значение передаем свойству Text создаваемой формы frm:
private void mnuNew_Click(object sender, System.EventArgs e) { blank frm = new blank(); frm.DocName = "Untitled " + ++openDocuments; frm.Text = frm.DocName; frm.MdiParent = this; frm.Show(); }
Запускаем приложение. Теперь новые документы содержат разные заголовки (рис. 2.6).
Перечисление MdiLayout
При работе с несколькими документами в MDI-приложениях удобно упорядочивать их на экране. Можно, конечно, распределять формы вручную, но при работе с большим количеством документов это представляется затруднительным. В пункте меню Window реализуем процедуру выравнивания окон.
Создаем обработчиков:
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); }
Метод LayoutMdi содержит перечисление MdiLayout, содержащее четыре члена. ArrangeIcons переключает фокус на выбранную форму, в свойстве MdiList пункта меню ArrangeIcons устанавливаем также значение true. При открытии нескольких новых документов окна располагаются каскадом (рис. 2.6), их можно расположить горизонтально — значение TileHorizontal или вертикально — значение TileVertical, а затем снова вернуть каскадное расположение — Cascade (рис. 2.7):
Вырезание, копирование и вставка текстовых фрагментов
С приложением работать будет удобней, если при создании нового документа он сразу будет занимать всю область главной формы. Для этого установим свойство WindowState формы blank Maximized. Теперь приступим к созданию обработчиков для стандартных операций вырезания, копирования и вставки. Элемент управления RichTextBox имеет свойство SelectedText, которое содержит выделенный фрагмент текста. На основании этого свойства и будут реализованы действия по работе с текстом. В коде формы blank объявляем переменную BufferText, в которой будет храниться буферизованный фрагмент текста:
private string BufferText = "";
Далее создаем соответствующие методы:
// Вырезание текста 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 = ""; }Листинг 2.1.
Переключаемся в режим дизайна формы и создаем обработчиков для пунктов меню:
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(); }Листинг 2.2.
Свойство ActiveMdiChild переключает фокус на текущую форму, если их открыто несколько, и вызывает один из методов, определенных в дочерней форме. Запускаем приложение. Теперь мы можем выполнять все стандартные операции с текстом.