Основы создания оконных приложений 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Основы создания оконных приложений



Основы создания оконных приложений

Элементы управления

Как мы уже говорили, внешний вид (официально – визуальный интерфейс) оконного приложения основан на стандартном наборе элементов, которые можно размещать в окне (на форме) приложения. Существует несколько десятков видов таких элементов (их еще называют элементами управления, а по-английски – control). Каждый вид элементов управления реализован с помощью некоторого класса. Все классы элементов управления являются производными от класса Control. Класс Control и  все классы элементов управления находятся в пространстве имен System.Windows.Forms. Наиболее популярными являются командные кнопки (класс Button), надписи или метки (класс Label) и поля ввода (класс TextBox). Программно управлять внешним видом элементов управления можно через соответствующие открытые свойства классов. Например, размер элемента управления можно узнать или изменить с помощью свойств Height (высота) и Width(ширина). Одной из важных составляющих Вашего умения создавать оконные приложения является знание этих многочисленных свойств.

Усовершенствуем нашу программу. После запуска в окне программы должны размещаться две кнопки. Размеры и расположение элементов на форме показаны на следующем рисунке:

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

01. using System;

02. using System.Windows.Forms;

03. using System.Drawing;

04. static class Program

05. {

06.   static void Main()

07.   {

08.     int FormHeight=300;

09.     int FormWidth=500;

10.     Form f;

11.     Button b1;

12.     Button b2;

13.     //создание и настройка формы

14.     f = new Form();

15.     f.ClientSize = new Size(FormWidth, FormHeight);

16.     //создание и настройка первой кнопки

17.     b1 = new Button();

18.     b1.Left = FormWidth / 5; //расстояние левой грани кнопки от левой грани клиентской области формы

19.     b1.Top = FormHeight / 3; //расстояние верхней грани кнопки от верхней грани клиентской области формы

20.     b1.Width = FormWidth / 5; //ширина кнопки

21.     b1.Height = FormHeight / 3; //высота кнопки

22.     //создание и настройка второй кнопки

23.     b2 = new Button();

24.     b2.Bounds = new Rectangle(3*FormWidth / 5, FormHeight / 3, FormWidth / 5, FormHeight / 3);

25.     //добавление кнопок на форму

26.     f.Controls.Add(b1);

27.     f.Controls.Add(b2);

28.     //запуск цикла обработки событий

29.     Application.Run(f);

30.   }

31. }

Текст программы существенно вырос. Объясним все подробнее.

1. В программе используются классы из пространства имен System.Drawing. Поэтому не забудьте доавить в проект ссылку (reference) на это пространство имен и соответствующую директиву using в текст программы (стр.03).

2. Для удобства управления размерами в стр. 08 и 09 вводятся вспомогательные переменные FormHeight (высота формы) и FormWidth(ширина формы). Они определяют размер внутренней области окна (клиентской области), не включающей заголовок и рамку вокруг окна.

3. Программа должна обращаться к свойчтвам формы и кнопок. Поэтому для ссылки на эти объекты в стр. 10-12 описываются соответствующие переменные.

4. После создания объекта-формы в стр.14 ее клиентский размер задается с помощью свойства ClientSize. Значением этого свойства является ссылка на объект класса Size из пространства имен System.Drawing (стр.15).

5. Первая кнопка создается в стр.17. Ее положение и размер задаются свойствами Left, Top, Width и Heigh (стр.18-21).

6. Вторая кнопка создается в стр.23. Ее положение и размер задаются другим способом – с помощью свойства Bounds (границы), значением которого является объект Rectangle (прямоугольник) (стр.24). В дальнейшем выбирайте тот способ управления, который Вам больше подходит.

7. Следующий момент очень важен и часто вызывает на практике ошибки. Объекты кнопки пока никак не связаны с объектом-формой. Поэтому программа хотя и создает все объекты, но не показывает кнопки внутри формы. Для показа кнопок на форме их необходимо добавить в специальный контейнер формы, который доступен через свойство Controls. Это делается методом Add в стр. 26 и 27.

8. Наконец в стр. 29 форма показывается на экране и начинает взаимодействовать с пользователем.

Элемент управления 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 можно индексировать.

Файл 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;

}

Далее можно рассмотреть несколько других примеров:

- крестики-нолики.

Дальнейшая логика курса – рассмотрим способы постоянного хранения. Тогда можно будет рассмотреть архитектурные принципы, основанные на разделении на бизнес-логику, визуальный интерфейс и источник данных.

Сохранение результатов

Возможность хранить информацию в постоянной памяти является необходимым свойством большинства программных приложений. Для этого используются несколько различных подходов:

1. Файловый ввод-вывод.

2. Механизм сериализации.

3. Базы данных.

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

Работа с файлами – наиболее традиционный способ использования постоянной памяти. Для этого в С# имеется множество классов, содержащихся в пространстве имен System.IO. Классы этого пространства имен можно разбить на 2 категории:

1. Классы, управляющие объектами файловой системы.

2. Классы, использующие потоки.

Создание каталога.

di1.Create();

Удаление каталога

di1.Delete();

Если удаляемый каталог не пуст, возникает исключение.

Работа с файлами

Для выполнения задач, связанных с файлами, можно использовать класс FileInfo.

Для получения списка файлов в папке используется статический метод GetFiles класса DirectoryInfo.

У методов GetDirectories и GetFiles имеется перегруженный вариант со вторым параметром, в котором можно задать шаблон (маску) интересующих папок или файлов. Например, Directory.GetFiles(@"d:\MyWork", "*.doc") вернет массив с именами Word-файлов в папке d:\MyWork.

 

 

Запись в текстовый файл
// оператор using автоматически закрывает StreamWriter using (StreamWriter sw = new StreamWriter("TestFile.txt")) { // Добавить в файл некоторый текст sw.Write("Это "); sw.WriteLine("заголовок файла."); // В могут быть записаны объекты sw.WriteLine(DateTime.Now); }
Чтение из текстового файла
try { // оператор using автоматически закрывает StreamReader using (StreamReader sr = new StreamReader("TestFile.txt")) { String line; // читать и показывть строки из файла пока не конец while ((line = sr.ReadLine())!= null)  Console.WriteLine(line); } } catch (Exception e) { Console.WriteLine("The file could not be read:"); Console.WriteLine(e.Message); }
Добавление в текстовый файл
Так же как запись в файл, но объект StreamWriter создается: FileInfo fi=new FileInfo("log.txt"); StreamWriter sw = FileInfo.AppendText(); либо StreamWriter sw = new StreamWriter("TestFile.txt",true);
Перебор файлов каталога и определение размера файла
DirectoryInfo di = new DirectoryInfo("c:\\"); // получить ссылку на каждый файл каталога FileInfo[] fiArr = di.GetFiles(); // Показать имена и размеры файлов Console.WriteLine("Каталог {0} содержит файлы:", di.Name); foreach (FileInfo f in fiArr) Console.WriteLine("Размер {0} - {1} байт.",f.Name,f.Length);
Получение и изменение атрибутов файла В примере методы GetAttributes и SetAttributes применяют к файлу атрибуты Archive и Hidden (применяется техника битовых масок).
string path = @"c:\temp\MyTest.txt"; // Создать файл, если он не существует if (!File.Exists(path)) File.Create(path); if ((File.GetAttributes(path) & FileAttributes.Hidden) ==   FileAttributes.Hidden) { // Показать файл File.SetAttributes(path, FileAttributes.Archive); Console.WriteLine("Файл {0} теперь виден.", path); } else { // Скрыть файл File.SetAttributes(path, File.GetAttributes(path) | FileAttributes.Hidden); Console.WriteLine("Файл {0} скрыт.", path); }
Чтение и запись в бинарный файл
private const string FILE_NAME = "Test.data"; public static void Main(String[] args) { // создать новый пустой файл. if (File.Exists(FILE_NAME)) { Console.WriteLine("{0} already exists!", FILE_NAME); return; } FileStream fs=new FileStream(FILE_NAME,FileMode.CreateNew); BinaryWriter w = new BinaryWriter(fs); for (int i = 0; i < 11; i++) w.Write((int) i); w.Close(); fs.Close(); fs=new FileStream(FILE_NAME, FileMode.Open,FileAccess.Read); BinaryReader r = new BinaryReader(fs); for (int i=0; i<11; i++) Console.WriteLine(r.ReadInt32()); r.Close(); fs.Close(); }

Стандартные диалоговые окна

Создадим оконное приложение, позволяющее объединять содержимое двух выбранных пользователем файлов и сохранять их в третьем.

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

public partial class Form1: Form

{ public Form1()

{ InitializeComponent();

 ofdSourceFile.InitialDirectory = "c:\\";

ofdSourceFile.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";

}

private void Form1_Load(object sender, EventArgs e)

{ btnSrcFile1.Enabled = true;

btnSrcFile2.Enabled = false;

btnSaveFile.Enabled = false;

}

private void btnSrcFile1_Click(object sender, EventArgs e)

{ btnSrcFile1.Enabled = false;

OpenAndReadFile();

btnSrcFile2.Enabled = true;

}

private void btnSrcFile2_Click(object sender, EventArgs e)

{ btnSrcFile2.Enabled = false;

OpenAndReadFile();

btnSaveFile.Enabled = true;

}

private void OpenAndReadFile()

{ StreamReader sr;

if (ofdSourceFile.ShowDialog() == DialogResult.OK)

{ if (ofdSourceFile.ShowDialog() == DialogResult.OK)

{ sr = new StreamReader(ofdSourceFile.FileName);

   // сюда можно вставить код для чтения из файла

   sr.Close();

}

}

}

private void btnSaveFile_Click(object sender, EventArgs e)

{ btnSaveFile.Enabled = false;

StreamWriter sw;

if (sfdSaveFile.ShowDialog() == DialogResult.OK)

{ sw = new StreamWriter(sfdSaveFile.FileName);

// сюда можно вставить код для записи в файл

sw.Close();

}

}

}

Здесь используется переменная ofdSourceFile, которая описана как OpenFileDialog. Это описание генерируется дизайнером в ответ на перетаскивание на форму соответствующего элемента управления. Часто целесообразнее описать такую переменную как локальную в рамках метода-обработчика.

Обратите внимание на то, что текст приложения еще не завершен – необходимо реализовать чтение из двух файлов и запись их содержимого в третий файл.

Сериализация

Использование ранее рассмотренных простых средств файлового ввода-вывода оказывается совершенно неудобным для постоянного хранения сложных объектов с разнообразной и даже динамически меняющейся структурой. Для подобных случаев предлагается использовать поддерживаемый в.NET механизм сериализации. Буквальный перевод этого термина означает преобразование информационных объектов в линейную хранимую форму и обратную реконструкцию линейного представления в объектную структуру.

Пространства имен

System.Runtime.Serialization.Formatters.Binary;

Синтаксическая форма сериализации выглядит довольно просто:

[Serializable] public class Radio

{ public bool Autosearch;

public double[] stations;

[NonSerialized]

public string radioed = “XF-552RR6”;

}

Остальные классы нашего примера:

[Serializable] public class Car

{ public Radio theRadio=new Radio();

public bool Is4Wheel;

}

[Serializable] public class JamesBondCar: Car

{ public bool canFly;

public bool canShoot;

}

public class Program

{ static void Main()

{ JamesBondCar jbc = new JamesBondCar();

jbc.canFly = false;

jbc.canShoot = true;

jbc.theRadio.stations = new double[]{88.8, 99.9, 103.7};

jbc.Is4Wheel=true;

// Теперь сохраним объект в файле user. dat.

BinaryFormatter binFormat = new BinaryFormatter();

Stream fStream = new FileStream(“user.dat",

FileMode.Create, FileAccess.Write, FileShare.None);

binFormat. Serialize (fStream, jbc);

fStream.Close();

}

}

В приведенном примере сериализация осуществлялась в компактном бинарном формате с помощью класса BinaryFormatter. Часто практичнее сохранят в формате XML  с помощью другого класса-«форматизатора» SoapFormatter.

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

Объектные графы

Для лучшего представления о том, как выполняется процесс сериализации, удобно использовать так называемые объектные графы. Представим, что имеются следующие классы. «Автомобиль», «Радио» (класс «Автомобиль» содержит переменную этого типа) и «Автомобиль Джеймса Бонда» (производный от «Автомобиль»).

Текстовое представление этого графа (которое строит CLR) выглядит так:

[Computer 3, ref 2], [CPU 2], [Notebook 1, ref 3, ref 2]

Таким образом, на графе присутствуют отношения двух типов – наследование и композиция. При сериализации объекта класса Notebook объектный граф поможет учесть все его связи, в том числе завуалированную связь с объектом CPU.

Если Вам не нужно осуществлять сериализацию всех переменных объекта (выборочная сериализация), пометьте несериализуемые переменные атрибутом [NonSerialized].

Замечания.

1. Атрибут [Serializable] не наследуется. (в Справке сказано, что класс с этим атрибутом cannot be inherited!)

2. Сериализация с помощью BinaryFormatter сохраняет все переменные объекта. Сериализация с помощью SoapFormatter или XmlSerializer сохраняет только открытые переменные и закрытые переменные, доступные через открытые свойства (а как это?).

Десериализация vs Singleton

Формат сериализации

- BinaryFormatter – компактный двоичный формат. Требует подключения System.Runtime.Serialization.Formatters.Binary.

- SoapFormatter – в виде сообщения SOAP. Требует подключения System.Runtime.Serialization.Formatters.Soap. В проект нужно добавить ссылку на System.Runtime.Serialization.Formatters.Soap.dll. Этот вариант удобен при передаче данных по протоколу HTTP.

- XmlSerializer – в виде «чистого» XML. Требует подключения System.Xml.Serialization.

Объекты всех этих типов для осуществления сериализации реализуют методы Serialize и Deserialize.

Реконструкция объектов

// Чтение JamesBondCar из двоичного файла.

fStream = File.OpenRead("CarData");

JamesBondCar carFromDisk =

(JamesBondCar)binFormat. Deserialize (fStream);

Console.WriteLine("Может ли машина летать? {0}",

carFromDisk.canFly);

fStream.Close();

 

Другие элементы управления

Label – поле вывода текста (метка)

TextBox – поле ввода и редактирования текста

Button – командная кнопка

CheckBox – переключатель не исключающего выбора

RadioButton – переключатель исключающего выбора

ListBox – список выбора

ComboBox – комбинированный список выбора

MainMenu – главное меню окна

ContextMenu – контекстное меню

 

MessageBox

           Show

Label

           Refresh

           Paint

           PaintEventArgs

Button

           xEnabled

           SetBounds

TextBox

           Text

           Handled

           Focus

           TextChanged

           KeyPress

KeyPress

KeyPressedEventArgs

           KeyChar

ComboBox

           DropDownStyle

           SelectedIndex

SelectedIndexChanged

CheckBox

           CheckedChanged

           Checked

Form

           Load

           Close

 

FolderBrowserDialog

PictureBox

DirectoryInfo

FileInfo

 

Timer

NumericUpDown

 

Класс Control

Все классы элементов управления и класс Form являются производными от класса Control. Поэтому они имеют доступ к обширной унаследованной функциональности этого класса. Класс System.Windows.Forms.Control задает общее поведение, ожидаемое от любого GUI-типа. Базовые члены Control позволяют указать размер и позицию элемента управления, выполнить захват событий клавиатуры и мыши, получить и установить фокус ввода, задать и изменить видимость членов и т.д. В табл. 19.4 определяются некоторые (но, конечно же, не все) свойства, сгруппированные по функциональности.

Таблица 19.4. Базовые свойства типа Control (большинство свойств обеспечивают доступ как по чтению, так и по записи)

Свойства Описание
BackColor Цвет фона. Можно указать название или же привя­заться к цветовой схеме операционной системы. Привязка к цветовой схеме задается путем указания элемента интерфейса (например, Control)
ForeColor Цвет, используемый по умолчанию компонентами, находящимися на поверхности формы, для отобра­жения текста, а также в качестве основного цвета. Изменение свойства приводит к автоматическому изменению соответствующего свойства всех компо­нентов формы (при условии, что значение свойства компонента не было задано (изменено) вручную)
BackgroundImage Фоновое изображение. Если изображение меньше размера формы, фоновое изображение будет сформировано путем дублирования его по вертика­ли и горизонтали
Font Шрифт, используемый по умолчанию компонентами, находящимися на поверхности формы. Изменение свойства приводит к автоматическому изменению соответствующего свойства всех компонентов формы (при условии, что значение свойства компонента не было задано (изменено) вручную)
Cursor Вид указателя мыши при позиционировании указателя на кнопке
Top, Left, Bottom, Right,, Height, Width Указывают текущие размеры элемента управления
Bounds Расположение и размеры элемента управления. Используется объект класса Rectangle. Button btn = new Button(); btn.Bounds = new Rectangle(10,10,75,25);
ClientRectangle (только чтение) Прямоугольник, определяющий внутреннюю (клиентскую) область элемента управления Form frm = new Form(); Rectangle r = frm.ClientRectangle;  
Enabled, Focused, Visible Каждое из этих свойств возвращает значение типа Boolean, указывающее соответствующую характеристику состояния элемента управления
ModifierKeys Статическое свойство, содержащее информацию о текущем состоянии модифицирующих клавиш (<Shift>, <Ctrl> и <Alt>) и возвращающее эту информацию в виде типа Keys
MouseButtons Статическое свойство, содержащее информацию о текущем состоянии кнопок мыши (левой, правой, и средней) и возвра­щающее эту информацию в виде типа MouseButtons
TabIndex, TabStop Используются для указания порядка переходов по клавише табуляции для элемента управления
Opacity Определяет степень прозрачности элемента управления в дробных единицах (0.0 соответствует абсолютной прозрачно­сти, а 1.0— абсолютной непрозрачности)
Text Указывает текстовые данные, ассоциируемые с элементом управления
Controls Позволяет получить доступ к строго типизованной коллекции (ControlsCollection), содержащей все дочерние элемен­ты управления, существующие в рамках данного элемента управления

Кроме того, класс Control определяет ряд событий, позволяющих реагировать на изменение состояния мыши, клавиатуры, действия выделения и перетаскива­ния объектов (а также на многие другие действия). В табл. 19.5 предлагается список некоторых (но далеко не всех) событий, сгруппированных по функциональности.

Таблица 19.5. События типа Control

События Описание
Click, Doubleclick, MouseEnter, MouseLeave, MouseDown, MouseUp, MouseMove, MouseHover, MouseWheel, События, позволяющие учитывать состояние мыши
KeyPress, KeyUp, События, позволяющие учитывать состояние клавиатуры
KeyDown,DragDrop, DragEnter, DragLeave, DragOver События, используемые для контроля действий, связанных с перетаскиванием объектов
Paint События, позволяющие взаимодействовать с GDI+

Наконец, базовый класс Control определяет целый ряд методов, позволяющих взаимодействовать с любым типом, производным от Control. При ближайшем рассмотрении методов Control вы обнаружите, что многие из них имеют префикс On, за которым следует имя соответствующего события (OnMouseMove, OnKeyUp, OnPaint и т.д.). Каждый из этих снабженных префиксом виртуальных методов представляет собой обработчик соответствующего события, заданный по умолчанию. Переопределив такой виртуальный член, вы получаете возможность выпол­нить необходимую предварительную (или заключительную) обработку данных, пе­ред вызовом (или после вызова) родительской реализации обработчика события.

public class MainWindow: Form

{ protected override void OnMouseDown(MouseEventArgs e)

  {

// Добавленный программный код для события MouseDown.

// Вызов родительской реализации.

base.OnMouseDown(e);

  }

}

Это может оказаться полезным, например, при создании пользовательских элементов управления, которые получаются из стандартных (см. главу 21), но чаще всего вы будете использовать обработку событий в рамках стандартного синтаксиса событий С# (именно это предлагается средствами проектирования Visual Studio 2005 по умолчанию). В этом случае среда разработки вызовет пользовательский обработчик события после завершения работы родительской реализации.

public class MainWindow: Form

{ public MainWindow ()

{ MouseDown+=new MouseEventHandler(MainWindow_MouseDown); }

void MainWindow_MouseDown(object sender, MouseEventArgs e)

  {

  // Добавленный программный код для события MouseDown.

}

}

Кроме методов вида OnХХХ(), есть несколько других методов, о которые вам следует знать.

  • Hide(). Скрывает элемент управления, устанавливая для его свойства Visible значение false (ложь).
  • Show(). Делает элемент управления видимым, устанавливая для его свойства Visible значение true (истина).
  • Invalidate(). Заставляет элемент управления обновить свое изображение, посылая событие Paint.

Несомненно, класс Control определяет и другие свойства, методы и события в дополнение к тем, которые вы только что рассмотрели. Но и сейчас вы должны иметь достаточно хорошее представление об общих функциональных возможностях этого базового класса. Давайте рассмотрим примеры, позволяющие увидеть указанный класс в действии.

Ответ на события MouseMove

Далее, мы должны обработать событие MouseMove. Целью является отображение текущих координат (х, у) указателя в области заголовка формы. Все связанные с состоянием мыши события (MouseMove, MouseUp и т.д.) работают в паре с делегатом MouseEventHandler, способным вызвать любой метод, соответствующий следующей сигнатуре.

void MyMouseHandler(object sender, MouseEventArgs e);

Поступающая на вход структура MouseEventArgs расширяет общий базовый класс EventArgs путем добавления целого ряда членов, специально предназначенных для обработки действий мыши (табл. 19.6).

Таблица 19.6. Свойства типа MouseEventArgs

Свойство Описание
Button Содержит информацию о том, какая клавиша мыши была нажата, в соответствии с определением перечня MouseButtons
Clicks Содержит информацию о том, сколько раз была нажата и отпущена клавиша мыши
Delta Содержит значение со знаком, соответствующее числу щелчков, произошедших при вращении колесика мыши
X, Y Содержит информацию о координатах х и y указателя при щелчке мыши

Вот обновленный класс MainForm, в котором обработка события MouseMove происходит так, как предполагается выше.

public class MainForm: Form

{ public MainForm ()

{...

// Для обработки события MouseMove.

MouseMove += new MouseEventHandler(MainForm_MouseMove);

  }

  // Обработчик события MouseMove.

public void MainForm_MouseMove (object sender,MouseEventArgs e)

{ Text = string.Format("Текущая позиция указателя: ({0}, {1})",

       e.X, e.Y);

  }

}

Если теперь запустить программу и поместить указатель мыши на форму, вы увидите текущие значения координат (х, у) указателя, отображенные в области заголовка соответствующего окна (рис. 19.4).

Рис. 19.4. Мониторинг движения мыши

Ответ на события клавиатуры

Обработка ввода с клавиатуры почти идентична обработке событий мыши. События KeyUp и KeyDown работают в паре с делегатом KeyEventHandler, кото­рый может указывать на любой метод, получающий объект общего вида в качестве первого параметра, и KeyEventArgs — в качестве второго.

void MyKeyboardHandler(object sender, KeyEventArgs e);

Описания членов KeyEventArgs предлагаются в табл. 19.7.

Таблица 19.7. Свойства типа KeyEventArgs

Свойство   Описание  
Alt Содержит значение, являющееся индикатором нажатия клавиши <Alt>
Control         Содержит значение, являющееся индикатором нажатия клавиши <Ctrl>
Handled        Читает или устанавливает значение, являющееся индикатором полного заверше­ния обработки события обработчиком
KeyCode         Возвращает клавишный код для события KeyDown или события KeyUp
Modifiers     Указывает, какие модифицирующие клавиши были нажаты (<Ctrl>, <Shift> и/или <Alt>)
Shift            Содержит значение, являющееся индикатором нажатия клавиши <Shift>

 

Измените объект MainForm, чтобы реализовать обработку события KeyUp. В окне сообщения отобразите название нажатой клавиши, используя свойство KeyCode.

public class MainForm: Form

{ public MainForm ()

{ // Для отслеживания событий KeyUp.

KeyUp += new KeyEventHandler(MainForm_KeyUp);

}

private void MainForm_KeyUp(object sender, KeyEventArgs e)

{ MessageBox.Show(e.KeyCode.ToString(),"Нажата клавиша!"); }

}

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

На этом мы завершим обсуждение функциональных возможностей базового класса Control и перейдем к обсуждению роли Form.

Button

Компонент Button представляет собой командную кнопку. Свой­ства компонента приведены в табл. 2.2.

Таблица. 2.2. Свойства компонента Button

Свойство Описание
Text Текст (надпись) на кнопке
TextAlign Положение текста (надписи) на кнопке. Надпись может располагаться в центре (MiddleCenter), быть прижата к левой (MiddleLeft) или правой (MiddleRight) границе Можно задать и другие способы размещения надписи (TopLeft, TopCenter, TopRight, BottomLeft, BottomCenter. BottomRight)
FlatStyle Кнопка может быть стандартной (Standard), плоской (Flat) или "всплывающей" (Popup)
Location Положение кнопки на поверхности формы. Уточняющее свойство X определяет расстояние от левой границы кнопки до левой границы формы, уточняющее свойство Y - от верхней границы кнопки до верхней границы кли­ентской области формы (нижней границы заголовка)
Size Размер кнопки
Font Шрифт, используемый для отображения текста на кнопке
ForeColor Цвет текста, отображаемого на кнопке
Enabled Признак доступности кнопки. Кнопка доступна, если значение свойства равно True, и недоступна (например, событие Click в результате щелчка на кнопке не возникает), если значение свойства равно False
Visible Позволяет скрыть кнопку (False) или сделать ее видимой (True)
Image Картинка на поверхности формы. Рекомендуется использовать gif-файл, в котором определен прозрачный, цвет
ImageAlign Положение картинки на кнопке. Картинка может располагатъся в центе (MiddleCenter), быть прижата к левой (MiddleLeft) или правой (MiddleRight) границе. Можно задать и другие способы размещения картинки на кнопке (TopLeft, TopCenter, TopRight, BottomLeft, BottomCenter, BottomRight)
ImageList Набор изображений, из которых может быть выбрано то, которое будет отображаться на поверхности кнопки. Представляет собой объект типа ImageList. Чтобы задать значение свойства, в форму приложения нужно добавить компонент ImageList
ImageIndex Номер (индекс) изображения из набора ImageList, которое отображается на кнопке
ToolTip Подсказка, появляющаяся рядом с указателем мыши при позиционировании его на кнопке. Чтобы свойство было доступно, в форму приложения надо добавить компонент ToolTip

ComboBox

Компонент ComboBox представляет собой комбинацию поля редактирования и списка, что дает возможность ввести данные путем набора на клавиатуре или выбором из списка. Свойства компонента приведены в табл. 2.3.

Таблица 2.3. Свойства компонента CamboBox



Поделиться:


Последнее изменение этой страницы: 2021-12-15; просмотров: 45; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.129.23.214 (0.299 с.)