
- •Часть 2. Сборник рецептов по визуальному программированию Введение в объектно-ориентированное программирование
- •Создание проекта в VisualStudio
- •Файлы проекта
- •Сведения об объекте
- •Общие свойства всех объектов
- •Класс Form
- •Помещение компонента в форму и прочие действия с дизайнером форм
- •Свойства форм
- •События формы
- •Методы формы
- •Компоненты ввода и отображения текстовой информации Компонент Label
- •Некоторые свойства компонента Label
- •Компонент TextBox
- •Методы TextBox
- •Компонент RichTextBox
- •Ввод числовых значений в компонент TextBox
- •Проверка, введены ли значения
- •Компонент ListBox
- •Компонент ComboBox
- •Ввод данных из файла
- •Компонент MaskedTextBox
- •Кнопки, индикаторы и управляющие элементы Компонент Button
- •Компонент Panel
- •Компоненты RadioButtonиCheckBox
- •Компонент GroupBox
- •Пример. Комплектация автомобиля
- •Работа с меню Главное меню
- •Контекстное меню
- •Создание текстового редактора
- •Системные диалоги
- •Компонент OpenFileDialog
- •Компонент SaveFileDialog
- •Диалог выбора шрифта
- •Диалог выбора цвета
- •Компонент PrintDialog
- •Диалоговые окна в текстовом редакторе
- •Расширенные символы Unicode
- •Работа с графикой Использование графических файлов
- •Создание фотоальбома
- •Методы для рисования на форме и прочих компонентах
- •Работа с таймером
- •Работа с датой и временем
- •Добавление новых форм к проекту
- •Многостраничные панели
- •Способы задания страниц
- •Методы TabControl
Работа с таймером
Компонент Timerнаходится в спискеComponentsпалитры компонентов. Он задает счетчик времени и является удобным средством для организации процессов, автоматически повторяющихся через равные интервалы времени.
Данный компонент может быть использован для решения следующих задач:
синхронизация мультипликации;
закрытие окон, с которыми пользователь долго не работает;
включение хранителя экрана;
закрытие связи с удаленным сервером;
регулярный опрос некоторых источников информации;
задание времени на ответ в обучающих программах.
Таймер– невизуальный компонент, который размещается внизу окна дизайнера формы.
Основными свойствами этого компонента являются:
1) Interval– интервал времени в миллисекундах, через которое возникает событие таймераTick;
2) Enabled– управляет запуском и остановкой таймера.
При разработке обработчика события следует учитывать, что новое событие не возникает, пока не выполнятся все команды обработчика. Как только все команды обработчика будут завершены, новое событие возникает не позднее, чем через интервал времени, заданный в свойстве Interval.
Если задать значение свойства Interval=0илиEnabled=false, то таймер перестанет работать. Чтобы заново запустить отсчет времени, надо либо задатьEnabled=true, либо присвоить свойствуIntervalположительное значение.
Таймер точно выдерживает заданный интервал, если он достаточно велик – сотни и тысячи миллисекунд. Если задавать короткие интервалы (примерно по 10 мс), то реальные интервалы времени оказываются заметно больше вследствие различных накладных расходов, связанных с вызовом функций или иными вычислительными аспектами.
Основные методы компонента – Start()иStop(), которые запускают и останавливают таймер. Кроме того, включение и выключение таймера по нажатию на кнопку можно реализовать с помощью следующей строки, записанной в обработчике событияClick:
Timer1->Enabled=!Timer1->Enabled;
Для того чтобы обеспечить работу таймера, необходимо действия, выполняемые при каждом срабатывании таймера, поместить в обработчик события Tick.
Пример.Рассмотрим работу с таймером на примере создания приложения «Часы». На форме этого приложения нарисованы часы с часовой, минутной и секундной стрелками. Часы показывают текущее время. На создаваемой форме не будет ни одного компонента. Вся информация будет создана динамически.
В секции privateобъявим следующиепеременные:
Graphics ^g;- графическая поверхность, на которой будет сформирован рисунок;
int R – радиус циферблата;
int x0, y0– центр циферблата;
int ahr, amin, asec– углы, под которыми находятся стрелки.
В первых строчках файла подключим модули с математическими функциями и определим константу RAD, используемую при переводе градусов в радианы:
#define _USE_MATH_DEFINES
#include <cmath>
#define RAD 0.0174532
В конструкторе класса Formвыполним следующие действия.
Определим положение стрелок. Известно, что угол между метками часов (цифрами) – 30 градусов, а угол между метками минут – 6 градусов. Угол отсчитывается от положения 12 часов.
ahr=90-DateTime::Now.Hour*30-(DateTime::Now.Minute/12)*6;
amin=90- DateTime::Now.Minute*6;
asec=90- DateTime::Now.Second*6;
Установим период получения сигнала от таймера в 1 с:
Timer1->Interval=1000;
И выполним пуск таймера:
Timer1->Enabled=true;
При каждой перерисовке формы необходимо наносить на ее поверхность изображение циферблата. Это будет осуществляться с помощью события Paint.
Объявим следующие переменные.
int x,y; - координаты маркера на циферблате.
int a=0; - угол между осью ОХ и прямой (x0,y0)(x,y)
int h=3; - метка часовой стрелки, угол в 0 градусов соответствует 3 часам.
g=this->CreateGraphics();- определим графическую поверхность.
Определим радиус циферблата равным половине величины наименьшего из измерений форм минус 50 пикселей для полей.
if (this->ClientSize.Width < this->ClientSize.Height)
R= (this->ClientSize.Width/2)-50;
else
R= (this->ClientSize.Height/2)-50;
Установим положение центра циферблата:
x0= this->ClientSize.Width/2;
y0= this->ClientSize.Height/2;
С помощью следующего цикла выполним рисование циферблата. Тут поочередно рассчитываются положения точек на циферблате и в зависимости от значения угла выводится окружность разного радиуса и соответствующая цифра (если необходимо).
while (a<360){
x=x0+R*cos(a*RAD);
y=y0+R*sin(a*RAD);
if ((a%30)==0){
g->DrawEllipse(Pens::Black,x-2,y-2,3,3);
x=x0+(R+15)*cos(a*RAD);
y=y0-(R+15)*sin(a*RAD);
g->DrawString(h.ToString(),this->Font,Brushes::Red,x-5,y-7);
h--;
if (h==0) h=12;
} else
g->DrawEllipse(Pens::Black,x-1,y-1,1,1);
a+=6;
}
Далее остается только нарисовать стрелки с помощью функции DrawClock();.
Эта же функция будет вызываться и каждый раз при срабатывании таймера (обработчик события Tick).
Прежде, чем рассмотреть эту функцию, приведем функцию
void Vector(float x0, float y0, float a, float l, System::Drawing::Pen ^aPen)
С ее помощью мы будем рисовать стрелки. В качестве параметров передадим центр циферблата, угол, под которым располагается стрелка, длину стрелки и цвет ручки, которой эта стрелка будет нарисована.
Функция определяет координаты конца вектора
float x,y;
x=x0+l*cos(a*RAD);
y=y0+l*sin(a*RAD);
И рисует прямую, начинающуюся в точке (x0,y0) и заканчивающуюся в точке (x,y).
g->DrawLine(aPen,x0,y0,x,y);
Перейдем теперь к функции DrawClock. Она возвращаетvoidи не имеет параметров. В этой функции устанавливаются параметры пера для рисования часовой, минутной и секундной стрелок (первые две стрелки имеют ширину 3 пикселя, последняя – 2), а также сохраняется цвет фона (перо этого цвета имеет ширину 4 пикселя). Он необходим для того, чтобы затереть предыдущее положение стрелок.
Pen ^hPen=gcnew Pen(Color::LightBlue,3);
Pen ^mPen=gcnew Pen(Color::LightPink,3);
Pen ^sPen=gcnew Pen(Color::Brown,2);
Pen ^cPen=gcnew Pen(SystemColors::Control,4);
//стереть изображение стрелок
Vector (x0,y0,-ahr,R-20,cPen);
Vector (x0,y0,-amin,R-15,cPen);
Vector (x0,y0,-asec,R-7,cPen);
Далее рассчитываются новые координаты всех трех стрелок и выполняется их рисование на новых позициях. Функция завершается рисованием эллипса диаметром 6 пикселей – точки крепления стрелок.
//новое положение стрелок
ahr=90-DateTime::Now.Hour*30-(DateTime::Now.Minute/12)*6;
amin=90-DateTime::Now.Minute*6;
asec=90-DateTime::Now.Second*6;
//Нарисовать стрелки заново
Vector (x0,y0,-ahr, R-20,hPen);
Vector (x0,y0,-amin,R-15,mPen);
Vector (x0,y0,-asec,R-7, sPen);
g->FillEllipse(Brushes::Black,x0-3,y0-3,6,6);
Последний штрих – событие Resizeдля формы, необходимое для масштабирования циферблата. Эта функция содержит единственную строку:
this->Refresh();
Аналогичным образом можно формировать и другие объекты с использованием динамической графики. Для этого целесообразно пользоваться следующим алгоритмом при написании функции прорисовки.
Шаг 1. Закрасить текущий объект цветом фона.
Шаг 2. Определить новое положение объекта.
Шаг 3.Выполнить рисование объекта на новом месте.
Данные три шага повторяются при каждом срабатывании таймера.