RUS_-_Karejev_-_Razrabotka_Windows-prilozhenij
.pdf
Рис. 2.20. Свойства панели sbAmount
Рис. 2.21. Свойства панели sbTime
Значения некоторых свойств панели приводятся в таблице 2.2.
|
Таблица 2.2. |
Свойство |
Значение |
Alignment Выравнивание содержимого свойства Text на панели
AutoSize Изменение размеров панели по содержимому
BorderStyle Внешний вид панели – утопленная, приподнятая или без выделения
Icon Добавление иконки
Style Стиль панели
Text Текст, располагаемый на панели
ToolTipText Всплывающая подсказка — появляется при наведении курсора на панель
Width Ширина панели в пикселях
Name Название панели для обращения к ней в коде
Свойства панели, назначаемые в окне редактора StatusBarCollectionEditor, можно изменять в коде —именно так мы сейчас и поступим.
После завершения работы над панелями закрываем редактор. Свойству ShowPanels элемента управления StatusBar устанавливаем значение True. На форме немедленно отображаются две панели.
Выделяем элемент управления RichTextBox, в окне его свойств переключаемся на события и создаем обработчик для события
TextChanged:
private void richTextBox1_TextChanged(object sender, System.EventArgs e)
{
//Свойству Text панели sbAmount устанавливаем надпись "Аmount of symbols" //и длину текста в RichTextBox.
sbAmount.Text = "Аmount of symbols" + richTextBox1.Text.Length.ToString();
}
Свойство Text панели sbAmount мы изменяем программно: даже если бы мы ничего не написали в окне редактора StatusBarCollectionEditor, при возникновении события TextChanged на панели появится надпись.
Займемся теперь второй панелью — той, на которую будем выводить системное время. В конструкторе формы blank добавляем код:
public blank()
{
InitializeComponent();
//Свойству Text панели sbTime устанавливаем системное время, // конвертировав его в тип String
sbTime.Text = Convert.ToString(System.DateTime.Now.ToLongTimeString()); //В тексте всплывающей подсказки выводим текущую дату
sbTime.ToolTipText = Convert.ToString(System.DateTime.Today.ToLongDateString());
}
Запускаем приложение. Панель с выводимым временем располагается достаточно необычно (рис. 2.22), при необходимости для вывода времени в привычном правом нижнем углу можно добавить третью пустую панель.
Рис. 2.22. Строка состояния с двумя панелями
Закрывание формы
При запуске приложения Notepad С# на форме имеются три стандартные кнопки — "Свернуть", "Развернуть" и "Закрыть". Большинство пользователей предпочитают использовать именно кнопку "Закрыть" для выхода из приложения. Тем не менее принято дублировать кнопку формы пунктом меню Exit. В обработчике этой кнопки добавляем код
private void mnuExit_Click(object sender, System.EventArgs e)
{
this.Close();
}
Метод Close закрывает форму и может быть назначен другим элементам управления — например, кнопке.
CheckBox
Чекбоксы относятся к так называемым кнопкам отложенного действия, т. е. их нажатие не запускает немедленно какого-либо процесса. С их помощью пользователь устанавливает определенные параметры, результат действия которых скажется после запуска других элементов управления. Добавим в приложение Notepad C# форму для поиска заданного текста, в которой будут использованы элементы управления CheckBox. В окне Solution Explorer щелкаем правой кнопкой мыши на названии проекта — NotepadCSharp — и в появившемся меню выбираем пункт Add Windows Form. Называем новую форму FindForm.cs и устанавливаем следующие свойства:
FindForm, форма, свойство |
Значение |
Name |
FindForm |
|
|
FormBorderStyle |
FixedToolWindow |
|
|
Size |
328; 112 |
|
|
Text |
Find |
Располагаем на форме TextBox, две кнопки и два элемента ChekBox так, как показано на рис. рис. 2.23:
Рис. 2.23. Форма FindForm в режиме дизайна
Устанавливаем следующие свойства элементам управления:
TextBox, свойство Значение
Name |
txtFind |
Size |
192; 20 |
Text |
|
checkBox1, свойство |
Значение |
Name |
cbMatchCase |
Text |
|
Match &Case |
|
|
|
|
|
|
|
checkBox2, свойство |
Значение |
|||
|
|
|
|
|
Name |
|
cbMatchWhole |
||
|
|
|
|
|
Text |
|
Match &whole word |
||
|
|
|
||
button1, свойство |
Значение |
|
||
Name |
btnOK |
|
||
DialogResult |
OK |
|
|
|
Text |
&OK |
|
||
|
||||
button2, свойство |
Значение |
|
||
Name |
btnCancel |
|
||
DialogResult |
Cancel |
|
||
Text |
&Cancel |
|
||
Выбор первого чекбокса — cbMatchCase — будет устанавливать поиск слова с учетом регистра, второго – cbMatchWhole — поиск по целому слову. Обратите внимание на свойство кнопок DialogResult — выбирая соответствующие свойства, мы устанавливаем
обработчики для кнопок без обращения к коду. Значение ОК закрывает форму, выполняя установленное действие, — в данном случае — поиск; значение Cancel просто закрывает форму. В главном меню формы frmmain добавляем разделительную линию и
пункт Find и устанавливаем значения свойств: Name — mnuFind, Shortcut — CtrlF, Text — &Find. Переходим в обработчик этого пункта:
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);
}
Основой поиска будет метод Find элемента управления RichTextBox. Нам остается лишь указать параметры поиска, которые могут принимать различные значения (рис. 2.24):
Рис. 2.24. Параметры метода Find. Щелкая на маленькую кнопку всплывающей подсказки Intel Sense, выбираем разные подсказки для групп передаваемых параметров
Вкоде формы FindForm осталось реализовать логику работы, зависящую от положения элементов CheckBox:
//Создаем перечисление, возвращающее параметр FindCondition public RichTextBoxFinds FindCondition
{
get
{
//Выбраны два чекбокса
if (cbMatchCase.Checked && cbMatchWhole.Checked)
{
// Возвращаем свойство MatchCase и WholeWord
return RichTextBoxFinds.MatchCase| RichTextBoxFinds.WholeWord;
}
//Выбран один чекбокс
if (cbMatchCase.Checked )
{
// Возвращаем свойство MatchCase return RichTextBoxFinds.MatchCase;
}
//Выбран другой чекбокс if (cbMatchWhole.Checked )
{
// Возвращаем свойство WholeWord return RichTextBoxFinds.WholeWord;
}
//Не выбран ни один чекбокс return RichTextBoxFinds.None;
}
}
Листинг 2.11.
И наконец, создаем свойство FindText, возвращающее в качестве переменной поиска введенный текст в текстовое поле формы
FindForm:
public string FindText
{
get{return txtFind.Text;} set{txtFind.Text = value;}
}
Запускаем приложение. Выбирая различные варианты, можно однократно искать заданное слово (рис. 2.25):
Рис. 2.25. Поиск слова в тексте
Свойство TabIndex элементов управления
Многие пользователи предпочитают работать по большей части с клавиатурой и прибегать к помощи мыши только там, где без нее нельзя обойтись. При работе с формой Find было бы удобно ввести слово в текстовое поле, затем, нажав клавишу Tab и Enter,
осуществить поиск, — или, дважды нажав клавишу Tab, переключить фокус ввода на чекбокс Match Case. Для этого в режиме дизайна формы Find следует установить свойство TabIndex элементов управления в виде последовательной нумерации, начиная с
нуля:
Элемент управления TabIndex
TxtFind |
0 |
BtnOK |
1 |
CbMatchCase |
2 |
CbMatchWhole |
3 |
BtnCancel |
4 |
При такой нумерации фокус ввода будет последовательно переходить в порядке возрастания — от элемента txtFind до btnCancel. Свойство TabIndex имеет особенно большое значение при создании ряда текстовых полей, где пользователю будет предлагаться ввести информацию.
Label, LinkLabel и PictureBox
Программы, как правило, содержат пункт главного меню "О программе", где в отдельном окне помещается логотип компании, лицензионное соглашение, гиперссылки на сайт разработчика и другая информация. Создадим подобную форму, используя новые элементы управления — Label, LinkLabel и PictureBox.
Итак, добавим в наш проект новую форму и назовем ее About.cs. Установим следующие свойства формы:
About, форма, свойство |
Значение |
Name |
About |
|
|
FormBorderStyle |
FixedSingle |
|
|
MaximizeBox |
False |
|
|
MinimizeBox |
False |
|
|
Size |
318; 214 |
|
|
Text |
About Notepad C# |
Добавим на форму элемент управления PictureBox — он представляет собой подложку, размещаемую на форме, которая может содержать в себе рисунки для отображения. В поле свойства Image щелкаем на кнопку (…) и выбираем рисунок по адресу
Code\Glava2\NotepadCSharp\Icon\logo.gif. Поскольку logo.gif является анимированным рисунком, элемент PictureBox начинает воспроизводить анимацию сразу же, даже в режиме дизайна.
Из окна ToolBox перетащим на форму кнопку, Label и LinkLabel. В поле свойства Text кнопки введем &OK. Элемент Label предназначен для размещения на форме надписей, которые в готовом приложении будут доступны только для чтения. В поле свойства Text введем Notepad C# 2006 All rights reserved. Элемент LinkLabel отображает текст на форме в стиле web-ссылок и обычно используется для создания навигации между формами или ссылки на сайт. В поле Text этого элемента вводим адрес гипотетического сайта — www.notepadcsharp.com. Пользователь будет переходить на сайт, нажимая на эту ссылку, поэтому реализуем переход по гиперссылке для события Click. В окне Properties щелкаем дважды на событии Click и добавляем обработчик:
private void linkLabel1_Click(object sender, System.EventArgs e)
{
//Добавляем блок для обработки исключений — по разным причинам //пользователь может не получить доступа к ресурсу.
try
{
//Вызываем метод VisitLink, определенный ниже
VisitLink();
}
catch (Exception ex )
{
MessageBox.Show(ex +"Unable to open link that was clicked.");
}
}
//Создаем метод VisitLink private void VisitLink()
{
// Изменяем цвет посещенной ссылки, программно //обращаясь к свойству LinkVisited элемента LinkLabel linkLabel1.LinkVisited = true;
//Вызываем метод Process.Start method для запуска браузера, //установленного по умолчанию, и открытия ссылки
System.Diagnostics.Process.Start("http://www.notepadcsharp.com");
}
Листинг 2.12.
Кнопка OK просто будет закрывать форму:
private void button1_Click(object sender, System.EventArgs e)
{
this.Close();
}
В пункте главного меню About Programm… формы frmmain добавляем процедуру вызова формы About:
private void mnuAbout_Click(object sender, System.EventArgs e)
{
//Создаем новый экземпляр формы About About frm = new About();
frm.Show();
}
Запускаем приложение (рис. 2.26):
Рис. 2.26. Окно About Notepad C#
Режимы запуска окон
В приложении Notepad C# с открытой формой About без труда можно вернуться к другим пунктам меню программы или документу, т. е. форма About позволяет переключать фокус. Такое поведение дочерних форм характерно для панелей инструментов в
программах и называется немодальным. Наоборот, форма, запущенная в модальном режиме, не позволит работать с приложением до тех пор, пока мы не закроем эту форму. Для открытия формы в модальном режиме используется метод ShowDialog:
private void mnuAbout_Click(object sender, System.EventArgs e)
{
//Создаем новый экземпляр формы About About frm = new About(); frm.ShowDialog();
}
Модификаторы доступа и наследование форм
С модификаторами доступа вы сталкивались, когда изучали синтаксис языка C#. Используя их, можно определить область видимости, иначе говоря, уровень доступности типов и членов классов, — под этим понимается участок кода, из любой точки которого будет доступен запрашиваемый тип или член класса. Технология Common Type System (CTS, система общих типов) — одна из технологий, обеспечивающих функционирование среды .NET, определяет правила для видимости типов и доступа к их членам. Различные типы модификаторов и их описание приводятся в таблице 2.3.
|
Таблица 2.3. |
Модификатор |
Определение |
|
|
public (общественный, открытый) |
Объект доступен любому коду из любой сборки |
|
|
private (частный, закрытый) |
Объект может быть вызван другими методами только из того же типа |
|
|
internal (внутренний, сборочный) |
Объект может быть вызван любым кодом из той же сборки |
|
|
protected (защищенный, родовой) |
Объект может быть вызван производными типами независимо от их сборки |
protected internal (родовой сборочный) Объект может быть вызван производными типами, определенными в той же самой сборке
В качестве объекта могут выступать методы, свойства, классы и, как мы далее увидим, — формы. Под сборкой здесь понимается функциональная единица кода (строгое определение сборок см. в лекции 9).
Наследование классов — достаточно простое и чрезвычайно удобное понятие синтаксиса С#. Формы, которые содержат большую часть методов и свойств, определенных как public, тоже можно наследовать — для получения доступа к свойствам, определенным
как protected, и для ускорения работы. В самом деле, если у нас имеется уже готовая форма (например, About Notepad C#), которую мы собираемся использовать в нескольких приложениях, удобно просто создать наследуемую форму.
Запускаем приложение Notepad C# и в окне Solution Explorer щелкаем правой кнопкой на названии проекта. В появившемся контекстном меню выбираем Add\Add Inherited Form… . В окне Add New Item задаем название формы — IAbout.cs. Далее появляется окно Inheritance Picker, в котором отображаются все формы текущего проекта (рис. 2.27).
Рис. 2.27. Окно выбора формы для наследования Inheritance Picker
В этом окне мы выбираем форму About. Обратите внимание на кнопку Browse, позволяющую искать формы для наследования в библиотеках dll. Нажимаем кнопку OK — в проекте появилась новая форма, содержащая все элементы управления формы About (рис. 2.28). Для завершения связей необходимо скомпилировать проект cнова — выбрав пункт главного меню Build/Rebuild Solution.
Рис. 2.28. Форма IAbout, наследованная от формы About
При редактировании родительской формы изменения также касаются дочерней — добавьте, например, кнопку на форму About, и она появится на форме IAbout. Изменения же, производимые с дочерней формой, не затрагивают родительскую форму.
ToolBar и ImageList
Панели инструментов ToolBar содержат наборы кнопок, как правило, дублирующих пункты главного меню. В графических программах панели инструментов — основное средство работы. Откроем снова приложение Notepad C# и перетащим из окна ToolBox элемент управления ToolBar. На кнопках панели обычно располагаются иконки, поэтому, прежде чем мы начнем заниматься ими, нам следует подумать о рисунках. Добавим на форму элемент управления ImageList, применяемый для хранения
рисунков, которые могут быть использованы для оформления приложения. Щелкнем в поле Images элемента ImageList (рис. 2.29).
Рис. 2.29. Cвойство Images элемента ImageList
Добавим файлы иконок, последовательно нажимая кнопку Add и выбирая директорию — Code\Glava2\NotepadCSharp\Icon. Мы создадим кнопки панели инструментов, дублирующие действия пунктов меню New, Open, Save, Cut, Copy и Paste, поэтому вы
можете выбрать подходящие изображения на своем компьютере1). В любом случае, подобрав иконки, завершаем работу с редактором ImageCollectionEditor, нажимая OK. Займемся теперь элементом ToolBar. Свойству Name установим значение
toolBarMain, а в поле свойства ImageList выберем imageList1. Запустим редактор ToolBarButton Collection Editor для создания кнопок, щелкнув кнопку (…) в поле свойства Buttons (рис. 2.30).
Рис. 2.30. Редактор ToolBarButton Collection Editor
Для добавления кнопок в этом редакторе тоже следует нажимать клавишу Add. Создадим шесть кнопок, установив для них следующие свойства:
Name Image Index ToolTipText
tbNew
Create New
tbOpen
Open
tbSave
Save
tbCut
Cut
tbCopy
Copy
tbPaste
Paste
Свойство Name устанавливает название кнопки для обращения к ней в коде. Свойство Image Index определяет изображение на кнопке, а в поле ToolTipText вводим текст всплывающей подсказки, которая будет появляться при наведении курсора на кнопку. Завершив работу с редактором кнопок в режиме дизайна формы frmmain, дважды щелкаем на ToolBar и переходим в код. Для создания функциональности кнопок связываем событие Click заданной кнопки c соответствующим обработчиком пунктов меню:
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.13.
Запускаем приложение. Кнопки панели инструментов дублируют пункты меню, а при наведении на них появляются подсказки (рис. 2.31).
Рис. 2.31. Панель инструментов Toolbar
На диске, прилагаемом к книге, вы найдете приложение NotepadCSharp (Code\Glava2\NotepadCSharp). В конце этой лекции приводится листинг форм frmamin и blank.
Чтение и запись файлов
При изучении синтаксиса языка С# вы сталкивались с чтением и записей файлов. Если при рассмотрении обработчиков OpenFileDialog и SaveFileDialog вы не до конца поняли, как .NET Framework работает с файлами, давайте еще раз разберемся с
этим понятием.
Файл — это совокупность данных, сохраненных на диске под общим названием. Когда мы открываем файл, он становится потоком, с которым мы можем осуществлять следующие операции:
считывать данные из потока;
записывать данные в поток;
производить поиск в потоке.
В С# все классы, которые представляют потоки, наследуются от абстрактного класса Stream. Класс Stream вместе со своими
подклассами обеспечивает универсальное представление источников данных и архивов, абстрагированное от подробностей операционной системы. Классы потоков определены в пространстве имен System.IO.
Чтение и запись текстовых файлов
Для чтения и записи файлов, содержащих только текст, используются классы StreamReader и StreamWriter. Класс Stream Reader наследуется от класса TextReader, который считывает строки из стандартного текстового файла. Класс StreamWriter наследуется от класса TextWriter, записывающего символы в поток в специальном кодировании.
Создайте новое консольное приложение и назовите его FileStream. Скомпилируйте приложение (Ctrl+F5). В папке проекта
создайте текстовый документ 1.txt. Откройте его в блокноте (или в приложении Notepad C#) и напишите в нем любой текст на русском и английском языках, сохранив затем его в кодировке Unicode. Выведем теперь записанный текст в окно консольного приложения. Переходим в код FileStream и подключаем пространство имен:
using System.IO;
В методе Main добавляем код:
[STAThread]
static void Main(string[] args)
{
//Cоздаем экземпляр Chitat класса StreamReader и указываем путь к файлу и его название
StreamReader Chitat = new StreamReader("1.txt"); // Объявляем переменную A.
string A;
//В переменную А считываем содержимое файла
A = Chitat.ReadToEnd(); //Закрываем поток
Chitat.Close();
//Выводим переменную A в окно консольного приложения. Console.WriteLine(A);
}
Когда вы работаете с файлом, например, редактируете документ Microsoft Word, вы не сможете удалить его или переместить — потому что приложение занято и поток открыт. Только завершив работу с документом и, следовательно, закрыв поток, можно перемещать его или открывать с помощью других приложений. Аналогично, в этом примере мы закрываем поток, вызывая метод Close, освобождая тем самым задействованные системные ресурсы.
Запускаем приложение. В консольном окне появляется текст, считанный из файла (рис. 2.32 ).
Рис. 2.32. Чтение текста из файла
Добавим теперь объект класса StreamWriter, который будет записывать текст в файл:
[STAThread]
static void Main(string[] args)
{
//Cоздаем экземпляр Chitat класса StreamReader и указываем путь к файлу и его название
StreamReader Chitat = new StreamReader("1.txt");
//Объявляем переменную A. string A;
//В переменную А считываем содержимое файла
A = Chitat.ReadToEnd(); //Закрываем поток
Chitat.Close();
//Выводим переменную A в окно консольного приложения. Console.WriteLine(A);
//Cоздаем экземпляр Pisat класса StreamWriter
StreamWriter Pisat = new StreamWriter("1.txt", true, System.Text.Encoding.Unicode); //Вызываем метод Write экземпляра Pisat
Pisat.Write("Добавляем текст"); //Закрываем поток
Pisat.Close();
//Для того, чтобы не переходить в директорию
//для просмотра файла вручную, выведем его еще раз
StreamReader ChitatSnova = new StreamReader("1.txt"); string B;
B = ChitatSnova.ReadToEnd(); ChitatSnova.Close(); Console.WriteLine(B);
}
Листинг 2.14.
Метод Write добавил строку в файл (рис. 2.33):
Рис. 2.33. Чтение и запись текста из файла
На диске, прилагаемом к книге, вы найдете приложение FileStream (Code\Glava2\ FileStream).
Object Browser и Intel Sense
В первой лекции мы рассматривали окно Object Browser. Использование этого окна зачастую может быть гораздо более удобным, чем поиск справочной информации в MSDN.
В предыдущем примере, при создании экземпляра Pisat класса StreamWriter следует указывать параметры, передаваемые классу,
— при использовании Intel Sense всплывающая подсказка указывает, какие именно параметры следует передавать (рис. 2.34).
увеличить изображение
Рис. 2.34. Группа из семи различных вариантов, предлагаемых Intel Sense. Для перемещения между вариантами щелкаем на кнопку со стрелкой — вариант 1 of 7
Следуя подсказке, мы могли указать и передать такие параметры:
StreamWriter Pisat = new StreamWriter("1.txt");
В этом случае файл 1.txt перезаписывался и текстовая строка помещалась в пустой файл. Для добавления в файл нужно указывать булевскую переменную:
StreamWriter Pisat = new StreamWriter("1.txt", true);
В этом случае можно было бы добавлять в файл текст, содержащий только латинские буквы. Для корректной записи кириллицы следует указывать кодировку, например Unicode, что мы и сделали:
StreamWriter Pisat = new StreamWriter("1.txt", true, System.Text.Encoding.Unicode);
Возможны и другие варианты передаваемых параметров — например, указание размера передаваемого буфера в байтах.
Предположим, мы не знаем, какую именно кодировку следует указывать. В самом деле, Intel Sense на рис. 2 не указывает, что именно кодировка Unicode принадлежит пространству имен System.Text.Encoding. Но мы можем просмотреть все доступные объекты и свойства этого пространства, используя окно Object Browser (рис. 2.35).
