Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C#_справочные сведения.doc
Скачиваний:
5
Добавлен:
26.04.2019
Размер:
384.51 Кб
Скачать

Урок 1. Первая программа под Windows

Ну, хватит нам программировать консольные приложения. Пора и что-нибудь поинтересней сделать. Поинтересней значит в данном случае под Windows. Наша программа будет делить два числа, которые пользователь введет в двух TextBox'ох. Результат будет показываться в label'е.

Запустите Visual Studio, создайте новый проект. Тип проекта выберите Visual C#, в качестве шаблона возьмите Windows Application:

Нажмите на OK. Разместите на форме 2 TextBox'а, label и кнопку. Форма будет выглядеть приблизительно так:

Из косметических изменений установите свойство Text для наших двух TextBox'ов в пустую строку. Сделайте на кнопке двойной щелчок для создания заготовки для кода. Внесите в нее следующие строки:

private void button1_Click(object sender, System.EventArgs e)

{

int result =

Convert.ToInt32(textBox1.Text)/Convert.ToInt32(textBox2.Text);

label1.Text=result.ToString();

}

Код, в общем-то, не сложный, хотя без конвертации типов не обошлось. Это мы делаем в выражениях типа

...

Convert.ToInt32(textBox1.Text)

...

Результатом такого выражения будет превращение строки типа "23" в число 23.

После того, как мы разделили одно число на другое, результат надо опять превратить в строку. Делаем мы это с помощью метода .ToString():

...

label1.Text=result.ToString();

...

А вот примерный результат программы:

Все вроде хорошо, но ведь обязательно найдется пользователь, котрый захочет разделить на ноль. Как-то эту ситуацию надо предусмотреть.

Урок 2. Перехватываем ошибки

На прошлом уроке мы с вами написали первую программу для Windows на C#. У нее было много недостатков, в частности, не была предусмотрена ситуация, когда пользователь попытается разделить на ноль. Также не было предусмотрено, если пользователь вообще попытается ввести не число, а, скажем, буквы.

Вот этим мы сейчас и займемся.

Для обработки ошибок в C# предусмотрен так называемый механизм исключений. Самое важное, что пока надо понять - это то, что исключения являются экземплярами классов. Все классы для исключений являются потомками класса System.Exception (либо класс исключения совпадает с самим классом System.Exception).

Раз исключения - это классы, то у них есть методы и свойства.

Исключения бывают как предопределенные (т. е. соответствующие классы уже существуют в системе .NET-классов), так и заданные программистом (в этом случае программист должен объявить собственные, производные от System.Exception классы).

Давайте изменим текст программы прошлого урока так, чтобы программы не вылетала с ошибкой, когда мы делим на ноль или вообще вводим не число. Вот текст нового обработчика щелчка на кнопке:

private void button1_Click(object sender, System.EventArgs e)

{

int result=0;

// Пытаемся произвести деление.

try

{

result =

Convert.ToInt32(textBox1.Text)/Convert.ToInt32(textBox2.Text);

label1.Text=result.ToString();

}

// Обрабатываем деление на ноль.

catch(DivideByZeroException ex)

{

label1.Text = ex.Message;

}

// Обрабатываем отальные ошибки.

catch

{

label1.Text = "Неизвестная ошибка!";

}

}

Как вы видите, мы заключаем потенциально опасную операцию в блок try:

// Пытаемся произвести деление.

try

{

...

}

Заключение в такой блок означает, что возникшую в нем ошибку мы сможем ниже обработать.

После блока try может идти один или несколько блоков catch. Каждый catch обслуживает свой вид исключения, которое указывается в скобках после catch. Если после catch в круглых скобках ничего не указать, то это будет обработчик по умолчанию (т. е. если исключение не было обработано одним из предыдущих обработчиков, то оно обработается тут). У нас обработчиков catch два - у первого параметром идет исключение деления на ноль, второй обрабчик - это обработчик по умолчанию:

// Обрабатываем деление на ноль.

catch(DivideByZeroException ex)

{

label1.Text = ex.Message;

}

// Обрабатываем остальные ошибки.

catch

{

label1.Text = "Неизвестная ошибка!";

}

Обратите внимание, что для обработчика деления на ноль мы в label выводим текст сообщения для возникшего исключения:

...

label1.Text = ex.Message;

...

Для конструкции try есть еще необязательный блок finally, который мы не используем.

После запуска наша программа будет выдавать при делении на ноль соответствующее сообщение:

При вводе же не чисел будет выдаваться сообщение "Неизвестная ошибка!":

Урок 3. Работа со строкой состояния (StatusBar)

На этом уроке мы посмотрим, как можно работать со строкой состояния. На панели Toolbox она выглядит так:

Перенесите ее на форму нашего созданного на прошлых уроках приложения.

Основное свойство у строки состояния - это Panels. Это коллекция, которая содержит все панели строки состояния. Первоначально на строке состояния никаких панелей нет. Для их добавления нажмите на кнопочку с многоточием справа от свойства Panels (сначала, разумеется, надо выделить на форме строку состояния):

Откроется окно StatusBarPanel Collection Editor. В этом окне для добавления панелей к нашей строке состояния нажмите два раза на кнопку Add:

Обратите внимание, что размер левой панели изменится - она подстраивается под размер содержимого.

Сейчас мы не будем подробно настраивать свойства панелей на строке состояния. Только установим свойство AutoSize для нуленой панели в Contents. Это означает, что размер строки состояния будет изменяться в соответствии с ее содержимым. Для закрытия окна StatusBarPanel Collection Editor просто нажмите на OK.

Для того, чтобы наши добавленные панели стали видимыми а строке состояния, свойство ShowPanels установите в True.

У каждой панели состояния есть свойство Text, которое отвечает, естественно, за текст, отображаемый на панели. Вот так, например, можно отобразить вывод ошибок в строку состояния:

private void button1_Click(object sender, System.EventArgs e)

{

...

// Обрабатываем деление на ноль.

catch(DivideByZeroException ex)

{

// Вывод описания ошибки в строку состояния.

statusBar1.Panels[0].Text = ex.Message;

}

...

}

Из свойств строки состояния отметим еще свойство логического типа SizingGrid - оно отвечат на наличие у строки состояния правого уголка, с помощью которого можно изменять размеры окна и свойсто Visible - оно, понятно, отвечает за показ строки состояния.

Урок 4. Работа со строкой состояния (StatusBar) 2

Продолжаем заниматься строкой состояния.

Вот так мы можем обрабатывать щелчок мышью на нашей строке состояния:

private void statusBar1_PanelClick(object sender,

System.Windows.Forms.StatusBarPanelClickEventArgs e)

{

// Производим действие только при щелчке правой кнопкой

// мыши на нулевой панели.

if(e.Button == MouseButtons.Right &&

e.StatusBarPanel == statusBar1.Panels[0])

{

MessageBox.Show("Нулевая панель");

}

}

Обратите внимание на параметр e типа StatusBarPanelClickEventArgs, передаваемый в наш обработчик. Он имеет такие свойства как X и Y (позволяют определить точку, на которой мы щелкнули), StatusBarPanel (позволяет определить панель, на которой щелкнули - см. пример выше), Button (служит для определения кнопки мыши - применение этого свойства тоже есть в нашем примере), Clicks - сколько раз была нажата и отпущена кнопка мыши и др.

Часто для строки состояния необходимо, чтобы правая панель имела фиксированный размер и располагалась всегда в превом углу формы. Это можно сделать, например, так:

private void statusBar1_Resize(object sender, System.EventArgs e)

{

statusBar1.Panels[0].Width = statusBar1.Width-100;

}

Мы тут добавили обработчик для изменения размера строки состояния. В нем мы устанавливаем размер левой панели только на 100 меньше, чем размер всей строки состояния. 100 же пикселов остается на правую панель.

Теперь правая панель имеет фиксированный размер:

Урок 5. Рисование на строке состояния

Для рисования на панели строки состояния мы должны, во-первых, для этой панели установить значение свойства Style в OwnerDraw (для этого мы выбираем на форме строку состояния и для нее нажимаем на кнопку с многоточием рядом со значением свойства Panels, далее в появившемся окне StatusBarPanel Collection Editor выбираем нужную панель строки состояния):

И вот теперь мы можем что-нибудь на строке состояния нарисовать. Для этого нам надо добавить обработчик события DrawItem. Внутри него можно написать что-нибудь такое:

private void statusBar1_DrawItem(object sender,

System.Windows.Forms.StatusBarDrawItemEventArgs sbdevent)

{

// Рисуем эллипс.

sbdevent.Graphics.DrawEllipse(new Pen(Color.DarkRed, 2),2, 2, 15, 15);

}

Результат выполнения программы будет такой:

Понятно, что так как мы получили контекст устройства, то мы можем нарисовать все, что захотим.

Можно вывести в панели строки состояния и иконку. Это делаем так: в окне StatusBarPanel Collection Editor задаем значение свойства Icon, задав для нее мя некоторого файла на диске. Иконка появится в строке состояния:

Урок 6. Создание потока

Что такое отдельный поток? В первом приближении это некоторая отдельная часть программы, которая может выполняться параллельно с другими частями программы. Ключевое слово тут - параллельно. Т. е. в одном своем потоке программа может делать некоторое длительное действие, а в другом потоке - другое, и эти действия будут выполняться параллельно.

Классический пример использования потоков можно найти в программе Word - тут в одном потоке может происходить фоновая проверка орфографии, в другом - печать текста пользователем, в третьем - сохранение файла на жесткий диск.

Для использования потоков в программе мы используем пространство имен System.Threading. Простейший поток - это экземпляр класса Thread из этого пространства имен.

Рассмотрим пример использования потоков в Windows-приложении. Создайте обычное Windows-приложение на C#. Разместите на форме две кнопки, заголовки на которых поменяйте на Start Thread и MsgBox соответственно. По первой кнопке мы запустим поток, в котором бы будем выполнять некоторое продолжительное действие (оно будет длиться несколько секунд). По второй кнопке мы будем выполнять некоторое параллельное действие (там мы просто вызовем обычный MessageBox).

Вот что вы должны добавить в текст программы (т. е. в класс формы):

...

using System.Threading; // Добавляем нужное пространство имен.

...

// Первый поток.

public Thread thr1;

// Вызываемая в потоке функция.

void f1()

{

// Запуск длинной операции.

for(int i=0; i<3000; i++)

{

// Результаты показываем в заголовке окна.

Text = i.ToString();

}

}

private void button1_Click(object sender, System.EventArgs e)

{

// Создание нового потока.

thr1 = new Thread(new ThreadStart(f1));

// Запуск нового потока.

thr1.Start();

}

private void button2_Click(object sender, System.EventArgs e)

{

// Некоторое параллельное действие.

MessageBox.Show("Some Action");

}

...

Наш поток создается в обработчике щелчка по первой кнопке. Обратите внимание, что при вызове конструктора мы указываем, что за метод будет выполняться в нашем потоке (а именно метод с именем f1):

...

thr1 = new Thread(new ThreadStart(f1));

...

Разумеется, метод f1 должен быть определен в нашем классе. В нем мы просто запускаем для демонстрации длинный цикл, в котором выводим возрастающие числа в заголовок окна.

Запускаем программу. При нажатии на первую кнопку запустится функция f1 в отдельном потоке. В заголовке окна замелькают последовательные числа. И, что самое важное, на вторую кнопку тоже можно будет нажимать до окончания работы обработчика первой кнопки - при этом появится соответствующий MessageBox:

Урок 7. Работаем с xml-файлом

Для работы с XML на платформе .NET существует пространство имен System.Xml. Подсоединим его к созданной нами Windows-программе. Для этого добавим строку

...

using System.Xml;

наверху файла.

На форме разместите кнопоку. По нажатии на эту кнопку наша программа выдаст из некого XML-файла все дочернии узлы первого уровня (т. е. вложенные непосредственно в корневой тег).

В обработчике щелчка по кнопке напишите следующий код:

/// <summary>

/// Получение всех дочерних элементов.

/// </summary>

private void button1_Click(object sender, System.EventArgs e)

{

// Создаем новый xml-документ.

XmlDocument xml = new XmlDocument();

// Загружаем в xml-документ xml-файл.

xml.Load("1.xml");

// Берем корневой узел (тег) xml-документа.

XmlNode d = xml.DocumentElement;

// Берем все дочерние теги.

XmlNodeList xnl = d.ChildNodes;

// Перебираем все дочерние теги.

for (int i=0; i<d.ChildNodes.Count; i++)

{

// Выводим атрибуты тегов.

MessageBox.Show(xnl[i].Attributes["text"].Value + " " +

xnl[i].Attributes["rustext"].Value);

}

}

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

Теперь займемся нашим xml-файлом. Его надо разместить в той же папке, что и наш exe-файл (или написать полный или относительный путь в методе Load для нашего xml-документа). Xml-файл может выглядеть так:

<?xml version="1.0" encoding="windows-1251" ?>

<item xmlns="http://127.0.0.1/1.xsd" text="root" rustext="Начало" url="/">

<item text="vc" rustext="Visual C++" url="/vcnet/">

<item text="mfc" rustext="MFC" url="" />

<item text="atl" rustext="ATL" url="" />

<item text="samples" rustext="Примеры" url="">

<item text="lines" rustext="Lines" url="" />

</item>

</item>

<item text="vbnet" rustext="VB.NET" url="/vbnet/">

<item text="console" rustext="Основы" url="" />

<item text="windows" rustext="Windows" url="" />

</item>

</item>

Как вы видите, тут несколько тегов, вложенных друг в друга. У нас все теги называются item, хотя это и не принципиально - вложенные теги могут иметь имена, отличные от корневого тега. У наших тегов присутствую атрибуты (text, rustext, url). У каждого атрибута есть некоторое значение.

Теперь запускаем программу. При нажатии на кнопку выведется два последовательных messagebox'а (если, разумеется, вы использовали именно приведенный xml-файл). В первом будет сообщение "vc Visual C++", во втором - "vbnet VB.NET".

Урок 8. Работаем с меню

Сейчас мы с вами рассмотрим, как использовать меню (а точнее, главное меню - экземпляр класса MainMenu) в программах на C#. Главное, что мы сделаем - это динамическое добавление пунктов меню и обработчиков для них.

Программа наша будет работать так - при нажатии на кнопку (а это будет единственная кнопка на форме) в главное меню будет добавляться еще один подпункт. Текст на этом подпункте будет очередное число ("1", "2", ...). При выборе любого пункта меню будет появляться messagebox с текстом, совпадающим с текстом на нажатом пункте меню.

Итак, создайте новый Windows-проект, разместите на форме кнопку и добавьте MainMenu из окна Toolbox:

MainMenu добавится не на саму форму, а ниже (и это логично, так как мы не можем задать точного положения главного меню на форме - x и y, например; так что и особого смысла в расположении на самой форме нет). В меню задайте имя самого первого пунта как "Menu". После этого наша форма будет выглядеть примерно так:

Теперь приступаем к коду.

Во-первых, добавим в класс переменную-счетчик и присвоим ей начальное значение:

public int num = 0;

Эта переменная будет увеличиваться на единицу при добавлении каждого нового пункта меню.

Теперь напишем обработчик для нажатия кнопки. Текст обработчика будет следующий:

private void button1_Click(object sender, System.EventArgs e)

{

// Увеличиваем счетчик пунктов меню.

num++;

// Создаем новый подпункт меню.

// Для него задаем надпись

// и обработчик выбора пользователем этого пункта.

MenuItem mi = new MenuItem(num.ToString(),

new System.EventHandler(this.menuItem_Click));

// Подсоединяем новый пункт меню к главному меню формы.

mainMenu1.MenuItems[0].MenuItems.Add(mi);

}

Обратите внимание, что в качаестве имени обработчика мы задали menuItem_Click. Разумеется, функцию с таким именем мы должны добавить в класс формы:

private void menuItem_Click(object sender, System.EventArgs e)

{

// Читаем текст на выбранном пользователе пункте меню.

string s = ((MenuItem)sender).Text;

// Выводим этот текст.

MessageBox.Show(s);

}

Посмотрите, как мы тут выясняем, какой пункт меню обрабатывается (а эта функция является обработчиком для всех пунктов нашего меню) - мы просто берем у передаваемого в функцию параметра sender свойство Text (предварительно мы приводим наш параметр к типу MenuItem):

...

string s = ((MenuItem)sender).Text;

...

Все! Компилируем и запускаем программу. Сколько раз мы нажмем на кнопку на форме, столько у нас появится новых подпунктов для меню:

И при выборе соответствующего пункта меню появится messagebox с соответствующим тестом, совпадающим с текстом на пункте меню.

Урок 9. Создаем контекстное меню из главного

Часто в программе контекстное меню повторяет один из пунктов главного. Например, у вашей программе может быть пункт Edit с подпунктами Cut, Copy и Paste. Контекстное меню для главного окна программы может содержать эти же самые три пункта. Разумеется, и обработчики у пунктов меню должны быть такие же, как и у главного.

Вот как это делается. Создайте Windows-программу. Добавьте главное меню, для него создайте несколько пунктов с обработчиками. Пусть для определенности у меню главного окна нашей программы два пункта верхнего уровня (File и Edit) и у пункта Edit три подпункта (Cut, Copy и Paste). Для подпунктов Cut, Copy и Paste добавьте обработчики-заглушки (например, MessageBox'ы).

Добавьте на форму кнопку, в обработчике которой напишите следующий код:

private void button1_Click(object sender, System.EventArgs e)

{

// Создание контекстного меню.

ContextMenu cm = new ContextMenu( );

// Слияние меню.

cm.MergeMenu(mainMenu1.MenuItems[1]);

// Подсоединение контекстного меню к главному окну.

ContextMenu = cm;

}

Запускаем программу. После нажатия на кнопку у окна нашей программы будет контекстное меню с пунктами, повторяющими подпунты пункта Edit главного меню:

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]