Программа «часы-будильник- календарь»

1. Создайте новый проект Borland C++ Builder.

2. Задайте в инспекторе объектов значения свойств главной формы следующим образом:

BorderIcons – biMaximize – false (чтобы пользователь не мог развернуть окно программы на весь экран), BorderStyle – bsSingle (чтобы пользователь не мог растянуть границы окна мышью), Caption – Часы-календарь, Name – MainForm, Position – poDesktopCenter (чтобы окно программы при запуске располагалось в центре рабочего стола), ShowHint – true (чтобы у всех компонентов формы свойство показа подсказок также было true).

3. Поместите на форму компонент GroupBox (вкладка панели инструментов Standard). Подкорректируйте его размеры так, чтобы он занимал чуть меньше половины ширины формы. Задайте следующие значения его свойств в инспекторе объектов:

Caption – Текущее время:, Font – Style – fsBold (жирный шрифт), Name – TimeBox.

4. Выделите TimeBox на форме и поместите в него Panel (вкладка Standard). Её свойство Caption послужит нам для вывода текущего времени. Откорректируйте размеры панели так, чтобы она размещалась в центре TimeBox. Задайте следующие значения свойств панели в инспекторе объектов:

AutoSize – false, BevelInner – bvLowered, очистите значение свойства Caption, щёлкните по кнопке с многоточием рядом с полем свойства Font, чтобы задать значения свойств шрифта: размер – 24, жирный, Name – TimePanel.

5. Выделите наш TimeBox и нажмите клавиши Ctrl+C, чтобы скопировать его в буфер обмена. После этого нажмите клавиши Ctrl+V, чтобы добавить на форму ещё один GroupBox с содержащейся в нём панелью. Заметим, что в новых компонентах все внесённые нами изменения свойств сохранились (кроме, естественно, имени – Name, т.к. в программе не может быть двух переменных с одинаковым именем). Замечу, что способ копировать – вставить очень удобен при создании нескольких объектов с одинаковыми свойствами (например, группы кнопок). Только стоит помнить, что этим приёмом можно пользоваться лишь на этапе проектирования: нельзя копировать кнопки (и вообще компоненты) с уже написанными обработчиками событий, т.к. попытки последние изменить приведут к неработоспособности программы.

6. Перетащите новый GroupBox с содержащейся в нём панелью под TimeBox. Задайте следующие значения свойств GroupBox:

Caption – Время оповещения:, Name – AlarmBox.

Переименуйте содержащуюся в нём панель (изменив свойство Name) в AlarmPanel.

7. Теперь можно приступать к выводу на панель TimePanel текущего времени. Для этого нам понадобится компонент Timer (вкладка System). Задайте его имя (Name) как Timer, остальные свойства оставьте по умолчанию. Таймер позволяет нам генерировать событие OnTimer с частотой, определяемой его свойством Interval. По умолчанию оно равно 1000 миллисекунд (или одной секунде). Это нас вполне устроит. Когда мы вызываем обработчик события OnTimer, происходит сброс таймера и отсчёт промежутка времени, определённого свойством Interval, начинается снова. В качестве обработчика события у нас выступит вывод текущего времени на панель с использованием ей свойства Caption.

8. Чтобы получить текущее время, в среде C++ Builder имеется функция Time(); для получения – текущей даты – Date(). Обе эти функции возвращают значение типа TDateTime. Рассмотрим его подробнее. Этот тип представляет собой число с плавающей точкой, целая часть которого содержит число дней, отсчитанных от 0 часов 30 декабря 1899 года, а дробная часть равна части 24-часового дня, отсчитанная от полудня (12 часов). Т.е. дробная часть характеризует время и не относится к дате. Подобный способ представления данных не слишком-то удобен для практического использования, поэтому в среде C++ Builder имеется ряд функций для преобразования типа TDateTime в более удобоваримую форму – строку (AnsiString). Функция DateToStr() выводит в строку дату, TimeToStr() – время, а DateTimeToStr() – дату и время, причём форма представления данных определяется установкой глобальных переменных (зависит от настроек Вашей операционной системы). Для более гибкого представления данных существуют другие способы, которые мы рассмотрим ниже. Пока же внесём строчку в обработчик события OnTimer нашего таймера:

void __fastcall TMainForm::TimerTimer(TObject *Sender)

{

TimePanel->Caption=TimeToStr(Time());

}

Мы преобразовали текущее время, полученное функцией Time() в строку и присвоили её свойству Caption панели. Поскольку подобное присваивание будет происходить каждую секунду по событию OnTimer, мы получили простейшие электронные часы.

9. Теперь пришла пора подумать о будильнике. Что нам понадобится для этого? Во-первых, какой-нибудь объект, в котором мы будем задавать значение времени «побудки» (оповещения), медиаплейер для воспроизведения мелодии оповещения, 2 кнопки для задания времени и отмены и диалог открытия файла для выбора музыкального файла.

Помимо этого, нам нужны переменные для хранения следующих значений: информации о том, включён или выключен будильник (т.е. тип bool), переменная для хранения текущего часа, переменная для хранения текущих минут, переменная для хранения часа оповещения и переменная для хранения минуты оповещения (все типа int). Перейдите в редактор кода и нажмите клавиши Ctrl+F6. Откроется вкладка с исходным текстом заголовочного файла главной формы (MainUnit.h). В раздел private класса главной формы добавьте следующие переменные:

bool bIsTimerOn; // Таймер включён?

int iHours; // Текущий час.

int iMinutes; // Текущая минута.

int iAlarmHours; // Час оповещения.

int iAlarmMinutes; // Минута оповещения.

Полученное время ещё предстоит преобразовать.

Но вначале нам это время следует задать. Сделаем мы это с использованием компонента DateTimePicker, расположенного на вкладке Win32 палитры компонентов. Компонент может работать в двух режимах, определяемых свойством Kind: ввода времени (значение dtkTime) и ввода даты (dtkDate). Сейчас нам нужно именно первое значение. Поместите на AlarmPanel компонент DateTimePicker и откорректируйте его размеры так, чтобы он красиво располагался в центре панели. Задайте следующие значения его свойств в инспекторе объектов:

Hint – Установите в таймере время для оповещения, Kind – dtkTime, Name – TimePicker, очистите значение свойства Time (оно автоматически установится в 0:00:00.

Поместим на форму также 2 кнопки типа TButton с вкладки Standard. Свойства первой кнопки зададим такими:

Caption – Задать, Hint – Задать время оповещения, установленное в таймере, Name – AlarmBttn.

У второй кнопки:

Caption – Отменить,

Hint – Отменить оповещение,

Name – CancelAlarmBttn.

Также на форму поместим компонент MediaPlayer с вкладки System и OpenDialog с вкладки Dialogs.

Значения свойств медиаплейера зададим следующими:

AutoEnable – true, AutoOpen – false (открывать музыкальный файл будем сами), DeviceType – dtAutoSelect (плейер автоматически определяет тип устройства для воспроизведения), установите в false свойства EnabledButtons и VisibleButtons для кнопок btNext, btPrev, btStep, btBack, btRecord (они нам не понадобятся), Name – MediaPlayer.

Проделаем эту манипуляцию и с объектом типа TOpenDialog:

DefaultExt - *.mp3 (расширение по умолчанию - *.mp3), Filter – Все поддерживаемые типы / *.mp3; *.wav; *.mid; *.rmi, Name – AlarmOpenDialog, Options – установите в true ofExtensionDifferent, ofPathMustExist, ofFileMustExist, Title – открыть мелодию для оповещения.

10. Напишем обработчик события главной формы OnActivate, в котором переменной bIsTimerOn присвоим значение false. Это наш флаг для таймера, что будильник выключен (bIsTimerOn=false; // Будильник выключен).

Разумеется, мы могли бы для этого воспользоваться вторым таймером (их на форме может быть несколько), но зачем объявлять объект, когда можно обойтись одной переменной!

Пользователь задаёт время для оповещения, выбирает мелодию звонка и подтверждает операцию. Время пользователь будет выбирать в компоненте TimePicker, о чём его и предупреждает подсказка, а 2 другие операции можно реализовать в обработчике события OnClick кнопки AlarmBttn:

void __fastcall TMainForm::AlarmBttnClick(TObject *Sender)

{

do

{

if(AlarmOpenDialog->Execute()) //Если диалог открытия запущен…

{

MediaPlayer->FileName=AlarmOpenDialog->FileName;

//выберем файл для воспроизведения медиаплейером.

}

if(MediaPlayer->FileName=="")

Application-> MessageBox("Вы должны выбрать мелодию для оповещения!", "Будильник", MB_OK+MB_ICONWARNING);

}

while(MediaPlayer->FileName=="");

iAlarmHours=StrToInt(FormatDateTime("h", TimePicker->Time));

iAlarmMinutes=StrToInt(FormatDateTime("n", TimePicker->Time));

MediaPlayer->Open();

bIsTimerOn=true; // Таймер будильника запущен

}

iAlarmHours=StrToInt(FormatDateTime("h", TimePicker->Time));

iAlarmMinutes=StrToInt(FormatDateTime("n", TimePicker->Time));

11. Теперь нагрузим работой наш таймер, которому каждую секунду (если, конечно запущен будильник bIsTimerOn=true;), помимо отрисовки текущего времени, предстоит сравнивать его с заданным, чтобы решить, не пора ли включить музыку:

void __fastcall TMainForm::TimerTimer(TObject *Sender)

{

TimePanel->Caption=TimeToStr(Time());

if(bIsTimerOn==true) // Если будильник включён…

{

iHours=StrToInt(FormatDateTime("h", Time()));

iMinutes=StrToInt(FormatDateTime("n", Time()));

// …получим текущее время…

if((iHours==iAlarmHours) && (iMinutes>=iAlarmMinutes))

// …и если оно совпало с заданным пользователем…

{

MediaPlayer->Play(); // …играем!

}

if(MediaPlayer->Mode==mpPlaying) bIsTimerOn=false;

// Если медиаплейер уже играет, то будильник можно выключить. Будильник готов.

}}

Возможность пользователю отменить действие, если он по каким-либо причинам передумал побудку.

void __fastcall TMainForm::CancelAlarmBttnClick(TObject *Sender)

{

bIsTimerOn=false;
if(MediaPlayer->Mode==mpPlaying) MediaPlayer->Stop();

TimePicker->Time=StrToTime("0:00:00"); // Сброс на ноль.

}

12. Создание календаря. Для этого можно воспользоваться в принципе уже известным нам компонентом DateTimePicker. Но мы возьмём компонент с той же вкладки – MonthCalendar, похожий на DateTimePicker в режиме ввода дат. Для того, чтобы компонент выглядел несколько «притопленным» на форме, воспользуемся квадратом Bevel с вкладки Additional. Установим значения его свойств следующим образом:

Height – 156 (чтобы в него поместился календарь), Name – MonthBevel, Width – 193. Теперь в квадрате можно разместить наш календарик и заняться изменением его свойств:

Name – MonthCalendar, ShowToday – true, ShowTodayCircle – true (для того, чтобы текущая дата на календаре выделялась и обводилась кружочком.

void __fastcall TMainForm::FormActivate(TObject *Sender)

{bIsTimerOn=false; // Будильник выключен.

MonthCalendar->Date=Date(); // В календаре – текущая дата.

DayOfWeekLabel->Caption=FormatDateTime("День недели - dddd", Date());

// Текущий день недели.

}

После 0 часов значение DayOfWeekLabel->Caption перестанет соответствовать действительности! Поэтому необходимо ввести проверку дня недели на валидность, внеся строчку отображения дня недели (и, кстати, присвоения даты компоненту MonthCalendar) в событие OnTimer:

void __fastcall TMainForm::TimerTimer(TObject *Sender)

{

TimePanel->Caption=TimeToStr(Time());

DayOfWeekLabel->Caption=FormatDateTime("День недели - dddd", Date());

MonthCalendar->Date=Date(); // В календаре – текущая дата.

}

Контрольные вопросы

  1. Каково назначение компонента DateTimePicker?
  2. Можно ли в компоненте DateTimePicker выбрать диапазон дат?
  3. Как в компоненте DateTimePicker показать текущую дату красным цветом?
  4. Как получить прграммно текущий день с помощью компонента DateTimePicker?
  5. В какое свойство компонента DateTimePicker помещается выбранная дата?
  6. Каково назначение компонента CCalendar?
  7. С помощью какой функции можно получить текущую дату?
  8. Какая функция переводит в строку дату?

Практическая работа №14

Тема: «Разработка приложения, с использованием управляющих кнопок, радиокнопок, индикаторов».

Цель работы: Ознакомление с основными принципами программирования работы управляющих кнопок, радиокнопок, индикаторов в C++ Builder.

Время выполнения: подготовка – 5 мин; выполнение – 165 мин.; проверка – 10 мин; всего – 180 мин.

Теоретическая часть

Наши рекомендации