Реферат: Завершение работы программы обычно также происходит по инициативе пользователя и приводит к закрытию окна
Основы создания оконных приложений Особенности поведения оконных приложений.
Большинство современных программ относятся к категории оконных. Это значит, что их интерфейс (внешний вид) и поведение соответствует стандартам современных операционных систем:
Выполнение программы начинается с показа на экране ее главного (правильнее сказать, стартового) окна.
Далее программа выполняется обычно в режиме диалога с пользователем. Это означает, что если пользователь не осуществляет управляющих воздействий на программу (например, с помощью мыши или клавиатуры), то эта программа находится в режиме пассивного ожидания.
Активные действия программы проявляются в виде реакции на управляющие воздействия. С этой точки зрения поведение программы удобно представлять как множество диалоговых актов, каждый из которых можно представить как последовательность из 3-х взаимосвязанных этапов:
внешнее воздействие на программу
возникновение внутреннего события
программная реакция на событие.
Завершение работы программы обычно также происходит по инициативе пользователя и приводит к закрытию окна.
Описанные особенности поведения оконных программ на практике имеют исключения. Например, в некоторых случаях программа может показать стартовое окно, в котором в автоматическом режиме демонстрируется ее процесс выполнения и/или конечные результаты. После этого окно программы может автоматически закрываться.
Важным свойством оконных программ является высокая степень соответствия стандартам используемой операционной системы. Например, крайне редко окно программы может иметь не прямоугольную форму. Это же касается и элементов, из которых построены окна (кнопки, поля ввода, списки и т.д.) Принципиальная возможность «экзотических» приложений у программиста остается, но это, как правило, сопряжено со значительными усилиями при программировании и выходит за рамки нашего иложения.
Стандартизация интерфейса относится не только к внешнему виду, но и к способам управления визуальными элементами.
^ Первое оконное приложение
На практике при создании оконного приложения с помощью современных систем программирования (например, MS Visual Studio) программист получает значительную помощь от визуального дизайнера (Visual Designer) – компонента Visual Studio, который генерирует большую часть программного кода автоматически. Однако для лучшего понимания происходящего первый проект создадим почти полностью вручную.
Запустите Visual Studio и при создании нового проекта (New->Project) выберите шаблон EmptyProject. В результате в окне Solution Explorer Вы увидите решение, содержащее один проект. Этот проект «пустой», то есть не содержит ни одного файла с программным кодом.
Добавьте в этот проект новый файл с программным кодом: Add New Item Code File.
Внесите в этот файл следующее содержимое:
using System;
using System.Windows.Forms;
static class Program
{
static void Main()
{
Application.Run(new Form());
}
}
В тексте программы имеется директива using, обеспечивающая использование классов, очень важных для создания оконных приложений – классов из пространства имен System.Windows.Forms. Чтобы эти классы были доступными, нужно добавить в проект ссылку на это пространство имен: выберите проект и выполните для него команду Add Reference. В повившемся диалоговом окне на вкладке .NET найдите пространтво имен System.Windows.Forms и нажмите кнопку OK. Аналогично добавьте ссылку и на другое необходимое пространство имен – System.
В параметрах проекта укажите тип приложения – Project Properties: Output Type – Window Application.
Теперь программу можно выполнить. Результатом является появление стандартного пустого окна:
Хотя окно и пустое, однако оно уже демонстрирует все стандартные черты поведения «настоящих» окон.
^ Элементы управления
Как мы уже говорили, внешний вид (официально – визуальный интерфейс) оконного приложения основан на стандартном наборе элементов, которые можно размещать в окне (на форме) приложения. Существует несколько десятков видов таких элементов (их еще называют элементами управления, а по-английски – control). Каждый вид элементов управления реализован с помощью некоторого класса. Все классы элементов управления являются производными от класса Control. Класс Control и все классы элементов управления находятся в пространстве имен System.Windows.Forms. Наиболее популярными являются командные кнопки (класс Button), надписи или метки (класс Label) и поля ввода (класс TextBox). Программно управлять внешним видом элементов управления можно через соответствующие открытые свойства классов. Например, размер элемента управления можно узнать или изменить с помощью свойств Height (высота) и Width(ширина). Одной из важных составляющих Вашего умения создавать оконные приложения является знание этих многочисленных свойств.
Усовершенствуем нашу программу. После запуска в окне программы должны размещаться две кнопки. Размеры и расположение элементов на форме показаны на следующем рисунке:
Для реализации такого поведения текст программы следует изменить следующим образом:
using System;
using System.Windows.Forms;
using System.Drawing;
static class Program
{
static void Main()
{
int FormHeight=300;
int FormWidth=500;
Form f;
Button b1;
Button b2;
//создание и настройка формы
f = new Form();
f.ClientSize = new Size(FormWidth, FormHeight);
//создание и настройка первой кнопки
b1 = new Button();
b1.Left = FormWidth / 5; //расстояние левой грани кнопки от левой грани клиентской области формы
b1.Top = FormHeight / 3; //расстояние верхней грани кнопки от верхней грани клиентской области формы
b1.Width = FormWidth / 5; //ширина кнопки
b1.Height = FormHeight / 3; //высота кнопки
//создание и настройка второй кнопки
b2 = new Button();
b2.Bounds = new Rectangle(3*FormWidth / 5, FormHeight / 3, FormWidth / 5, FormHeight / 3);
//добавление кнопок на форму
f.Controls.Add(b1);
f.Controls.Add(b2);
//запуск цикла обработки событий
Application.Run(f);
}
}
Текст программы существенно вырос. Объясним все подробнее.
В программе используются классы из пространства имен System.Drawing. Поэтому не забудьте доавить в проект ссылку (reference) на это пространство имен и соответствующую директиву using в текст программы (стр.03).
Для удобства управления размерами в стр. 08 и 09 вводятся вспомогательные переменные FormHeight (высота формы) и FormWidth(ширина формы). Они определяют размер внутренней области окна (клиентской области), не включающей заголовок и рамку вокруг окна.
Программа должна обращаться к свойчтвам формы и кнопок. Поэтому для ссылки на эти объекты в стр. 10-12 описываются соответствующие переменные.
После создания объекта-формы в стр.14 ее клиентский размер задается с помощью свойства ClientSize. Значением этого свойства является ссылка на объект класса Size из пространства имен System.Drawing (стр.15).
Первая кнопка создается в стр.17. Ее положение и размер задаются свойствами Left, Top, Width и Heigh (стр.18-21).
Вторая кнопка создается в стр.23. Ее положение и размер задаются другим способом – с помощью свойства Bounds (границы), значением которого является объект Rectangle (прямоугольник) (стр.24). В дальнейшем выбирайте тот способ управления, который Вам больше подходит.
Следующий момент очень важен и часто вызывает на практике ошибки. Объекты кнопки пока никак не связаны с объектом-формой. Поэтому программа хотя и создает все объекты, но не показывает кнопки внутри формы. Для показа кнопок на форме их необходимо добавить в специальный контейнер формы, который доступен через свойство Controls. Это делается методом Add в стр. 26 и 27.
Наконец в стр. 29 форма показывается на экране и начинает взаимодействовать с пользователем.
^ Событийно-управляемая модель выполнения оконного приложения
Исходный текст первого оконного приложения соответствует правилам языка C#: программа состоит из классов (одного класса Program) и имеет «точку входа» - метод Main. В нем выполняется оператор, выполнение которого и реализует поведение простого окна:
Application.Run(new Form());
Здесь «работает» статический метод Run класса Application. Класс Application предоставляет несколько статических методов и свойств для управления оконным приложением. Для создания оконного приложения необходимо уметь «запускать» оконное приложение – это и делает метод Run.
Теперь разберемся, что при этом происходит. В момент запуска на экране появляется изображение окна. Далее запускается цикл обработки событий. Событием называется порция информации, автоматически создаваемая операционной системой (Windows) в ответ на физическое или логическое внешнее воздействие. Например, пользователь щелкнул левой кнопкой мыши. В этом случае событие возникнет, если этот щелчок был выполнен по «особому» месту, например по кнопке, нарисованной в окне. Возникновение события еще не означает, что программа на него отреагирует каким-то ответным действием. Для этого необходимо, чтобы программист, создавший эту программу, реализовал программный фрагмент, отвечающий за реакцию на это событие. В терминах языка C# - это метод-обработчик события. После того, как этот метод завершит свою работу, программа переходит к ожиданию следующего «достойного внимания» события.
Если новое событие возникло раньше того, когда было обработано текущее событие, новое событие не теряется, а помещается в очередь событий.
Такой цикл обработки событий завершается, когда возникает некоторой специальное событие, приводящее к завершению работы приложения.
Описанный здесь сценарий работы оконного приложения схематически изображен на следующем рисунке:
Мы видели, что даже первое оконное приложение уже реагирует на целый ряд стандартных событий. Где же обработчики этих событий? Эти обработчики определены в стандартном классе Form.
Наша первая программа, хотя и выглядит как стандартное окно Windows, является весьма пассивной, поскольку не реагирует ни на какие события, кроме «неинтересных» стандартных событий управления окном. Заставим программу действовать интереснее: когда пользователь щелкнет мышью по любой кнопке, на ее поверхности появится текущее время.
Для достижения этой цели необходимо выполнить 2 действия:
Написать специальный метод-обработчик для реакции на требуемое событие.
Связать этот метод с событием элемента управления.
Измененный текст программы теперь выглядит следующим образом:
using System;
using System.Windows.Forms;
using System.Drawing;
static class Program
{
private static int FormHeight=300;
private static int FormWidth=500;
private static Form f;
private static Button b1;
private static Button b2;
static void Main()
{
//создание и настройка формы
f = new Form();
f.ClientSize = new Size(FormWidth, FormHeight);
//создание и настройка первой кнопки
b1 = new Button();
b1.Left = FormWidth / 5;
b1.Top = FormHeight / 3;
b1.Width = FormWidth / 5; //ширина кнопки
b1.Height = FormHeight / 3; //высота кнопки
b1.Click += ButtonClick;
//создание и настройка второй кнопки
b2 = new Button();
b2.Bounds = new Rectangle(3*FormWidth / 5, FormHeight / 3, FormWidth / 5, FormHeight / 3);
b2.Click += ButtonClick;
//добавление кнопок на форму
f.Controls.Add(b1);
f.Controls.Add(b2);
//запуск цикла обработки событий
Application.Run(f);
}
private static void ButtonClick(object sender, EventArgs ea)
{
((Button)sender).Text = DateTime.Now.ToString();
}
}
Полужирным шрифтом выделенны изменения в тексте.
В классе Program уже появился второй метод. В дальнейшем классы будут содержать довольно большое количество методов. Как Вы уже должны знать, эти методы могут безпрепятсвенно пользоваться общей для них информацией, содержащейся в переменных класса (даже если ети переменные закрыты – private). Поэтому важная информация, интенсивно используемая методами класса, обычно представлена переменными класса. В нашем примере переменными стали размеры окна FormHeight и FormWidth (стр.06 и 07), сама форма f (стр. 08) и кнопки b1 и b2 (стр. 09 и 10).
Метод-обработчик написан как метод класса Program (стр.33-36). При написании методов-обработчиков нужно соблюдать следующие требования:
А) обработчик никогда ничего не возвращает (void);
Б) первым параметром обработчика обычно является переменная типа object – общего базового класса всех классов .NET. Существуют ситуации, когда тип этого параметра может быть другим.
В) вторым параметром обработчика является переменная класса EventArgs или производного от него.
Решение о том, что обработчик будет методом класса Program, не является обязательным требованием. В нашем случае это сделано для сохранения простоты программы. Использование модификаторов private и static также не является обязательным. В нашем случае обработчик является закрытым, потому что используется только в классе Program, а статическим потому, что используется в статическом методе Main.
Связь обработчика с событием-щелчком для кнопок b1 и b2 определена в стр. 22 и 26. Это обязательно делается оператором присваивания +=. Обратите внимание на «странность» этих операторов. Операция += в данном случае совсем не занимается арифметическим накоплением числовой информации. Правым ее операндом является название метода-обработчика. В то же время в левой части += указано событие Click для кнопки b1 и b2. Упрощенное (но в принципе правильное) представление о том, чем яляется событие – это список названий методов-обработчиков, которые срабатывают, когда с элементом управления происходит соответствующее внешнее воздействие. Разработчики классов для стандартных элементов управления предусмотрели для них довольно большой спектр событий.
В нашей программе обе кнопки используют одинаковый обработчик. Но ведь в процессе обработки надпись должна измениться именно на той кнопке, по которой щелкнул пользователь. Для этого и используется первый параметр обработчика – он ссылается на тот объект, с которым произошло событие. События могут происходить с любыми объектами (даже не визуальными элементами управления). Поэтому тип этого параметра – object. Внутри обработчика этот параметр нужно явным образом приводить к требуемому типу (в нашем случае – Button).
Для получения текущей даты и времени обработчик использует статическое свойство Now класса DateTime.
^ Принцип распределения ответственности
В предложенном варианте программы единственный класс Program отвечал за создание формы и за запуск приложения. Полезно разделить эти обязанности между двумя классами, например MainWindow и Program:
class Program
{ public static void Main()
{ Application.Run(new MainWindow()); }
}
class MainWindow:Form
{ private int FormHeight = 300;
private int FormWidth = 500;
private Button b1;
private Button b2;
public MainWindow()
{
this.ClientSize = new Size(FormWidth, FormHeight);
//создание и настройка первой кнопки
b1 = new Button();
b1.Left = FormWidth / 5; b1.Top = FormHeight / 3;
b1.Width = FormWidth / 5;b1.Height = FormHeight / 3;
b1.Click += ButtonClick;
//создание и настройка второй кнопки
b2 = new Button();
b2.Bounds = new Rectangle(3 * FormWidth / 5, FormHeight / 3, FormWidth / 5, FormHeight / 3);
b2.Click += ButtonClick;
//добавление кнопок на форму
this.Controls.Add(b1);
this.Controls.Add(b2);
}
private void ButtonClick(object sender, EventArgs ea)
{
((Button)sender).Text = DateTime.Now.ToString();
}
}
Прокомментируем изменения.
Самое главное – за создание формы отвечает класс MainWindow, производный от стандартного класса Form. Это значит, что объекты нашего нового класса полностью унаследовали возможности стандартных окон.
Класс программ стал чрезвычайно коротким – его задачей является выполнить при запуске программы (метод Main!) 2 действия – создание объекта класса MainWindow, а затем запуск цикла обработки событий для этого объекта-формы. Это типичная ситуация для оконных приложений, поэтому в дальнейших программах класс Program почти всегда будет оставаться именно таким. Вы даже можете забыть о его существовании ().
Первое, что происходит при запуске программы – создание окна. А за создание объектов классов, как известно, отвечают конструкторы. Основную часть текста программы как раз и составляет конструктор класса MainWindow. Теперь объекты-кнопки представлены переменными класса MainWindow. Переменная f пропала – ее представляет ключевое слово this.
Обработчик щелчка – метод класса MainWindow.
Почему такая структура предпочтительнее. Пока без доказательств (а строгие доказательства здесь вряд ли возможны) повторим заголовок данного параграфа: в такой структуре программа разбита на несколько частей (классов), между которыми правильно распределены ответственности – именно такой подход называют принципом «разделяй и властвуй» в программировании. Следуя этому принципу, мы сможем создавать большие и, в то же время, не слишком сложные программы.
Замечание! Если Вы попытаетесь открыть в VisualStudio файл, содержащий такой исходный код, то получите сообщение об ошибке следующего содержания:
«The class MainWindow can be designed, but is not the first class in the file. Visual Studio requires that designers use the first class in the file. Move the class code so that it is the first class in the file and try loading the designer again.»
В свободном переводе это означает следующее – визуальному дизайнеру «не нравится», что класс формы не первый в файле. Строго говоря, это не ошибка. Но зато если Вы просто переместите класс MainWindow в начало, то сможете и увидеть Вашу форму в режиме дизайна еще до запуска программы.
^ Динамическое управление обработчиками
Вы составили себе представление о том, как операция += связала событие с обработчиком. И тут возникает несколько логичных вопросов:
Вопрос 1: Перед тем как оператор
b1.Click += ButtonClick;
связал с щелчком по кнопке b1 обработчик ButtonClick, был ли список обработчиков пуст?
Ответ 1: Нет. Уже для стандартного класса Form определены обработчики щелчка по кнопкам. Это можно заметить и визуально – щелчки по кнопкам приводят к эффекту «вдавливания» кнопки. Вопрос, который пока останется без ответа – где находятся эти обработчики?
Вопрос 2: Можно ли связать с событием несколько обработчиков и что при этом происходит?
Ответ 2: Связать несколько обработчиков можно путем многократного выполнения оперции +=. В этом случае все обработчики срабатывают последовательно в том порядке, в котором они добавлялись в множество обработчиков события.
Вопрос 3: Можно ли выполнить обратную операцию – исключить обработчик из списка?
Ответ 3: Да, это делается с помощью аналогичной операции -=.
Попробуем продемонстрировать это на примере. Рассмотрим, как работает программа, содержащая следующий класс MainWindow:
class MainWindow:Form
{
. . .
public MainWindow()
{
. . .
b1.Click += ButtonClick;
b1.Click += NewButtonClick;
. . .
b2.Click += ButtonClick;
b2.Click += NewButtonClick;
. . .
}
private void ButtonClick(object sender, EventArgs ea)
{ ((Button)sender).Text = DateTime.Now.ToString(); }
private void NewButtonClick(object sender, EventArgs ea)
{ this.Text=((Button)sender).Text;
if (sender == b1)
b2.Click -= NewButtonClick;
else
b1.Click -= NewButtonClick;
}
}
Первоначально (после создания формы) обе кнопки реагируют на щелчок двумя обработчиками:
первый обработчик выводит на кнопку дату и время;
второй обработчик выводит в заголовок формы надпись на кнопке, по которой щелкнули.
Допустим, сначала пользователь щелкнул по первой кнопке. Тогда условный оператор во втором обработчике исключит этот обработчик из списка обработчиков щелчка второй кнопки. Таким образом, «победила» первая кнопка – теперь только она выводит дату и время и на своей поверхности и в заголовке формы.
Аналогично «победит» вторая кнопка, если пользователь щелкнет сначала по ней.
^ Элемент управления Timer
Модель выполнения оконного приложения существенно ориентирована на события. Можно говорить, что оконное приложение функционирует только в ответ на происходящие с ним (его элементами) события. Отсюда можно сделать вывод – если пользователь не дотрагивается до «органов управления» компьютером, программа бездействует в ожидании новых событий. Это означало бы, что мы не можем реализовать большое количество задач, которые демонстрируют автономную, независимую от пользователя динамику.
В качестве простого примера рассмотрим решение следующей задачи. В окне приложения находится небольшая квадратная кнопка, которая каждую секунду перемещается в случайное место, оставаясь целиком в пределах окна. Пользователь пытается успеть щелкнуть по поверхности кнопки. Если ему это удается сделать 3 раза, кнопка перестает двигаться.
Для решения этой задачи нужно обеспечить перемещение кнопки независимо от каких-либо действий пользователя. Тем не менее, это перемещение может быть только результатом реакции на некоторое событие. Для разрешения сложившегося противоречия нам нужно событие, которое будет происходить без участия пользователя, и связано с течением времени. Специально для таких задач предусмотрен элемент управления Timer, очень напоминающий обычный будильник. Таймер умеет порождать через указанный интервал времени сигнал – событие Tick. Интервал времени определяется свойством Interval, измеряемым в миллисекундах (1 сек = 1000 миллисекунд). Элемент Timer имеет логическое свойство Enabled: true означает, что Timer включен и генерирует событие Tick, false – Timer выключен. И последнее замечание – Timer не является визуальным элементом. Как следствие, его не нужно помещать в коллекцию Controls объекта-формы.
Далее приведем код класса формы, решающий нашу задачу:
class MyForm:Form
{ private Button target; //кнопка-цель
private Timer timer;
private const int TSize = 50; //размер кнопки
private int lifes; //количество "жизней" кнопки
public MyForm()
{ lifes = 3;
target = new Button();
Jump();
target.Click += TargetClick;
this.Controls.Add(target);
timer = new Timer();
timer.Interval = 1000;
timer.Tick += TimerTick;
timer.Enabled = true;
}
private void TimerTick(object sender, EventArgs ea)
{
Jump();
}
private void TargetClick(object sender, EventArgs ea)
{
lifes--;
if (lifes <=0)
timer.Tick -= TimerTick;
// или timer.Enabled = false;
}
private void Jump()
{
Random r = new Random();
int Left=r.Next(0,this.ClientSize.Width-TSize);
int Top=r.Next(0,this.ClientSize.Height-TSize);
target.Bounds = new Rectangle(Left, Top, TSize, TSize);
}
}
Комментарии
^ Элемент управления ListBox
Часто возникает необходимость отображать в окне большое множество информационных элементов на сравнительно небольшом пространстве. Для этого хорошо подходят списки с вертикальными линейками прокрутки. Такие элементы создаются как объекты класса ListBox. Класс ListBox сочетает в себе свойства визуального элемента и знакомого Вам контейнерного класса ArrayList.
Для демонстрации возможностей этого элемента создайте оконное приложение, в окне которого располагаются кнопка button1 и список listBox1.
Для управления обычными визуальными свойствами у класса ListBox имеются уже знакомые свойства – Height, Width, Top, Left и т.д. Для доступа к «контейнерным» функциям следует использовать свойство Items. Items представляет все множество элементов, находящихся в списке. Возможности этой коллекции сходны с возможностями ArrayList. В первую очередь это означает, что в список с помощью метода Add можно добавлять элементы любых типов.
Например, для добавления в список целого числа 1 можно выполнить оператор listBox1.Items.Add(1).
Следующий обработчик щелчка по кнопке добавляет в список разные объекты:
private void button1_Click(object sender, EventArgs e)
{
Random r=new Random();
switch (r.Next(1, 5))
{ case 1: listBox1.Items.Add(1); break;
case 2: listBox1.Items.Add('a'); break;
case 3: listBox1.Items.Add("Hi"); break;
case 4: listBox1.Items.Add(new Random()); break;
}
}
Все элементы успешно отображаются в списке. Даже объект-генератор случайных чисел:
Объекты любых типов (классов) отображаются в списке с помощью метода ToString своего класса. Если в классе нет собственного метода ToString, действует унаследованный метод – обычно это метод ToString из класса Object, который возвращает строку с полным именем класса.
В списке объекты хранятся в первоначальном виде: значимые типы непосредственно копируются в список, а для ссылочных в список помещается только ссылка на объект.
Метод Add добавляет элементы в конец списка.
Для программного доступа к выбранному в списке элементу используются свойства SelectedIndex (номер выбранного элемента) и SelectedItem(сам выбранный элемент, это свойство имеет тип Object).
Добавьте на форму еще одну кнопку (button2). Сделаем так, чтобы в результате щелчка по кнопке, в заголовке формы отображался выбранный элемент. Для этого напишем следующий обработчик:
private void button2_Click(object sender, EventArgs e)
{ if (listBox1.SelectedIndex != -1)
Text = Convert.ToString(listBox1.SelectedItem);
else
Text = "Элемент не выбран";
}
Здесь учтена ситуация, когда в списке ничего не выбрано. В этом случае свойство SelectedIndex равно -1.
Наконец, для взаимодействия с пользователем элемент ListBox обычно использует событие SelectedIndexChanged. Это событие происходит в любом случае изменения номера выбранного элемента:
- в случае выбора пользователем элемента списка мышью;
- в случае выбора пользователем элемента списка клавиатурой;
- изменение значения свойства SelectedIndex программным путем.
Рассмотрим следующий пример обработчика этого события:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{ if ((listBox1.SelectedIndex < 5) &&
(listBox1.SelectedIndex < listBox1.Items.Count-1))
listBox1.SelectedIndex++;
}
Если пользователь выбирает мышью некоторый элемент в списке, возникает первое событие SelectedIndexChanged. Далее при выполнении условия оператора if осуществляется программное увеличение свойства SelectedIndex. Это в свою очередь приводит к возникновению второго события SelectedIndexChanged, его обработке и т.д. Этот процесс останавливается благодаря условию if либо на пятом элементе списка, либо в конце списка.
Далее приводятся другие популярные средства управления коллекцией Items:
public int Count
Свойство, позволяющее узнать количество элементов в коллекции
public void AddRange (Object[] items)
Добавление в коллекцию массива объектов
public void AddRange (ObjectCollection value)
Добавление в коллекцию содержимого другого списка
public virtual void Clear ()
Очистка содержимого коллекции
public bool Contains (Object value)
Определяет, найден ли данный объект в коллекции
public int IndexOf (Object value)
Определяет позицию данного элемента в коллекции (-1, если не найден)
public void Insert (int index,Object item)
Добавляет данный объект в коллекцию в указанную позицию
public void Remove (Object value)
Удаляет данный элемент из коллекции
public void RemoveAt (int index)
Удаляет из коллекции объект в указанной позиции
Этот перечень еще раз подтверждает сходство коллекции Items с объектами ArrayList. Естественно, коллекцию Items можно индексировать.
^ Параметры событий. Каскад событий
В предыдущих примерах нам приходилось использовать первый параметр обработчиков событий – Object sender. Через этот параметр мы можем получить доступ к элементу управления, с которым произошло событие. Это особенно важно, когда несколько элементов управления используют один обработчик.
Однако у каждого обработчика имеется и второй параметр, который имеет тип EventArgs, либо производный от него. Этот параметр содержит дополнительную информацию об обстоятельствах возникновения события. Содержание этой информации, естественно, зависит от вида события.
Допустим, нам хотелось бы знать, в какой части поверхности кнопки button1 пользователь осуществил щелчок. Искать информацию о координатах щелчка при обработке события Click не удастся. Для этого существует более специализированное событие MouseClick. Обработчик этого события должен иметь параметр класса MouseEventArgs, который и предоставит Вам информацию о координатах щелчка в виде свойств X и Y:
private void button1_MouseClick(object sender, MouseEventArgs e)
{ if (e.X < button1.Width / 2) Text = "Левая часть";
else Text = "Правая часть";
}
Как ни странно, событие MouseClick поисходит только при щелчке левой клавишей мыши.
Также можно получить и информацию о клавише мыши, которая использовалась в момент щелчка. Однако для этого придется использовать событие MoseDown (клавиша мыши нажата) или MouseUp (клавиша мыши отпущена):
private void button1_MouseDown(object sender, MouseEventArgs e)
{ switch (e.Button)
{ case MouseButtons.Left: Text="Левая клавиша"; break;
case MouseButtons.Middle: Text="Средняя клавиша"; break;
case MouseButtons.Right: Text="Правая клавиша"; break;
}
}
Как видите, здест используется свойство Button параметра события e. Это свойство имеет перечислимй тип MouseButtons.
Для улучшения контроля элементами управления рекомендуем познакомиться и с другими «мышиными» событиями:
^ Использование визуального дизайнера
Познакомившись с созданием простейших оконных приложений «вручную», рассмотрим средства автоматизации написания прграмм, предлагаемые Visual Studio.
Для начала попробуем максимально использовать Visual Designer – компонент Visual Studio, обеспечивающий высокую степень визуальной связи между системой и программистом.
Следующая наша программа покажет на экране окно с тремя элементами управления – текстовой надписью, полем ввода и кнопкой.
При создании проекта выбирайте шаблон WindowsApplication. В результате в Visual Studio появится окно формы и панель элементов управления Toolbox.
Методом drag&drop перенесите из Toolbox на форму и должным образом расположите по одному элементу Label, Button и TextBox. С помощью обычных «мышиных» приемов сжатия и растягивания Вы можете регулировать размеры не только элементов управления на форме, так и самой формы.
^ Редактирование свойств элементов управления
Набор элементов управления (Toolbox) визуально представляет множество стандартных классов из пространства имен System.Windows.Forms. Все они являются производными от класса Control. Как и любой класс C#, классы элементов управления имеют открытые свойства. Однако в этом случае свойства обычно соответствуют визуально наблюдаемым характеристикам элементов. Например, свойства Height и Width определяют высоту и ширину элемента управления. Значения некоторых свойств автоматически устанавливаются в процессе манипуляции элементами управления с помощью мыши. Более универсальным способом задания свойств является использование специального окна свойств Properties в Visual Studio
Это окно представляет собой таблицу из двух столбцов. При выборе мышью на форме элемента в первом столбце этой таблицы показываются названия свойств. Во втором столбце можно указывать значения этих свойств.
Особый интерес представляет свойство Name. Оно имеется у каждого вида элементов управления и определяет программное имя (имя переменной), по которому можно получить доступ в исходном коде к выбранному элементу управления. Visual Designer автоматически назначает «невзрачные» имена – label1, tbutton1 и т.д. Обычно программист изменяет их на более содержательные.
В нашем случае для элемента-надписи (переменная label1 класса Label) укажите свойство Text равным строке «Число», а для элемента-кнопки (переменная button1 класса Button) - свойство Text равным строке «Делай».
Теперь заставим нашу единственную кнопку регировать на щелчок показом внутри метки label1 строки, являющейся удвоенной копией строки, введенной пользователем в поле ввода textBox1.
Для этого одинарным щелчком выберите элемент, которому Вы хотите назначить обработчик – в нашем случае кнопку button1. Далее в окне свойств перейдите в режим работы с событиями, нажав кнопку-«молнию» .Теперь в окне Properties с многочисленными событиями класса дважды щелкните по событию Click. В ответ на это Visual Studio выполнит два действия:
Предоставит Вам сгенерированный текст «заготовки» метода-обработчика:
private void button1_Click(object sender, EventArgs e)
{
}
Этот текст будет сгенерирован в файле Form1.cs. Тело этого метода Вам предстоит дописать самостоятельно. Для достижения поствленной цели будет достаточно одного оператора:
label1.Text = textBox1.Text + textBox1.Text;
В файле Form1.Designer.cs в сгенерированном методе InitializeComponent появится оператор, связывающий метод-обработчик с событием кнопки:
this.button1.Click += new System.EventHandler(this.button1_Click);
Здесь используется более длинный (и более точный) вариант этого оператора.
^ Анализ сгенерированного исходного кода
Исходный код получившегося на данный момент приложения распределен между тремя файлами Program.cs, Form1.cs и Form1.Designer.cs.
Файл Program.cs - его содержимое совсем небольшое и напоминает код, написанный в «пустом» оконном приложении. Главное в нем – уже знакомый оператор:
Application.Run(new Form1());
Важное отличие – при вызове метода Run используется не стандартный класс Form, а класс Form1. Это производный от Form класс, уже сгенерированный визуальным дизайнером в файлах Form1.cs и Form1.Designer.cs. Эти файлы содержат две «половинки» класса Form1. Такое разделение осуществляется с использованием ключевого слова partial в заголовках класса в обоих файлах:
Файл Form1.cs
public partial class Form1 : Form
. . .
Файл Form1.Designer.cs
partial class Form1
. . .
Главный вопрос – зачем нужно такое разделение. Это удобно в случае активного использования визуального дизайнера. Файл Form1.cs используется программистом для самостоятельного изменения класса. Содержимое файла Form1.Designer.cs автоматически заполняется кодом, сгенерированным визуальным дизайнером.
В текущем состоянии файл Form1.cs очень короткий:
using System;
//другие необходимые директивы using
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
Таким образом, в классе Form1 сейчас имеется конструктор, вызывающий метод InitializeComponent. Этот метод содержится в файле Form1.Designer.cs.
Файл Form1.Designer.cs уже сейчас довольно громоздкий. Поэтому при его рассмотрении опустим необязательные подробности. Сначала найдите в этом файле описания переменных класса – они находятся в конце класса Form1:
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox textBox1;
Узнаете!? Эти три переменные button1, label1 и textBox1 сгенерированы в ответ на перетаскивание соответствующих элементов из Toolbox на форму.
Кроме того, в классе Form1 определен закрытый метод InitializeComponent:
В начале этого метода для переменных button1, label1 и textBox1 создаются соответствующие объекты:
this.button1 = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.textBox1 = new System.Windows.Forms.TextBox();
Далее для каждого элемента управления происходит установка его свойств. Например, для кнопки button1 это выглядит так:
this.button1.Location = new System.Drawing.Point(92, 52);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(61, 26);
this.button1.TabIndex = 0;
this.button1.Text = "Делай";
this.button1.UseVisualStyleBackColor = true;
Напомним, что события Click кнопки Button1 был предусмотрен обработчик, который «привязан» к событию оператором:
this.button1.Click += new System.EventHandler(this.button1_Click);
Аналогично выглядит настройка элементов label1 и textBox1.
Для того чтобы форма визуально отображала элементы управления, недостаточно того, что эти элементы являются переменными класса формы. Необходимо разместить их в специальной коллекции, доступной через свойство Controls базового класса Form. В сгенерированном коде этим занимаются следующие строки:
this.Controls.Add(this.textBox1);
this.Controls.Add(this.label1);
this.Controls.Add(this.button1);
В следующем листинге рассмотренная структура программного кода представлена схематично.
^ Файл Program.cs
class Program
{. . .
static void Main()
{ . . .
Application.Run(new Form1());
}
}
Файл Form1.cs
public partial class Form1 : Form
{ public Form1()
{ InitializeComponent(); }
// обработчики событий
private void button1_Click(object sender, EventArgs e)
{ . . .}
. . .
}
^ Файл Form1.Designer.cs
partial class Form1
{ . . .
#region Windows Form Designer generated code
private void InitializeComponent()
{ //создание объектов-элементов управления
this.button1 = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.textBox1 = new System.Windows.Forms.TextBox();
// button1
this.button1.Location = new System.Drawing.Point(192, 23);
. . .
this.button1.Click += new System.EventHandler(this.button1_Click);
// label1
. . .
// textBox1
. . .
// Form1
. . .
this.Controls.Add(this.textBox1);
this.Controls.Add(this.label1);
this.Controls.Add(this.button1);
}
#endregion
//описание переменных для элементов управления
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox textBox1;
}
Далее можно рассмотреть несколько других примеров:
- крестики-нолики.
Дальнейшая логика курса – рассмотрим способы постоянного хранения. Тогда можно будет рассмотреть архитектурные принципы, основанные на разделении на бизнес-логику, визуальный интерфейс и источник данных.
^ Сохранение результатов
Возможность храни
еще рефераты
Еще работы по разное
Реферат по разное
Основные сетевые команды Linux
17 Сентября 2013
Реферат по разное
Розділ swot-аналіз
17 Сентября 2013
Реферат по разное
Положение о Web-сайте Муниципального общеобразовательного учреждения Средней общеобразовательной школы №4 городского округа Стрежевой Томской области
17 Сентября 2013
Реферат по разное
Технологии как среду интеграции для контроля изменений состояния окружающей среды и климата
17 Сентября 2013