Глава 22
В этой главе вы узнаете что обозначает термин WinForms.
Узнаете что такое форма и управляющие элементоы
А так же о том, как происходит обработка событий, происходящих на форме.
Наверное, компьютерные гуру компании Microsoft, работавшие над созданием среды .NET, хотели быть уверены, что их творение полюбят все. Среда .NET способна решать разнообразнейшие задачи: от управления вводом-выводом данных, до создания программ, работающих в Web и оснащенных самым потрясающим графическим интерфейсом.
Эта глава посвящена вопросам разработки графического пользовательского интерфейса (Graphical User Interface-— GUI) с использованием .NET-классов GUI, которые обычно обозначаются термином WinForms. (Формально эти классы называются Windows Forms, но программисты, которые с ними работают, называют их просто WinForms.)
.NET-классы WinForms подключаются к интерфейсу среды Windows и взаимодействуют с его элементами (диалоговыми окнами, кнопками, меню, списками и т.п.). Они
непосредственно обращаются к компонентам среды Windows, которые представляют отдельные элементы пользовательского интерфейса.
Например, объект класса System.
Windows.Forms.CheckBox выглядит и работает точно так же, как и любой другой
флажок (check box), расположенный где-нибудь в диалоговом окне Windows. Это означает, что вы можете создавать .NET-приложения, используя все преимущества среды .NET, CLR и всего, что им сопутствует; в то же время они будут иметь все характеристики и возможности приложений Windows.
Вверх
Классы WinForms представляют одну из частей Windows API (Application Programming
Большинство классов WinForms используются для создания визуальных средств управления,
Основной набор инструментов
Interface— программный интерфейс приложения). Другие части Windows API
представлены другими компонентами .NET. Например, интерфейсу графических устройств
(Graphical Device Interface— GDI) в среде .NET соответствуют классы System.
Drawing.
которые являются составными компонентами среды Windows. Некоторые из них, например объекты
класса ContextMenu, не всегда отображаются на экране. Способ отображения других заранее
определен. Так, например, объекты класса MainMenu всегда отображаются в верхней части окна
программы.
В табл 22.1 приведен список тех классов WinForms, которые, вероятнее всего, вы будете использовать в повседневной работе.
Таблица 22.1. Наиболее часто используемые классы WinForms
Класс
System.Windows.Form |
Описание |
Application
|
Управляет программой, в том числе ее запуском и остановкой
|
Button | Кнопка, иногда называемая также командной кнопкой. Щелчок на кнопке влечет за собой выполнение каких-то действий |
CheckBox
|
Флажок. Можно выбирать сразу несколько флажков, принадлежащих одной группе (в отличие от переключателей)
|
Checked List Box | Список флажков, который можно прокручивать. Элемент может вмещать в себя множество флажков, занимая при этом небольшое пространство |
Combo Box
|
Поле со списком. В нем вы можете либо набрать собственное значение, либо выбрать из списка одно из предлагаемых значений. Существует несколько видов полей со списком |
ContextMenu | Контекстное меню (открывается после щелчка правой кнопкой мыши). Позволяет пользователю выбрать команды или опции, относящиеся к тому элементу, на котором он щелкнул |
DataGrid
|
Таблица данных, в которой отображается информация, сохраненная в источнике данных ADO.NET. Столбцы таблицы данных соответствуют полям в источнике данных, а строки - записям |
FileDialog | Диалоговое окно, предоставляющее пользователю возможность обзора для выбора файла, который должен быть открыт, или папки, в которой должен быть сохранен новый файл |
Form
|
Базовый класс WinForms, из которого путем наследования создаются классы, описывающие все формы вашей программы. Производные классы могут представлять как постоянные, так и диалоговые окна |
Label | Надпись. Отображает текст, который обычно относится к другим элементам управления. Пользователь не может изменить текст надписи |
LinkLabel
|
Гиперссылка, щелчок на которой приводит к открытию Web-страницы или к другим действиям |
ListBox | Список. Пользователю предоставляется возможность выбрать одно из предлагаемых значений |
ListView
|
Список, содержащий в себе элементы и соответствующие им пиктограммы. Такие списки широко используются в среде Windows, и вы наверняка часто с ними сталкивались |
MainMenu | Главное меню. Отображается в виде строки в верхней части окна программы |
Picture Box
|
Рисунок. Используется для отображения графики в окне формы
|
ProgressBar | Индикатор выполнения. Отображает сообщения о выполняемой операции |
RadioButton
|
Переключатель. Из группы переключателей может быть выбран только один переключатель |
RichTextBox | Окно с плотным текстом. Отображает форматированный текст и позволяет пользователю набирать новый текст, который в дальнейшем может быть использован программой. Форматирование может включать полужирное начертание, курсив, маркеры абзаца и гиперссылки |
Splitter
|
Разделитель. Позволяет пользователям изменять в окне формы размеры элементов управления |
StatusBar | Строка состояния, располагающаяся в нижней части окна формы. Отображает информацию и сообщения для пользователя |
TabControl
|
Элемент управления, содержащий набор вкладок. Пользователь может переходить от одной вкладки к другой, щелкая на их корешках |
TextBox | Текстовое поле. Отображает текст и позволяет пользователю набрать свой текст, который в дальнейшем будет использован программой. Текстовые поля могут состоять из нескольких строк |
ToolBar
|
Панель инструментов, на которой размещаются командные кнопки. Щелкая на кнопках, пользователь может инициировать те или иные действия |
TreeView | Дерево, представляющее информацию в иерархическом виде, как, например, дерево папок в окне Windows Explorer |
Вверх
Настройка формы
Основная работа, которая касается определения параметров новой формы, состоит в добавлении к ней элементов управления. Осуществляется это следующим образом.
Кроме того, вы можете определить свойства самой формы:
Вверх
Создавая программу с использованием инструментов WinForms, вы должны определить,
Обрабатывать события можно двумя способами: либо использовать для этого классы, полученные
Как видите, процесс обработки событий тесно связан с объектно-ориентированным
Вверх
Имена всех функций-членов, предназначенных для обработки событий, начинаются с
Предположим, например, что вы хотите, чтобы при перемещении пользователем курсора мыши в
Вы, наверное, спросите: "Что это еще за MouseEventArgs?" Дело в том. что каждая
После того как функция OnMouseMove объявлена, она должна быть определена. Чтобы
Вверх
Объявление и определение обрабатывающей событие функции
Каждому событию соответствует делегирующий класс, который определяет, как должна
Аргумент sender является объектом, который генерирует событие. В нашем примере это
Совет:
//Изменение отображаемого рисунка
Добавление делегата
Просто создать процедуру обработки события недостаточно. Нужно еще сообщить компилятору, когда эта процедура должна выполняться. Нужно связать событие C l i c k с только
Этот принцип распространяется и на все другие события. Например, чтобы обработать событие ChangeUICues (смысл которого в том, что пользователь нажимает клавишу <ТаЬ> или щелкает кнопкой мыши на элементе управления, делая его таким образом активным), вам нужно просмотреть справочную информацию об этом событии. Из нее вы узнаете, что данному событию соответствует делегирующий класс UlCuesEventHandler, которому нужна обрабатывающая событие функция-член с такой сигнатурой:
Добавление делегата для этого события будет выглядеть следующим образом:
Назад |
Начало урока |
Вверх |
Вперед
Формы
Сейчас, наверное, перспектива создания программ с использованием инструментов WinForms
кажется вам весьма сомнительной. Если вы уже пытались создавать программы для Windows и использовали для этого такие приложения, как, например, MFC, вы можете подумать, что при использовании классов WiiiForms вам придется столкнуться с теми же проблемами. Не переживайте, это не так. Компания Microsoft учла свой предыдущий опыт, и ее новое творение — среда .NET — объектно-ориентированна и отличается особой простотой в использовании.
Чтобы создать форму, нужно выполнить три основных шага.
Наследование форм
Все формы, которые используются в вашей программе, создаются путем наследования
класса WiiiForms, который так и называется — Form. В процессе наследования определяется, как новая форма будет выглядеть и как она будет работать. Производный класс от класса
Form создается очень просто.
__gc class MyForm : public Form
{
управления памятью, выделяемой для объектов создаваемого класса.
Для нового класса объявите конструктор, с помощью которого впоследствии будут определены
все характеристики создаваемой формы.
Совет:
Button *роОК = new Button();
RichTextBox *poTE = new RichTextBox();
PictureBox *polmg = new PictureBox();
//Определение свойств кнопки
poOK->Text = "OK";
poOK->Left - 280;
роОК->Тор = 350;
poOK->BackColor = Color::Blue;
this->Controls->Add(poOK);
this->Contro!s->Add(poTE);
this->Controls->Add(polmg);
членов, к числу которых относится, например, конструктор. Здесь этот указатель
используется, чтобы с помощью возможности редактора Visual C++ выделять цве-
том отдельные синтаксические элементы, тем самым обозначив, что набираемые
коды относятся ко всей форме, а не только к одному из ее элементов управления.
//Определение размеров формы
this->Width = 600;
this->Keight = 400;
Открытие формы
После того как вы создадите форму и определите ее характеристики, вам еще нужно будет
сообщить компилятору, что эта форма должна быть главной формой вашей программы. Для
этого используется класс System.Windows.Forms.Application. Метод Run этого класса принимает в качестве аргумента указатель созданной формы и делает ее главной для вашей программы. Обычно метод Run вызывается функцией main.
#ifdef _UNICODE
int wmain(void)
#else
int main(void)
#endif
{
return 0;
Обработка событий
Создание любого графического пользовательского интерфейса подразумевает разработку
программ, обрабатывающих события. Осуществляется это посредством объектно-
ориентированного программирования. Сами события в Windows и в среде .NET происходят
постоянно и в основном являются следствием действий пользователя. Например, перемещение
окна, щелчок на кнопке, выбор пункта меню — все это воспринимается как событие.
на какие события должна реагировать программа. Обрабатывать все события подряд не имеет
никакого смысла. В действительности в процессе работы программы могут происходить тысячи
событий, поэтому, если бы все их нужно было обрабатывать, только на написание программ
уходили бы годы, не говоря уже о процессе отладки и об устранении ошибок.
путем наследования, либо делегировать управление событием другому классу. Например,
функции-члены производного класса, представляющего форму, могут непосредственно
обрабатывать события, касающиеся самой формы. Но допустим, что в окне этой формы есть
кнопка, на которой должен щелкнуть пользователь. Вам, наверное, не хотелось бы
создавать еще один отдельный класс, представляющий кнопку, только для того, чтобы
определить, что должно произойти после щелчка на ней. Поэтому среда .NET включает в себя
концепцию делегирования, которая позволяет событие, относящееся, например, к кнопке,
обрабатывать функцией-членом формы, на которой эта кнопка расположена.
программированием. Создавая путем наследования класс, представляющий форму, вы добавляете к
нему функции-члены, делающие эту форму рабочей, включая делегированные, которые
делают рабочими элементы управления, расположенные на этой форме.
Объекты, которые умеют реагировать
Представляющие формы и элементы управления классы имеют множество встроенных
функций-членов, предназначенных для обработки событий. Таким образом значительно упрощается
процесс создания собственных программ, обрабатывающих события. Еше один плюс состоит в том,
что, если вам необходимо как-то изменить поведение производного класса, просто
воспользуйтесь возможностью перегрузки и измените нужные вам функции-члены.
букв On. Например, функция-член, предназначенная для обработки события MouseMove
(перемещение курсора мыши), называется OnMouseMove. Список названий всех функций-членов,
обрабатывающих события, вы можете найти в справочной системе Visual C++ .NET в
разделе Protected Instance Methods. Поскольку все эти функции являются защищенными
(protected), они могут быть перегружены и вызваны только из производных классов.
окне созданной вами формы для курсора постоянно отображалось текущее значение координаты X.
Чтобы сделать это, вам нужно перегрузить функцию-член OnMouseMove, но для этого вы должны
знать ее сигнатуру. (Сигнатура функции определяет тип возвращаемого ею результата, а также
количество и тип передаваемых ей аргументов. Дополнительную информацию о сигнатуре функций
вы найдете в главе 18.) Вы можете найти описание функции OnMouseMove в справочной системе
Visual C++ или просто воспользоваться возможностью IntelliSense редактора Visual C++.
(Попробуйте набрать On и, удерживая клавишу
случае вы увидите, что функция OnMouseMove должна быть объявлена таким образом:
void OnMouseMove(MouseEventArgs *е);
функция, обрабатывающая событие, должна иметь какую-то информацию о самом событии.
Так, например, функция OnMouseMove вызывается каждый раз, когда пользователь перемещает
курсор мыши, но она также должна знать, куда курсор перемещается. Именно для этого
и существует аргумент MouseEventArgs, у которого есть свойства, позволяющие определить
текущие координаты X и Y курсора мыши. Для других событий предусмотрены другие
аргументы.
ссылающийся на объект производного класса, полученного путем наследования
класса EventArgs (или же на объект самого класса EventArgs). Существует
почти сотня классов, производных от класса EventArgs.
отображать значение координаты X курсора мыши, добавьте к классу в качестве члена данных
элемент управления Label (Надпись) и свойству Text этого объекта присвойте значение
свойства X объекта MouseEventArgs:
void MyForm::OnMouseMove(MouseEventArgs *e)
{
m_poXPosition->Text = e->x.ToString() ;
координаты X обновляется каждый раз, когда курсор перемещается над пустыми
участками формы. Дело в том, что при размещении курсора над любым элементом управления,
событие MouseMove будет относиться уже к этому элементу и
сама форма не будет реагировать на перемещение курсора.
Хорошие менеджеры умеют делегировать свои обязанности
Создание программ, обрабатывающих события, было бы весьма утомительным, если бы
для каждого события нужно было создавать новый производный класс и перегружать функции-члены. Среда .NET упрощает эту задачу, позволяя делегировать другим классам возможность реагировать на то или иное событие. Делегирование можно использовать в отношении как форм, так и элементов управления. Так, вам не нужно создавать новые классы для каждого отдельного элемента управления. Если программа должна как-то отреагировать на событие, совершенное пользователем в отношении какого-то элемента управления (например,
пользователь щелкнул на кнопке Выход), делегируйте эту обязанность классу, представляющему форму, где эта кнопка расположена. Функции-члены, которые обрабатывают делегированные события, называются делегатами (delegate).
Чтобы добавить к какому-то классу делегированную функцию, нужно выполнить два основных шага.
выглядеть обрабатывающая это событие функция-член. Событию Click, например, соответствует делегирующий класс EventHendier, функция-член которого требует для себя значения двух аргументов:
void Change Clicked(Object *sender, EventArgs *e);
будет кнопка, на которой щелкнул пользователь. Аргумент EventArgs содержит в себе информацию о событии. В данном случае все, что вам нужно знать, — на какой кнопке щелкнул пользователь, поэтому здесь используется стандартный объект класса EventArgs, который не несет в себе никакой дополнительной информации.
Из определения функции Change_Clicked видно, что после щелчка на кнопке Change
изменяется рисунок, отображаемый объектом PictureBox:
void MyForm::Change_Clicked(Object ^sender, EventArgs *e)
ra_polmg->lmage = Image::FromFile("..\\ Wdesert5.jpg");
что созданным делегатом.
Процесс добавления делегата включает в себя четыре основных элемента:
В нашем примере элементом управления является кнопка Change, представляемая членом данных poChange. Обрабатываемое событие - Click(щелчок кнопкой мыши), которому соответствует делегирующий класс EventHandler. Функцию-член мы назвали именем
Change Clicked. Итак, чтобы добавить этого делегата, наберите такой код:
poChange->Click += new EventHandler(this, Change_Clicked);
void Change__UICues (Object *sender, UICuesEventArgs *e) ;
poChange->ChangeUICues += new UICuesEventHandier(this,
Change_UICues);
что .NET позволяет создавать для одного события множество процедур, которые
это событие обрабатывают. Если вы используете просто оператор присвоения (=),
одна процедура заменит собой все другие. Использование оператора += позволяет
добавлять новые процедуры к уже существующим.
Содержание