Выбери формат для чтения
Загружаем конспект в формате docx
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Оглавление
Введение в программирование под Windows 2
Событийно-управляемое программирование 2
Шаблон Windows-приложения 4
Класс Control 16
Элементы управления 19
Метка Label 19
Кнопка Button 20
Поле ввода TextBox 21
Меню MainMenu и ContextMenu 23
Флажок CheckBox 24
Переключатель RadioButton 25
Список ListBox 25
Предварительные замечания о формах 28
Класс Form 30
Диалоговые окна 33
Класс Application 37
Введение в программирование под Windows
В предыдущих главах мы изучали возможности языка C# на примере консольных приложений, чтобы не распылять свое внимание на изучение классов библиотеки .NET, поддерживающих Стандартный графический интерфейс пользователя. Сейчас пришло время освоить принципы создания Windows-приложений и получить представление об основных классах библиотеки, которые при этом используются.
В первую очередь рассмотрим основные особенности Windows как характерного и широко распространенного представителя современных операционных систем.
□ Многозадачность — это возможность одновременно выполнять несколько приложений. Операционная система обеспечивает разделение ресурсов: каждому приложению выделяется свое адресное пространство, распределяется процессорное время и организуются очереди для доступа к внешним устройствам. Внутри приложения также можно организовать параллельное выполнение нескольких фрагментов, называемых потоками. В разных версиях Windows используются различные механизмы диспетчеризации.
□ Независимость программ от аппаратуры. Для управления аппаратными средствами любое приложение обращается к операционной системе, что обеспечивает независимость от конкретных физических характеристик устройств: при смене устройства никакие изменения в программу вносить не требуется. Управление внешними устройствами обеспечивается с помощью драйверов.
□ Стандартный графический интерфейс с пользователем. Основное взаимодействие с пользователем осуществляется в графическом режиме. Каждое приложение выполняет вывод в отведенную ему прямоугольную область экрана, называемую окном. Окно состоит из стандартных элементов. Это упрощает освоение программ пользователем и облегчает работу программиста, поскольку в его распоряжение предоставляются библиотеки интерфейсных компонентов. Такие библиотеки входят в состав систем программирования.
Событийно-управляемое программирование
Рис. 14.1. Структура программы, управляемой событиями
Событие воспринимается Windows и преобразуется в сообщение — запись, содержащую необходимую информацию о событии (например, какая клавиша была нажата, в каком месте экрана произошел щелчок мышью). Сообщения могут поступать не только от пользователя, но и от самой системы, а также от активного или других приложений. Определен достаточно широкий круг стандартных сообщений, образующий иерархию, кроме того, можно определять собственные сообщения.
Сообщения поступают в общую очередь, откуда распределяются по очередям приложений. Каждое приложение содержит цикл обработки сообщений, который выбирает сообщение из очереди и через операционную систему вызывает подпрограмму, предназначенную для его обработки (рис. 14.2). Таким образом, Windows-приложение состоит из главной программы, содержащей цикл обработки сообщений, инициализацию и завершение приложения, и набора обработчиков событий.
Рис. 14.2. Структура Windows-приложения
Среда Visual Studio.NET содержит удобные средства разработки Windows-приложений, выполняющие вместо программиста рутинную работу — создание шаблонов приложения и форм, заготовок обработчиков событий, организацию цикла обработки сообщений и т. д. Рассмотрим эти средства.
Шаблон Windows-приложения
Создадим новый проект (Файл ► Создать ► Проект), выбрав шаблон Приложение Windows Forms (рис. 14.3). После более длительных раздумий, чем для консольного приложения, среда сформирует шаблон Windows-приложения. Первое отличие, которое бросается в глаза, — вкладка заготовки формы Form1.cs[Конструктор], расположенная в основной части экрана. Форма представляет собой окно и предназначена для размещения компонентов (элементов управления) — меню, текста, кнопок, списков, изображений и т. д.
Рис. 14.3. Выбор шаблона проекта
Среда создает не только заготовку формы, но и шаблон текста приложения. Перейти к нему можно, щелкнув в окне Обозреватель решений (Вид ► Обозреватель решений) правой кнопкой мыши на файле Forml.cs и выбрав в контекстном меню команду Перейти к коду (F7). При этом откроется вкладка с кодом формы, который, предназначен для редактирования программистом, приведен в листинге 14.1. Вторая часть кода, приведённая в листинге 14.1, предназначена для редактирования визуальной средой. Для доступа к ней в обозревателе решений надо раскрыть пиктограмму Forml.cs и выбрать файл Forml.Designer.cs. Третья часть кода, приведённая в листинге 14.1, доступна через обозреватель решений, она хранится в файле Program.cs. Представлять себе, что написано в вашей программе, весьма полезно, поэтому давайте внимательно рассмотрим этот текст.
Листинг 14.1. Шаблон Windows-приложения
Первая часть кода, которую может редактировать программист.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
}
Вторая часть кода, редактируемая визуальной средой программирования.
namespace WindowsFormsApplication1
{
partial class Form1
{
///
/// Требуется переменная конструктора.
///
private System.ComponentModel.IContainer components = null;
///
/// Освободить все используемые ресурсы.
///
/// истинно, если управляемый ресурс должен быть удален; иначе ложно.
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором форм Windows
///
/// Обязательный метод для поддержки конструктора - не изменяйте
/// содержимое данного метода при помощи редактора кода.
///
private void InitializeComponent()
{
this.SuspendLayout();
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(278, 244);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
}
}
Третья часть кода – файл Program.cs.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
static class Program
{
///
/// Главная точка входа для приложения.
///
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Приложение начинается с директив использования пространств имен библиотеки .NET. Для пустой формы, не содержащей ни одного компонента, необходимыми являются только две директивы:
using System;
using System.Windows.Forms;
Остальные директивы добавлены средой «на вырост». С пространством имен System вы уже знакомы. Пространство System.Windows.Forms содержит огромное количество типов, являющихся строительными блоками Windows-приложений.
Список наиболее употребительных элементов этого пространства имен приведен
в табл. 14.1, а часть иерархии — на рис. 14.4.
Таблица 14.1. Основные типы Windows.Forms
Класс
Назначение
Application
Класс Windows-приложения. При помощи методов этого класса можно обрабатывать . Windows-сообщения, запускать и прекращать работу приложения и т. п.
ButtonBase, Button, CheckBox, ComboBox,
DataGrid, GroupBox, ListBox, LinkLabel,
PictureBox
Form
Примеры классов, представляющих элементы
управления (компоненты): базовый класс кнопок,
кнопка, флажок, комбинированный список,
таблица, группа, список, метка с гиперссылкой,
изображение
Класс формы — окно Windows-приложения
ColorDialog, Fi1eDia1og, FontDialog
Примеры стандартных диалоговых окон для выбора цветов, файлов, шрифтов,
PrintPreviewDialog
окно предварительного просмотра
Menu, MainMenu, Menultem, ContextMenu
Классы выпадающих и контекстных меню
Clipboard, Helр, Timer, Screen, ToolTip, Cursors
Вспомогательные типы для организации графических интерфейсов: буфер обмена, помощь, таймер, экран, подсказка, указатели мыши
StatusBar, Splitter, ToolBar, Scrol1Bar
Примеры дополнительных элементов управления, размещаемых на форме: строка состояния, разделитель, панель инструментов и т. д.
Мы будем изучать типы пространства имен Windows.Forms по мере необходимости. Продолжим рассмотрение листинга 14.1. В нем описан класс Forml, производный от класса Form. Он наследует от своего предка множество элементов, которые мы рассмотрим в следующих разделах. В самом классе Forml описано новое закрытое поле components — контейнер для хранения компонентов, которые можно добавить в класс формы.
Конструктор формы вызывает закрытый метод InitializeComponent, автоматически формируемый средой (код метода скрыт между директивами препроцессора #region и #endregion). Этот метод обновляется средой при добавлении элементов управления на форму, а также при изменении свойств формы и содержащихся на ней элементов. Например, если изменить цвет фона формы с помощью окна свойств (Properties), в методе появится примерно такая строка:
this.BackColor = System.Drawing. SystemColors.AppWorkspace;
Метод освобождения ресурсов Dispose вызывается автоматически при закрытии
формы. Точка входа в приложение, метод Main, содержит вызов статического метода Run класса Application. Метод Run запускает цикл обработки сообщений и выводит на экран форму, новый экземпляр которой передан ему в качестве параметра.
Рис. 14.4. Элементы управления Windows.Forms
ПРИМЕЧАНИЕ
Запуск приложения, для создания которого мы пока не написали ни строчки кода, можно выполнить с помощью команды меню Отладка ► Начать отладкуt или клавиши F5. На экран выводится пустая форма, обладающая стандартной функциональностью окна Windows-приложения: например, она умеет изменять свои размеры и реагировать на действия с кнопками развертывания и закрытия. Процесс создания Windows-приложения состоит из двух основных этапов:
1. Визуальное проектирование, то есть задание внешнего облика приложения.
2. Определение поведения приложения путем написания процедур обработки событий.
Визуальное проектирование заключается в помещении на форму компонентов (элементов управления) и задании их свойств и свойств самой формы с помощью окна свойств. Если его не видно, можно воспользоваться командой Вид ► Окно свойств. Свойства отображаются либо в алфавитном порядке, либо сгруппированными по категориям. Способ отображения выбирается с помощью кнопок, расположенных в верхней части окна свойств (рис. 14.5).
Рис. 14.5. Окно свойств
Самый простой способ размещения компонента — двойной щелчок на соответствующем значке палитры компонентов Панель элементов (если ее не видно, можно воспользоваться командой меню Вид ► Панель элементов), при этом компонент помещается на форму. Затем компонент можно переместить и изменить его размеры с помощью мыши. Можно также сделать один щелчок на палитре и еще один щелчок в том месте формы, где планируется разместить компонент. В окне свойств отображаются свойства выбранного в данный момент компонента (он окружен рамкой).
Задание свойств выполняется либо выбором имеющихся в списке вариантов, либо вводом требуемого значения с клавиатуры. Если около имени свойства стоит значок +, это означает, что свойство содержит другие свойства. Они становятся доступными после щелчка на значке. Пример формы, на которой размещены компоненты с вкладки палитры Все формы Windows Forms, показан на рис. 14.6. Эти компоненты описаны в разделе «Элементы управления».
Определение поведения программы начинается с принятия решений, какие действия должны выполняться при щелчке на кнопках, вводе текста, выборе пунктов меню и т. д., иными словами, по каким событиям будут выполняться действия, реализующие функциональность программы.
ВНИМАНИЕ
Интерфейс программы должен быть интуитивно понятным и по возможности простым. Часто повторяющиеся действия не должны требовать от пользователя выполнения сложных последовательностей операций.
Заготовка шаблона обработчика события формируется двойным щелчком на поле, расположённом справа от имени соответствующего события на вкладке Events окна свойств, при этом появляется вкладка окна редактора кода с заготовкой соответствующего обработчика (вкладка Events отображается в окне свойств при щелчке на кнопке с желтой молнией, как показано на рис. 14.5). Для каждого класса определен свой набор событий, на которые он может реагировать. Наиболее часто используемые события:
□ Activated — получение формой фокуса ввода;
□ Click, Doubleclick — одинарный и двойной щелчки мышью;
□ Closed — закрытие формы;
□ Load — загрузка формы;
□ KeyDown, KeyUp — нажатие и отпускание любой клавиши и их сочетаний;
□ KeyPress — нажатие клавиши, имеющей ASCII-код;
□ MouseDown, MouseUp — нажатие и отпускание кнопки мыши;
□ MouseMove — перемещение мыши;
□ Paint — возникает при необходимости прорисовки формы.
В листинге 14.2 приведен текст программы, сформированной средой после размещения на форме компонентов, представленных на рис. 14.6, и выбора для кнопки события Click, а для поля ввода — события KeyPress. Из листинга для удобства восприятия удалены лишние элементы.
Листинг 14.2. Шаблон приложения с двумя компонентами и заготовками
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// 11
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
// 12
}
}
}
namespace WindowsFormsApplication1
{
partial class Form1 //0
{
///
/// Требуется переменная конструктора.
///
private System.ComponentModel.IContainer components = null;
///
/// Освободить все используемые ресурсы.
///
/// истинно, если управляемый ресурс должен быть удален; иначе ложно.
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором форм Windows
///
/// Обязательный метод для поддержки конструктора - не изменяйте
/// содержимое данного метода при помощи редактора кода.
///
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button(); // 3
this.textBox1 = new System.Windows.Forms.TextBox(); // 4
this.SuspendLayout(); // 5
//
// button1
//
this.button1.Location = new System.Drawing.Point(84, 149);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(101, 36);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click); // 6
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(69, 55);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(129, 26);
this.textBox1.TabIndex = 1;
this.textBox1.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.textBox1_KeyPress); // 7
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(278, 244);
this.Controls.Add(this.textBox1); // 8
this.Controls.Add(this.button1); // 9
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false); // 10
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button button1; // 1
private System.Windows.Forms.TextBox textBox1; // 2
}
}
Рассмотрим текст программы. В операторах 1 и 2 в класс формы добавляются два закрытых поля: строка ввода типа TextBox и кнопка типа Button. Эти типы определены в пространства имен System.Windows.Forms, которое подключается в соответствующей директиве using, поэтому можно записать эти и соседние строки проще:
public class Forml : Form
{
private TextBox textBoxl;
//
//
private Button buttonl;
//
private Container components = null;
Чаще всего программист изменяет имена, присваиваемые элементам средой, более осмысленными. Это можно сделать, задав новое значение свойства Name элемента.
Самое важное происходит в методе InitializeComponent. В операторах 3 и 4 создаются экземпляры компонентов, затем для каждого из них задаются свойства, определяющие их положение, размер, вид и т. д. Обратите внимание на операторы 6 и 7. В них регистрируются обработчики соответствующих событий. Механизм обработки событий тот же, что мы рассматривали в главе 10 (см. с. 232) — он описывается моделью «публикация — подписка».
Например, для кнопки buttonl, в составе которой есть событие Click, регистрируется обработчик buttonl_Click, являющийся закрытым методом класса Forml. Это значит, что при наступлении события нажатия на кнопку (об этом сообщит операционная система) будет вызван соответствующий обработчик.
Имя обработчика формируется средой автоматически из имени экземпляра компонента и имени события. Обратите внимание на то, что обработчикам передаются два параметра: объект-источник события и запись, соответствующая типу события.
ПРИМЕЧАНИЕ
При задании обработчика можно задать и другое имя, для этого оно записывается справа от имени соответствующего события на вкладке События окна свойств.
После создания экземпляров компонентов и настройки их свойств компоненты заносятся в коллекцию, доступ к которой выполняется через свойство Controls (операторы 8 и 9). Если этого не сделать, компоненты не будут отображаться на форме. Коллекция поддерживает методы добавления и удаления компонентов (Add и Remove).
Таким образом, для размещения компонента на форме необходимо выполнить три действия:
1. Создать экземпляр соответствующего класса.
2. Настроить свойства экземпляра, в том числе зарегистрировать обработчик событий.
3. Поместить экземпляр в коллекцию компонентов формы.
Операторы 5 и 10 используются для того, чтобы все изменения в свойства элементов вносились одновременно. Для этого в операторе 5 внесение изменений «замораживается», а в операторе 10 разрешается.
В теле обработчиков событий (операторы 11 и 12) программист может наконец-то самостоятельно написать код, который будет выполняться при наступлении события. Добавим в эти строки операторы, выводящие окна сообщений с соответствующим текстом:
MessageBox.Show("Нажата кнопка buttonl"); ,// 11
MessageBox.Show("Нажата клавиша " + e.KeyChar); //12
И установим в свойство KeyPreView значение true. Здесь используется простейший вариант статического метода Show класса MessageBox, определенного в пространстве имен System.Windows Torms.
Существуют более десяти перегруженных вариантов этого метода, позволяющих варьировать вид выводимой информации, например, задать заголовок окна и наименования отображаемых на нем кнопок.
Прежде чем приступить к изучению форм и элементов управления, размещаемых на формах, необходимо рассмотреть их общего предка — класс Control.
Класс Control
Класс Control является базовым для всех отображаемых элементов, то есть элементов, которые составляют графический интерфейс пользователя, например кнопок, списков, полей ввода и форм. Класс Control реализует базовую функциональность интерфейсных элементов. Он содержит методы обработки ввода пользователя с помощью мыши и клавиатуры, определяет размер, положение, цвет фона и другие характеристики элемента. Для каждого объекта можно определить родительский класс, задав свойство Parent, при этом объект будет иметь, например, такой же цвет фона, как и его родитель1.
Наиболее важные свойства класса Control перечислены в табл. 14.2, методы — в табл. 14.3.
Таблица 14.2. Основные свойства класса Control
Свойство
Описание
Anchor
Определяет, какие края элемента управления будут привязаны к краям родительского контейнера. Если задать привязку всех краев, элемент будет изменять размеры вместе с родительским
BackColor
Определяют параметры отображения рабочей области формы
Backgroundlmage, Font, ForeColor, Cursor
цвет фона, фоновый рисунок, шрифт, цвет текста, вид указателя мыши
Bottom, Right
Координаты нижнего правого угла элемента. Могут - устанавливаться также через свойство Size
Top, Left
Координаты верхнего левого угла элемента. Эквивалентны свойству Location
Bounds
Возвращает объект типа Rectangle (прямоугольник), который
определяет размеры элемента управления
ClientRectangle
Возвращает объект Rectangle, определяющий размеры рабочей области элемента
ContextMenu
Определяет, какое контекстное меню будет выводиться при щелчке на элементе правой кнопкой мыши
Dock
Определяет, у какого края родительского контейнера будет отображаться элемент управления
Location
Координаты верхнего левого угла элемента относительно верхнего левого угла контейнера, содержащего этот элемент, в виде структуры типа Point. Структура содержит свойства X и У
Height, Width
Высота и ширина элемента
Size
Высота и ширина элемента в виде структуры типа Size. Структура содержит свойства Weight и Width
Таблица 14.2 (продолжение)
Свойство
Описание
Created, Disposed, Enabled, Focused, Visible
Возвращают значения типа bool, определяющие текущее состояние элемента: создан, удален, использование разрешено, имеет фокус ввода, видимый
Handle
Возвращает дескриптор элемента (уникальное целочисленное значение, сопоставленное элементу)
ModifierKeys
Статическое свойство, используемое для проверки состояния модифицирующих клавиш (Shift, Control, Alt). Возвращает результат в виде объекта типа Keys
MouseButtons
Статическое свойство, проверяющее состояние клавиш мыши. Возвращает результат в виде объекта типа MouseButtons
Opacity
Определяет степень прозрачности элемента управления. Может изменяться от 0 (прозрачный) до 1 (непрозрачный)
Parent
Возвращает объект, родительский по отношению к данному (имеется в виду не базовый класс, а объект-владелец)
Region
Определяет объект Region, при помощи которого можно управлять очертаниями и границами элемента управления
Tablndex, TabStop
Используются для настройки последовательности перемещения с помощью клавиши Tab по элементам управления, расположенным на форме
Таблица 14.3. Основные методы класса Control
Метод
Описание
Focus
Установка фокуса ввода на элемент2
GetStyle, SetStyle
Получение и установка флагов управления стилем элемента. Используются значения перечисления Control Styles (см. далее)
Hide, Show
Управление свойством Visible (Hide — скрыть элемент, Show — отобразить элемент)
Invalidate
Обновление изображения элемента путем отправки соответствующего сообщения в очередь сообщений. Метод перегружен таким образом, чтобы можно было обновлять не всю область, занимаемую элементом, а лишь ее часть
OnXXXX
Методы-обработчики событий (OnMouseMove, OnKeyDown, OnResize, OnPaint и т. п.), которые могут быть замещены в производных классах
Refresh
Обновление элемента и всех его дочерних элементов
SetBounds, SetLocation, SetClientArea
Управление размером и положением элемента
Перечисление Control Styles задает возможные значения стиля формы в виде битовых флагов, поэтому можно использовать их комбинации. Значения всех констант перечисления можно посмотреть в электронной документации, а для первого знакомства достаточно одного — ResizeRedraw. Этот стиль определяет, что при изменении размеров формы она будет автоматически перерисована. По умолчанию перерисовка не выполняется, и если на форме есть какое-либо изображение, результат изменения размеров формы может сильно озадачить.
В табл. 14.4 перечислена небольшая часть событий, определенных в классе Control.
Таблица 14.4. Некоторые события класса Control
Событие
Описание
Click, Doubleclick, MouseEnter, MouseLeave, MouseDown, MouseUp, MouseMove, MouseWheel
События от мыши
KeyPress, Keyllp, KeyDown
События от клавиатуры
BackColorChanged, ContextMenuChanged, FontChanged, Move, Paint, Resize
События изменения элемента
GotFocus, Leave, LostFocus
События получения и потери фокуса ввода
Применение наиболее важных элементов, описанных в таблицах, рассматривается в следующих разделах.
При написании приложений применяются два способа обработки событий:
□ замещение стандартного обработчика;
□ задание собственного обработчика.
В большинстве случаев применяется второй способ. Среда разработки создает заготовку обработчика по двойному щелчку на поле, расположенном справа от имени соответствующего события на вкладке Events окна свойств. При этом в код приложения автоматически добавляется строка, регистрирующая этот обработчик.
Первый способ, то есть переопределение виртуальных методов ОпХХХХ (OnMouseMove, OnKeyDown, OnResize, OnPaint и т. п.), применяется в основном тогда, когда перед реакцией на событие требуется выполнить какие-либо дополнительные действия.
За подробностями интересующиеся могут обратиться к [27].
Элементы управления
Элементы управления, или компоненты, помещают на форму с помощью панели инструментов (Вид ► Панели инструментов). В этом разделе кратко описаны простейшие компоненты и приведены примеры их использования.
Обычно компоненты применяют в диалоговых окнах для получения данных от пользователя или его информирования.
Метка Label
Метка предназначена для размещения текста на форме. Текст хранится в свойстве Text. Можно задавать шрифт (свойство Font), цвет фона (BackColor), цвет шрифта (ForeColor) и выравнивание (TextAlign) текста метки. Метка может автоматически изменять размер в зависимости от длины текста (AutoSize = True). Можно разместить на метке изображение (Image) и задать прозрачность (установить для свойства BackColor значение Color .Transparent).
Метка не может получить фокус ввода, следовательно, не обрабатывает сообщения от клавиатуры. Пример использования меток приведен далее (см. с. 327).
Кнопка Button
Основное событие, обрабатываемое кнопкой, — щелчок мышью (Click). Кроме того, кнопка может реагировать на множество других событий — нажатие клавиш на клавиатуре и мыши, изменение параметров и т. д. Нажатие клавиши Enter или пробела, если при этом кнопка имеет фокус ввода, эквивалентно щелчку мышью на кнопке.
Можно изменить начертание и размер шрифта текста кнопки, который хранится
в свойстве Text, задать цвет фона и фоновое изображение так же, как и для метки.
Если занести имя кнопки в свойство AcceptButton формы, на которой расположена кнопка, то нажатие клавиши Enter вызывает событие Click, даже если кнопка не имеет фокуса ввода. Такая кнопка имеет дополнительную рамку и называется кнопкой по умолчанию.
Аналогично, если занести имя кнопки в свойство Cancel Button формы, на которой расположена кнопка, то нажатие клавиши Esc вызывает событие Click для этой кнопки.
Кнопки часто используются в диалоговых окнах. Как видно из названия, такое окно предназначено для диалога с пользователем и запрашивает у него какие-либо сведения (например, какой выбрать режим или какой файл открыть). Диалоговое окно обладает свойством модальности. Это означает, что дальнейшие действия с приложением невозможны до того момента, пока это окно не будет закрыто. Закрыть окно можно, либо подтвердив введенную в него информацию щелчком на кнопке ОК (или Yes), либо отменив ее с помощью кнопки закрытия окна или, например, кнопки Cancel.
Таблица 14.5. Значения перечисления DialogResult
Значение
Описание
None
Окно не закрывается
Ignore
Нажата кнопка Ignore
ОК
Нажата кнопка ОК
Yes
Нажата кнопка Yes
Cancel
Нажата кнопка Cancel
No
Нажата кнопка No
Abort
Нажата кнопка Abort
Retry
Нажата кнопка Retry
Для сохранения информации о том, как было закрыто окно, у кнопки определяют свойство DialogResult. Это свойство может принимать стандартные значения из перечисления DialogResult, определенного в пространстве имен System.Windows.Forms.
Значения перечисления приведены в табл. 14.5.
Пример использования кнопок приведен в следующем разделе.
Поле ввода TextBox
Компонент TextBox позволяет пользователю вводить и редактировать текст, который запоминается в свойстве Text. Можно вводить строки практически неограниченной длины (приблизительно до 32 000 символов), корректировать их, а также вводить защищенный текст (пароль) путем установки маски, отображаемой вместо вводимых символов (свойство PasswordChar). Для обеспечения возможности ввода нескольких строк устанавливают свойства Multiline, Scroll Bars и Wordwrap.
Доступ только для чтения устанавливается с помощью свойства Readonly. Элемент содержит методы очистки (Clear), выделения (Select), копирования в буфер (Сору), вставки из него (Paste) и др., а также реагирует на множество событий, основными из которых являются KeyPress и KeyDown.
Рассмотрим создание простого приложения, в котором использованы компоненты типа Label, Button и TextBox. Главное окно приложения показано на рис. 14.7.
Рис. 14.7. Окно приложения «Диагностика кармы»
Пользователь вводит число и нажимает клавишу Enter, после чего введенное значение сравнивается с числом, «задуманным» генератором случайных чисел. Если пользователь не угадал, выводится сообщение «Не угадали!». Каждое следующее сообщение для наглядности немного сдвигается вправо относительно предыдущего. После совпадения выводится итоговое сообщение, и фокус ввода передается на кнопку Еще раз (рис. 14.8). «Коэффициент невезучести» определяется как количество попыток, деленное на максимально возможное значение числа.
Создание приложения начинается с проектирования его интерфейса. На форме располагаются метки, поля ввода и кнопка. В окне свойств их свойству Text задаются перечисленные в табл. 14.6 значения (в окне отображаются свойства выделенного элемента; элемент выделяется щелчком мыши).
Рис. 14.8. Окно приложения после ввода правильного ответа
Таблица 14.6. Значение свойства Text для компонентов приложения
Компонент
Значение свойства Text
Form1
Диагностика кармы
label1
Введите число
label2, label3, textBox1
Пустое значение
button1
Еще раз
Поведение приложения задается в обработчиках событий. Число надо загадывать до того, как пользователь введет первый ответ, а затем после каждого щелчка на кнопке Еще раз. Следовательно, эти действия должны выполняться при загрузке формы - (событие Load) и щелчке на кнопке (событие Click). Ответ пользователя анализируется при нажатии клавиши Enter после ввода числа (событие KeyPress элемента textBoxl).
Вызов редактора программ выполняется двойным щелчком рядом с соответствующим событием элемента на вкладке Events окна свойств (см. рис. 14.5). Для ранения загаданного числа и ответа пользователя применяются поля i и k. В константе шах хранится максимально возможное число. Переменная rnd представляет собой экземпляр генератора случайных чисел.
Сокращенный текст программы с комментариями приведен в листинге 14.3.
Листинг 14.3. Программа «Угадай число»
private void Form1_Load(object sender, EventArgs e)
{
rnd = new Random();
i = rnd.Next(max); // загадано число в диапазоне от 0 до max
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
int n;
if ( e.KeyChar != (char)13 )return; // если нажата не клавиша Enter, выйти
try // преобразование ввода пользователя в число
{
n = Convert.ToInt32(textBox1.Text);
}
catch
{
n = -1; // если введено не число, принять за неверный ответ
}
if ( n != i ) // ===—===== пользователь не угадал
{
label2.Left += 5;
label2.Text = "He угадали!";
textBox1.Clear();
k++; // увеличение счетчика попыток
button1.Visible = false;
}
else // ============== пользователь угадал
{
label2.Left = 32; // восстановить начальное положение метки
label2.Text = "Коэффициент невезучести";
double koef = 1.0 * k / max;
label3.Text = koef.ToString();
button1.Visible = true;
}
}
private void button1_Click(object sender, EventArgs e)
{
i = rnd.Next(max);
k = 0;
textBox1.Clear();
textBox1.Focus();
label2.Text = "";
label3.Text = "";
// загадано число в диапазоне от 0 до max
// обнуление количества попыток ответа
// поле ввода очищено
// курсор установлен на поле ввода
// метки очищены
}
Меню MainMenu и ContextMenu
Главное меню MainMenu размещается на форме таким же образом, как и другие компоненты: двойным щелчком на его значке на панели Toolbox. При этом значок располагается под заготовкой формы, а среда переходит в режим редактирования пунктов меню. Каждый пункт меню представляет собой объект типа Menu Item, и при вводе пункта меню мы задаем его свойство Text. Переход к заданию заголовка следующего пункта меню выполняется либо щелчком мыши, либо нажатием клавиши Enter и клавиш со стрелками. Обычно, чтобы сделать программу понятнее, изменяют также свойства Name каждого пункта так, чтобы они соответствовали названиям пунктов.
Пункт меню может быть запрещен или разрешен (свойство Enabled), видим или невидим (Visible), отмечен или не отмечен (Checked). Заготовка обработчика событий формируется двойным щелчком на пункте меню.
Любое приложение обычно содержит в меню команду Exit, при выборе которой приложение завершается. Для закрытия приложения можно воспользоваться либо методом Close класса главной формы приложения, либо методом Exit класса Application, например:
private void Exit_Click(object sender, EventArgs e)
{ // имя пункта меню - Exit
Close();
// или:
// Application.ExitO;
}
Контекстное меню — это меню, которые вызывается во время выполнения программы по нажатию правой кнопки мыши на форме или элементе управления.
Обычно в этом меню размещаются пункты, дублирующие пункты главного меню, или пункты, определяющие специфические для данного компонента действия.
Контекстное меню ContextMenu создается и используется аналогично главному (значок контекстного меню появляется на панели инструментов, если воспользоваться кнопкой прокрутки). Для привязки контекстного меню к компоненту следует установить значение свойства ContextMenu этого компонента равным имени контекстного меню.
Флажок CheckBox
Флажок используется для включения-выключения пользователем какого-либо режима. Для проверки, установлен ли флажок, анализируют его свойство Checked, принимающее значение true или false. Флажок может иметь и третье состояние — «установлен, но не полностью». Как правило, это происходит в тех случаях, когда устанавливаемый режим определяется несколькими «подрежимами», часть из которых включена, а часть выключена. В этом случае используют свойство CheckState, которое может принимать значения Checked, Unchecked и Intermediate.
Кроме того, флажок обладает свойством ThreeState,-которое управляет возможностью установки третьего состояния пользователем с помощью мыши. Для флажка можно задать цвет фона и фоновое изображение так же, как и для метки. Свойство Appearance управляет отображением флажка: либо в виде собственно флажка (Normal), либо в виде кнопки (Button), которая «залипает» при щелчке на ней мышью.
Флажки используются в диалоговых окнах как поодиночке, так и в группе, причем все флажки устанавливаются независимо друг от друга. Пример приложения с флажками приведен далее в этой главе.
Переключатель RadioButton
Переключатель позволяет пользователю выбрать один из нескольких предложенных вариантов, поэтому переключатели обычно объединяют в группы. Если один из них устанавливается (свойство Checked), остальные автоматически сбрасываются. Программист может менять стиль и цвет текста, связанного с переключателем, и его выравнивание. Для переключателя можно задать цвет фона и фоновое изображение так же, как и для метки.
Переключатели можно поместить непосредственно на форму, в этом случае все они составят одну группу. Если на форме требуется отобразить несколько групп переключателей, их размещают внутри компонента Group или Panel.
Свойство Appearance управляет отображением переключателя: либо в традиционном виде (Normal), либо в виде кнопки (Button), которая «залипает» при щелчке на ней мышью.
Пример использования переключателей приведен далее в этой главе.
Список ListBox
Список служит для представления перечней элементов, в которых пользователь может выбрать одно (свойство SelectionMode равно One) или несколько значений (свойство SelectionMode равно MultiSimple или Multi Extended). Если значение свойства SelectionMode равно MultiSimple, щелчок мышью на элементе выделяет его или снимает выделение. Значение Multi Extended позволяет использовать при выделении диапазона строк клавишу Shift, а при добавлении элемента — клавишу Ctrl, аналогично проводнику Windows. Запретить выделение можно, установив значение свойства SelectionMode, равное None.
Чаще всего используются списки строк, но можно выводить и произвольные изображения. Список может состоять из нескольких столбцов (свойство Multi Column) и быть отсортированным в алфавитном порядке (Sorted = True).
Элементы списка нумеруются с нуля. Они хранятся в свойстве Items, представляющем собой коллекцию. В Items можно добавлять элементы с помощью методов Add, AddRange и Insert. Для удаления элементов служат методы Remove и RemoveAt, удаляющие заданный элемент и элемент по заданному индексу соответственно.
Выделенные элементы можно получить с помощью свойств SelectedItems и SelectedIndices, предоставляющих доступ к коллекциям выделенных элементов и их индексов.
В листинге 14.5 приведен пример приложения, которое отображает в списке типа ListBox строки, считанные из входного файла, а затем по щелчку на кнопке Запись выводит выделенные пользователем строки в выходной файл. Вид окна приложения приведен на рис. 14.10.
Рис. 14.10. Окно приложения для работы со списком строк
Листинг 14.5. Работа со списком строк
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
StreamReader f = new StreamReader( "input.txt" );
string buf;
while ( ( buf = f.ReadLine() ) != null ) // чтение из файла
listBox1.Items.Add(buf); // занесение в список
}
catch ( FileNotFoundException exc )
{
MessageBox.Show( exc.Message );
return;
}
}
private void button1_Click(object sender, EventArgs e)
{
StreamWriter f = new StreamWriter( "output.txt" );
foreach (string item in listBox1.SelectedItems )
f.WriteLine(item); // запись в файл
f.Close();
}
}
}
Предварительные замечания о формах
Класс Form наследует от длинной цепочки своих предков множество элементов, определяющих вид и поведение окон различного типа. Генеалогическое древо класса Form выглядит так: Object—>MarshalByRefObject—>Component—>Control —>Scrol1ableControl -»Contai nerControl.
Окна приложения могут иметь различные вид и назначение. Все окна можно разделить на модальные и немодальные. Модальное окно не позволяет пользователю переключаться на другие окна того же приложения, пока не будет завершена работа с текущим окном3. Как уже отмечалось, в виде модальных обычно оформляют диалоговые окна, требующие от пользователя ввода какой-либо информации. Модальное окно можно закрыть щелчком на кнопке наподобие ОК, подтверждающей введенную информацию, на кнопке закрытия окна или на кнопке вроде Cancel, отменяющей ввод пользователя. Примером модального окна может служить окно сообщений MessageBox, упоминавшееся в разделе «Шаблон Windows-приложения» (см. с. 322).
Немодальное окно позволяет переключаться на другие окна того же приложения. Немодальные окна являются, как правило, информационными. Они используются в тех случаях, когда пользователю желательно предоставить свободу выбора — оставлять на экране какую-либо информацию или нет.
Каждое приложение содержит одно главное окно. Класс главного окна приложения содержит точку входа в приложение (статический метод Main). При закрытии главного окна приложение завершается.
В случае использования многодокументного интерфейса (Multiple Document
Interface, MDI) одно родительское окно может содержать другие окна, называемые дочерними. При закрытии родительского окна дочерние окна закрываются автоматически. Вид окна определяет его функциональность, например, окно с одинарной рамкой не может изменять свои размеры.
Рассмотрим наиболее интересных предков класса формы. Их элементы наследуются не только формой, но и другими компонентами, такими как поля ввода или кнопки.
Класс MarshalByRefObject наделяет своих потомков некой особенностью, благодаря которой обращение к ним выполняется по ссылке, то есть локальная копия объекта не создается.
Класс Component обеспечивает потомков способностью взаимодействовать с контейнером, в котором они расположены. Кроме того, в нем определен метод Dispose, который автоматически вызывается, когда экземпляр класса более не используется. Поэтому для освобождения ресурсов, связанных с приложением, обычно переопределяют этот метод.
Класс Control, являющийся предком всех интерфейсных элементов, рассмотрен в этой главе ранее. В классе ScrollableControl определены элементы, позволяющие компоненту иметь горизонтальную и вертикальную полосы прокрутки. Свойства AutoScroll и AutoScrollMinSize обеспечивают автоматическое появление полос прокрутки в тех случаях, когда выводимая информация не помещается в компоненте.
Класс ContainerControl обеспечивает своих потомков возможностью управлять размещенными внутри них дочерними компонентами. Например, на форме обычно располагаются несколько кнопок, меток и т. п., а на панели — несколько флажков или переключателей. Свойства и методы класса позволяют установить фокус ввода на элемент или получать информацию о том, какой элемент имеет фокус ввода, а также управлять порядком получения фокуса с помощью свойств TabStop и Tablndex.
Класс Form
Класс Form представляет собой заготовку формы, от которой наследуются классы форм приложения. Помимо множества унаследованных элементов, в этом классе определено большое количество собственных элементов, наиболее употребительные из которых приведены в табл. 14.7-14.9.
Таблица 14.7. Некоторые свойства класса Form
Свойство
Описание
AcceptButton
Позволяет задать кнопку или получить информацию о кнопке, которая будет активизирована при нажатии пользователем клавиши Enter
ActiveMDIChild, IsMDIChild, IsMDIContainer
Свойства предназначены для использования в приложениях с многодокументным интерфейсом (MDI)
AutoScale
Позволяет установить или получить значение, определяющее, будет ли форма автоматически изменять свои размеры, чтобы соответствовать высоте шрифта, используемого ца форме, или размерам размещенных на ней компонентов
FormBorderStyle
Позволяет установить или получить стиль рамки вокруг формы (используются значения перечисления FormBorderStyle)
Cancel Button
Позволяет задать кнопку или получить информацию о кнопке, которая будет активизирована при нажатии пользователем клавиши Esc
Control Box
Позволяет установить или получить значение, определяющее, будет ли присутствовать стандартная кнопка системного меню в верхнем левом углу заголовка формы
Menu, MergedMenu
Используются для установки или получения информации о меню на форме
MaximizeBox, MinimizedBox
Определяют, будут ли на форме присутствовать стандартные кнопки восстановления и свертывания в правом верхнем углу заголовка формы
ShowInTaskbar
Определяет, будет ли форма отображаться на панели задач Windows
StartPosition
Позволяет получить или установить значение, определяющее исходное положение формы в момент выполнения программы (используются значения перечисления FormStartPosition).
Например, для отображения формы в центре экрана устанавливается значение CenterScreen
WindowState
Определяет состояние отображаемой формы при запуске (используются значения перечисления FormWindowState)
Таблица 14.8. Методы класса Form
Метод
Описание
Activate
Активизирует форму и помещает в нее фокус ввода
Close
Закрывает форму
CenterToScreen
Помещает форму в центр экрана
LayoutMDI
Размещает все дочерние формы на родительской в соответствии со значениями перечисления LayoutMDI
OnResize
Может быть замещен для реагирования на событие Resize
Show
Отображает форму (унаследовано от Control)
ShowDialog
Отображает форму как диалоговое окно (подробнее о диалоговых окнах рассказывается в следующем разделе)
Таблица 14.9. Некоторые события класса Form
Событие
Описание
Activate
Происходит при активизации формы (когда она выходит в активном приложении на передний план)
Closed, Closing
Происходят во время закрытия формы
MDIChildActive
Возникает при активизации дочернего окна
Об использовании некоторых элементов, перечисленных в таблицах, рассказывается в следующем разделе.
Диалоговые окна
В библиотеке .NET нет специального класса для представления диалоговых окон. Вместо этого устанавливаются определенные значения свойств в классе обычной формы. В диалоговом окне можно располагать те же элементы управления, что и на обычной форме. Диалоговое окно характеризуется:
□ неизменяемыми размерами (FormBorderStyle = FixedDialog);
□ отсутствием кнопок восстановления и свертывания в правом верхнем углу заголовка формы (MaximizeBox = False, MinimizedBox = False);
□ наличием кнопок наподобие ОК, подтверждающей введенную информацию, и Cancel, отменяющей ввод пользователя, при нажатии которых окно закрывается (AcceptButton = имя_кно-пки_ОК, Cancel Button = имя_кнопки_Сапсе1);
□ установленным значением свойства DialogResult для кнопок, при нажатии которых окно закрывается.
Для отображения диалогового окна используется метод ShowDialog, который формирует результат выполнения из значений перечисления DialogResu.lt, описанных в табл. 14.5. Если пользователь закрыл диалоговое окно щелчком на кнопке наподобие ОК, введенную им информацию можно использовать в дальнейшей работе. Закрытие окна щелчком на кнопке вроде Cancel отменяет все введенные данные. Диалоговое окно обычно появляется при выборе пользователем некоторой команды меню на главной форме.
Приведем пример простого приложения, содержащего две формы. На главной
форме (рис. 14.11) расположено меню из двух команд — Dialog и Exit. При выборе команды Dialog появляется диалоговое окно, включающее метку Введите информацию, поле ввода текста и две кнопки, ОК и Cancel (рис. 14.12).
Рис. 14.11. Главное окно приложения с меню и диалоговым окном
Рис. 14.12. Диалоговое окно
Если пользователь введет текст в диалоговое окно и закроет его щелчком на кнопке ОК, этот текст отобразится в поле метки в главном окне. Если диалоговое окно будет закрыто щелчком на кнопке Cancel, поле метки останется неизменным.
Добавление в проект второй формы выполняется выбором в меню команды Project ► Add Windows Form. Начнем визуальное проектирование с этой формы.
Значения свойств компонентов, установленных с помощью окна свойств, перечислены в табл. 14.10.
Таблица 14.10. Значения свойств элементов формы
Элемент
Свойство
Значение
Метка
Text
Введите информацию
TextAlign
MiddleCenter
Поле ввода
Text
Пустое значение
Кнопка
Name
btnOK
DialogResult
OK
Text
OK
Кнопка
Name
btnCancel
DialogResult
Cancel
Text
Cancel
Форма
AcceptButton
btnOK
CancelButton
btnCancel
FormBorderStyle
FixedDialog
MaximizeBox
False
MinimizeBox
False
StartPosition
CenterParent
Пользователь вводит информацию в поле ввода textBoxl, которое является закрытым элементом формы. Чтобы получить значение свойства Text поля ввода, добавим в описание класса свойство Info. Это единственное дополнение, которое вносится в шаблон текста класса формы:
public partial class Form2 : Form
{
public string Info
{
get { return textBox1.Text; }
}
public Form2()
{
InitializeComponent();
}
Визуальное проектирование главной формы еще проще, чем первой, и сводится к размещению главного меню и метки. Для наглядности метка окружена рамкой (BorderStyle = FixedSingle). Вот как выглядят обработчики событий для пунктов меню:
private void dialogToolStripMenuItem_Click(object sender, EventArgs e)
{
Form2 f = new Form2(); // создание экземпляра класса окна
if (f.ShowDialog() == DialogResult.OK) // отображение окна
label1.Text = f.Info;
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Close();
}
Как видите, для отображения диалогового окна следует создать экземпляр объекта соответствующей формы, а затем вызвать для этого объекта метод ShowDlalog.
При подтверждении ввода текст пользователя можно получить с помощью свойства Info, доступного только для чтения. При необходимости передавать информацию не только из диалогового окна, но и в него, можно добавить в описание свойства часть set.
ПРИМЕЧАНИЕ
Следует различать процесс создания формы — объекта класса Form или его наследника — от процесса вывода формы на экран. Форма, как и любой объект, создается при выполнении операции new с вызовом конструктора. Для вывода формы служит метод Show или ShowDialog класса Form, вызываемый соответствующим объектом. Для скрытия формы используется метод Hide. Фактически, методы Show и Hide изменяют свойство Visible объекта. Разница между скрытием формы методом Hide и ее закрытием методом Close состоит в том, что первый из них делает форму невидимой, но не изменяет сам объект, а метод Close делает объект недоступным и закрывает все его ресурсы.
Класс Application
Класс Application, описанный в пространстве имен System.Windows.Forms, содержит статические свойства, методы и события, предназначенные для управления приложением в целом и получения его общих характеристик. Наиболее важные элементы класса Application перечислены в табл. 14.11.
Таблица 14.11. Основные элементы класса Application
Элемент класса
Тип
Описание
AddMessageFi1ter RemoveMessageFi1ter
Методы
Позволяют перехватывать сообщения и, выполнять с этими сообщениями нужные предварительные действия. Для того чтобы добавить фильтр сообщений, необходимо указать класс, реализующий интерфейс IMessageFilter
DoEvents
Метод
Обеспечивает способность приложения обрабатывать сообщения из очереди сообщений во время выполнения какой-либо длительной операции
Exit
Метод
Завершает работу приложения
ExitThread
Метод
Прекращает обработку сообщений для текущего потока и закрывает все окна, владельцем которых является этот поток
Run
Метод
Запускает стандартный цикл обработки сообщений для текущего потока
CommonAppDataRegistry
Свойство
Возвращает параметр системного реестра, который хранит общую для всех пользователей информацию о приложении
CompanyName
Свойство
Возвращает имя компании
CurrentCulture
Свойство
Позволяет задать или получить информацию о естественном языке, для работы с которым предназначен текущий поток
CurrentInputLanguage
Свойство
Позволяет задать или получить информацию о естественном языке для ввода информации, получаемой текущим потоком
ProductName
Свойство
Позволяет получить имя программного продукта, которое ассоциировано с данным приложением
ProductVersion
Свойство
Позволяет получить номер версии программного продукта
StartupPath
Свойство
Позволяет определить имя выполняемого файла для работающего приложения и путь к нему в операционной системе
ApplicationExit
Событие
Возникает при завершении приложения
Idle
Событие
Возникает, когда все текущие сообщения в очереди обработаны и приложение переходит в режим бездействия
ThreadExit
Событие
Возникает при завершении работы потока в приложении. Если работу завершает главный поток приложения, это событие возникает до события ApplicationExit
Многие свойства класса Application позволяют получить метаданные сборки (на
пример, номер версии или имя компании), не используя типы пространства имен System.Reflection. Программист не часто работает непосредственно с классом Application, поскольку большую часть необходимого кода среда формирует автоматически.