Программирование с C++ Builder

         

в среде Windows, являются мультимедийными.



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

C++ Builder предоставляет в распоряжение программиста два компонента, которые позволяют разрабатывать мультимедийные программы:
 Animate — обеспечивает вывод простой, не сопровождаемой звуком анимации;  MediaPlayer — позволяет решать более сложные задачи, например воспроизводить видеоролики, звук и сопровождаемую звуком анимацию.
Содержание

Компонент Animate



Компонент Animate, значок которого находится на вкладке Win32 (рис. 4.1), позволяет воспроизводить простую, не сопровождаемую звуком анимацию, кадры которой находятся в AVI-файле.



Рис. 4.1. Значок компонента Animate


Компонент Animate добавляется к форме обычным образом. После того как компонент будет добавлен к форме, следует выполнить его настройку — установить значения свойств. Свойства компонента Animate перечислены в табл. 4.1.

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

Свойство
Описание
Name
Имя компонента. Используется для доступа к свойствам компонента и для управления его поведением
FileName
Имя AVI-файла, в котором находится анимация, отображаемая при помощи компонента
FrameWidth
Ширина кадров анимации
FrameHeight
Высота кадров анимации
FrameCount
Количество кадров анимации
AutoSize
Признак автоматического изменения размера компонента в соответствии с размером кадров анимации
Cente-r
Признак центрирования кадров анимации в поле компонента. Если значение свойства равно true и размер компонента больше размера кадров (AutoSize = false), кадры анимации располагаются в центре поля компонента
StartFrame
Номер кадра, с которого начинается отображение анимации
StopFrame
Номер кадра, на котором заканчивается отображение анимации
Active
Признак активизации процесса отображения анимации
Color
Цвет фона компонента (цвет "экрана"), на котором воспроизводится анимация
Transparent
Режим использования "прозрачного" цвета при отображении анимации
Repetitions
Количество повторов отображения анимации
CommonAVI
Определяет стандартную анимацию Windows (см. табл. 4.2)


Компонент Animate позволяет программисту использовать в своих программах стандартные анимации Windows. Вид анимации определяется значением свойства CommonAVI. Значение свойства задается при помощи именованной константы. В табл. 4.2 приведены некоторые константы, вид анимации и описание процессов, для иллюстрации которых используются эти анимации.

Таблица 4.2. Значение свойства conwonAVI определяет анимацию

Значение
Анимация
Процесс
aviCopyFiles
Копирование файлов
aviDeleteFile
Удаление файла
aviRecycleFile
Удаление файла в корзину


Следует еще раз обратить внимание, что компонент Animate предназначен для воспроизведения AVI-файлов, которые содержат только анимацию. При попытке записать в свойство FileName имя файла, в котором находится сопровождаемая звуком анимация, возникает исключение и C++ Builder выводит сообщение об ошибке Cannot open AVI.

Следующая программа (вид ее диалогового окна приведен на рис. 4.2, а текст— в листинге 4.1) демонстрирует использование компонента Animate для просмотра анимации.



Рис. 4.2. Форма программы "Просмотр анимации"


После запуска программы в форме будет выведен первый кадр анимации, которая находится в каталоге проекта. Если ни одного файла с расширением avi в каталоге проекта нет, то поле компонента Animate останется пустым.

Имя файла, в котором находится анимация, можно ввести в поле Edit1 или выбрать в стандартном диалоговом окне Открыть файл, которое становится доступным в результате щелчка на кнопке Выбрать. Доступ к стандартному диалоговому окну Открыть файл обеспечивает компонент opendialog1. Значок компонента opendialog находится на вкладке Dialogs.

Программа "Просмотр анимации" обеспечивает два режима просмотра: непрерывный и по кадрам. Кнопка Button1 используется как для инициализации процесса воспроизведения анимации, так и для его приостановки. Процесс непрерывного воспроизведения анимации инициирует процедура обработки события onclick на кнопке Пуск, которая присваивает значение true свойству Active. Эта же процедура заменяет текст на кнопке Button1 с "Пуск" на "Стоп". Режим воспроизведения анимации выбирается при помощи переключателей RadioButton1 и RadioButton2. Процедуры обработки события Onclick на этих переключателях изменением значения свойства Enabled блокируют или, наоборот, делают доступными кнопки управления: активизации воспроизведения анимации (Buttoni), перехода к следующему (Button2) и предыдущему (Buttons) кадру. Во время непрерывного воспроизведения анимации процедура обработки события onckick на кнопке Стоп (Buttoni) присваивает значение false свойству Active и тем самым останавливает процесс воспроизведения анимации.

Листинг 4.1. Использование компонента Animate

// обработка события OnCreate
void__fastcall TForml::FormCreate(TObject *Sender)
{
TSearchRec sr; // содержит информацию
//о файле, найденном функцией FindFirst
// найдем AVI-файл в текущем каталоге
if (FindFirst("*.avi",faAnyFile, sr) == 0)
 {
Editl->Text = sr.Name;
/* если анимация содержит звук, то при
выполнении следующего оператора произойдет
ошибка, т. к. компонент Animate обеспечивает
воспроизведение только простой,
не сопровождаемой звуком анимации */
try
{
Animatel->FileName = sr.Name;
}
catch (Exception &e)
 {
return;
}
RadioButtonl->Enabled = true;
RadioButton2->Enabled = true;
Buttonl->Enabled = true; } }
// щелчок на кнопке Выбрать
void __fastcall TForml::Button4Click(TObject *Sender)
{
OpenDialogl->InitialDir = "";
 // открыть каталог, из которого
// запущена программа
OpenDialogl->FileName = "*.avi";
// вывести список AVI-файлов
if ( OpenDialogl->Execute()) {
// пользователь выбрал файл и нажал кнопку Открыть
// Компонент Animate может отображать только простую,
// не сопровождаемую звуком анимацию. Поэтому
// при выполнении следующей инструкции возможна ошибка
try
{
Animatel->FileName = OpenDialogl->FileName;
}
catch (Exception &e)
 {
Editl-XText = "";
// сделаем недоступными кнопки управления
RadioButtonl->Enabled = false;
RadioButton2->Enabled = false;
Buttonl->Enabled = false;
Button2->Enabled = false;
Button3->Enabled = false;
// сообщение об ошибке AnsiString msg =
"Ошибка открытия файла " +
OpenDialogl->FileName +
"ХпВозможно анимация сопровождается звуком.";
ShowMessage(msg); return;
}
Editl-XText = OpenDialogl->FileName;
// отобразить имя файла
RadioButtonl->Checked = true;
// режим просмотра — непрерывно
Buttonl->Enabled = true;
// кнопка Пуск доступна Button2->Enabled = false;
// кнопка Предыдущий кадр недоступна
Button3->Enabled = false;
// кнопка Следующий кадр недоступна
RadioButtonl->Enabled = true;
 RadioButton2->Enabled = true;
}
}
// щелчок на кнопке Пуск/Стоп
void__fastcall TForml::ButtonlClick(TObject *Sender)
{
if (Animatel->Active)
{
// анимация отображается, щелчок на кнопке Стоп
Animatel->Active = false; Buttonl->
Caption = "Пуск";
RadioButton2->Enabled = true;
}
else // щелчок на кнопке Пуск
(
// активизировать отображение анимации
Animatel->StartFrame = 1;
// с первого кадра
Animatel->StopFrame = Animatel->FrameCount;
// по последний кадр
Animatel->Active = true;
Buttonl->Caption = "Стоп";
RadioButton2->Enabled = false;
}
}
// выбор режима просмотра всей анимации
void __fastcall TForml::RadioButtonlClick(TObject *Sender)
{
Buttonl->Enabled = true; // кнопка Пуск/Стоп доступна
// сделать недоступными кнопки режима просмотра по кадрам
Button2->Enabled = false;
Button3->Enabled = false;
Animatel->Active = false; }
// выбор режима просмотра по кадрам
void __fastcall TForml::RadioButton2Click(TObject *Sender)
{
Buttonl->Enabled = false; // кнопка Пуск/Стоп недоступна
Button2->Enabled = true; // кнопка Следующий кадр доступна
Button3->Enabled = false; // кнопка Предыдущий кадр недоступна
// отобразить первый кадр
Animatel->StartFrame =1;
Animatel->StopFrame = 1;
Animatel->Active = true;
CFrame =1; // запомним номер отображаемого кадра
 }
// щелчок на кнопке Следующий кадр
void__fastcall TForml::Button2Click(TObject *Sender)
{
CFrame++;
// отобразить кадр
Animatel->StartFrame = CFrame;
Animatel->StopFrame = CFrame;
Animatel->Active = true;
if (CFrame > 1)
Button3->Enabled = true;
if (CFrame == Animatel->FrameCount)
// отобразили последний кадр
Button2->Enabled = false;
// кнопка Следующий кадр недоступна }
// щелчок на кнопке Предыдущий кадр
void__fastcall TForml::Button3Click(TObject *Sender)
{
if (CFrame == Animatel->FrameCount)
 // последний кадр Button2->Enabled = true;
CFrame—;
// отобразить кадр
Animatel->StartFrame = CFrame;
Animatel->StopFrame = CFrame;
Animatel->Active = true;
if (CFrame == 1)
Button3->Enabled = false;
// кнопка Следующий кадр недоступна
}

Компонент MediaPlayer



Компонент MediaPlayer обеспечивает воспроизведение звуковых файлов различных форматов (WAV, MID, RMI, МРЗ), полноценной, сопровождаемой звуком анимации и видеороликов (AVI) и музыкальных компакт-дисков.

Значок компонента MediaPlayer находится на вкладке System (рис. 4.3).



Рис. 4.3. Значок компонента MediaPlayer


Компонент MediaPlayer представляет собой группу кнопок (рис. 4.4), подобных тем, какие можно видеть на обычном аудио- или видеоплеере. Назначение этих кнопок пояснено в табл. 4.3. Свойства компонента MediaPlayer, доступные во время разработки формы, приведены в табл. 4.4.



Рис. 4.4. Компонент MediaPlayer


Таблица 4.3. Кнопки компонента MediaPlayer

Кнопка
Обозначение
Действие
Воспроизведение
btPlay
Воспроизведение звука или видео
Пауза
btPause
Приостановка воспроизведения
Стоп
btStop
Остановка воспроизведения
Следующий
btNext
Переход к следующему кадру
Предыдущий
btPrev
Переход к предыдущему кадру
Шаг
btStep
Переход к следующему звуковому фрагменту, например, к следующей песне на CD
Назад
btBack
Переход к предыдущему звуковому фрагменту, например, к предыдущей песне на CD
Запись
btRecord
Активизирует процесс записи
Открыть
btEject
Открывает CD-дисковод компьютера


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

Свойство
Описание
Name
Имя компонента. Используется для доступа к свойствам компонента и для управления работой плеера
DeviceType
Тип устройства. Определяет конкретное устройство, которое представляет собой компонент MediaPlayer. Тип устройства задается именованной константой: dtAutoSelect — тип устройства определяется автоматически по расширению файла; dtVaweAudio — проигрыватель звука; dtAVlvideo— видеопроигрыватель; dtCDAudio — CD-проигрыватель
FileName
Имя файла, в котором находится воспроизводимый звуковой фрагмент или видеоролик
AutoOpen
Признак автоматической загрузки сразу после запуска программы, файла видеоролика или звукового фрагмента
Display
Определяет компонент, поверхность которого используется в качестве экрана для воспроизведения видеоролика (обычно в качестве экрана для отображения видео используют компонент Panel)
VisibleButtons
Составное свойство. Определяет видимые кнопки компонента. Позволяет сделать невидимыми некоторые кнопки


Помимо свойств, доступных в процессе разработки формы, компонент MediaPlayer предоставляет свойства, доступные во время работы программы (табл. 4.5), которые позволяют получить информацию о состоянии медиаплеера, воспроизводимом файле или треке Audio CD. Следует обратить внимание, что значения свойств, содержащих информацию о длительности, могут быть представлены в различных форматах. Наиболее универсальным форматом является формат tfMiiliseconds, в котором длительность выражается в миллисекундах. Некоторые устройства поддерживают несколько форматов. Например, если MediaPlayer используется для воспроизведения Audio CD, то информация о воспроизводимом треке может быть представлена в формате tfTMSF (Track, Minute, Second, Frame — трек, минута, секунда, кадр). Для преобразования миллисекунд в минуты и секунды надо воспользоваться известными соотношениями. Если значение свойства представлено в формате tfTMSF, то для преобразования можно воспользоваться макросами MCI_TMSF_TRACK, MCI_TMSF_SECOND и MCI_TMSF_ MINUTE. Объявление этих и других полезных макросов можно найти в файле mmsystem.h.

Таблица 4.5. Свойства компонента MediaPlayer, доступные во время работы программы

Свойство
Описание
Length
Длина (время, необходимое для воспроизведения) открытого файла (например, WAV или AVI) или всех треков Audio CD
Tracks
Количество треков на открытом устройстве (количество композиций на Audio CD)
TrackLength
Длина (длительность) треков. Свойство представляет собой массив
Position
Позиция (время от начала) в процессе воспроизведения трека
TimeFormat
Формат представления значений свойств Length, TrackLength и Position. Наиболее универсальным является формат tfMilliseconds. Если медиаплеер представляет собой проигрыватель звуковых CD, то удобно использовать формат tfTMSF
Mode
Состояние устройства воспроизведения. Устройство может находиться в состоянии воспроизведения (mpPlaying). Процесс воспроизведения может быть остановлен (mpStopped) или приостановлен (mpPaused). Устройство может быть не готово к работе (mpNotReady) или в устройстве (CD-дисководе) может отсутствовать носитель (mpOpen)
Display
Экран — поверхность, на которой осуществляется отображение клипа. Если значение свойства не задано, то отображение осуществляется в отдельном, создаваемом во время работы программы окне
DisplayRect
Размер и положение области отображения клипа на поверхности экрана


Компонент MediaPlayer предоставляет методы (табл. 4.6), используя которые можно управлять работой медиаплеера из программы так, как будто это делает пользователь.

Таблица 4.6. Методы компонента MediaPlayer

Метод
Действие
Play()
Активизирует процесс воспроизведения. Действие метода аналогично щелчку на кнопке Play
Stop ( )
Останавливает процесс воспроизведения
Pause ( )
Приостанавливает процесс воспроизведения
Next ( )
Переход к следующему треку, например к следующей композиции на Audio CD
Previous ( )
Переход к предыдущему треку, например к следующей композиции на Audio CD
Step ( )
Переход к следующему кадру
Back ( )
Переход к предыдущему кадру

Воспроизведение звука



В качестве примера использования компонента MediaPiayer для воспроизведения звука рассмотрим программу, используя которую, можно прослушать звуковые фрагменты, сопровождающие события Windows — такие, как начало и завершение работы, появление диалогового окна и др. Форма и диалоговое окно программы "Звуки Windows" представлены на рис. 4.5, текст — в листинге 4.2, а значения свойств компонента MediaPiayer1 — в табл. 4.7.



Рис. 4.5. Форма и диалоговое окно программы "Звуки Windows"


Таблица 4.7. Значения свойств компонента MediaPlayer1

Компонент
Значение
DeviceType
dtAutoSelect
VisibleButtons .btNext
false
VisibleButtons . BtPrev
false
VisibleButtons .btStep
false
VisibleButtons. btBack
false
VisibleButtons .btRecord
false
VisibleButtons. btEject
false


Помимо компонента MediaPlayer на форме находится компонент ListBox, который используется для выбора звукового файла, и два компонента Labe1, первый из которых используется для вывода информационного сообщения, второй — для отображения имени файла, выбранного пользователем.

 Листинг 4.2. Использование компонента MediaPlayer для воспроизведения звука

void __fastcall TForml::FormCreate(TObject *Sender)
{
char *wd; // каталог Windows
wd = (char*)AllocMem(MAX_PATH);
GetWindowsDirectory(wd,MAX_PATH);
SoundPath = wd;
// звуковые файлы находятся в подкаталоге Media
SoundPath = SoundPath + "\\Media\\";
// сформируем список звуковых файлов
TSearchRec sr;
if (FindFirst( SoundPath + "*.wav", faAnyFile, sr) == 0)
{
// найден файл с расширением wav
ListBoxl->Items->Add(sr.Name);
// добавим имя файла в список
// еще есть файлы с расширением wav?
while (FindNext(sr) == 0)
ListBoxl->Items->Add(sr.Name);
}
if (FindFirst( SoundPath + "*.mid", faAnyFile, sr) == 0) {
// найден файл с расширением mid
ListBoxl->Items->Add(sr.Name);
// добавим имя файла в список
// еще есть файлы с расширением mid?
while (FindNext(sr} = 0)
ListBoxl->Items->Add(sr.Name); }
if (FindFirstf SoundPath + "*.rmi", faAnyFile, sr) == 0) {
// найден файл с расширением rmi
ListBoxl->Items->Add(sr.Name);
// добавим имя файла в список
// еще есть файлы с расширением rmi?
while (FindNext(sr) == 0)
ListBoxl->Items->Add(sr.Name); }
// воспроизвести первый файл
if ( ListBoxl->Items->Count != 0)
{
Label2->Caption = ListBoxl->Items->Strings[1];
MediaPlayerl->FileName = SoundPath + ListBoxl->Items->Strings[l];
MediaPlayerl->Open();
MediaPlayerl->Play(); 
}
 }
// щелчок на элементе списка
void__fastoall TForml::ListBoxlClick(TObject *Sender)
{
Label2->Caption = ListBoxl->Items->Strings[ListBoxl->ItemIndex];
MediaPlayerl->FileName = SoundPath + Label2->Caption;
MediaPlayerl->Open();
MediaPlayerl->Play() ;
 } 

Работает программа следующим образом. Сразу после запуска функция обработки события onCreate формирует список звуковых файлов (WAV, MID и RMI), которые находятся в подкаталоге Media главного каталога Windows. Так как на разных компьютерах каталог, в который установлена операционная система, может называться по-разному, то для получения его имени используется API функция GetwindowsDirectory, значением которой является полное имя каталога Windows. Список звуковых файлов формируется

При помощи функций FindFirst и FindNext. функция FindFirst обеспечивает поиск файла, удовлетворяющего критерию поиска, указанному при вызове функции. Функция FindNext продолжает процесс поиска. Обеим функциям в качестве параметра передается структура типа TSearchRec, поле Name которой (в случае успеха) содержит имя файла, удовлетворяющего критерию поиска. После того как список звуковых файлов сформирован, применением метода Play активизируется процесс воспроизведения первого файла.

Щелчок на элементе списка обрабатывается функцией TFom1: :ListBox1Click, которая присваивает значение свойству FileName компонента MediaPiayer1, при помощи метода open открывает выбранный файл и применением метода Play активизирует процесс воспроизведения.

Следующий пример показывает, как на основе компонента MediaPiayer можно создать вполне приличный проигрыватель компакт-дисков. Вид формы и диалогового окна программы приведен на рис. 4.6. Помимо компонентов, показанных на рисунке, в форме есть компонент MediaPiayer. Так как кнопки компонента MediaPiayer во время работы программы не используются (для управления плеером служат кнопки Button1, Button2 и Buttons), свойству visible присвоено значение false, а сам компонент находится за границей формы.



Рис. 4.6. Форма программы CD Player


Значки на кнопках управления — это текст, изображенный шрифтом Webdings. При использовании этого шрифта, например, цифре 4 соответствует значок Play. Соответствие значков Webdings и обычных символов отражает табл. 4.8.

Таблица 4.8. Изображение символов шрифта Webdings

Символ Webdings
Обычный символ — например, шрифт Arial
Код символа (шестнадцатеричный)

9
39

4
34

:

<


Компонент Timer используется для организации цикла опроса состояния медиаплеера. Во время воспроизведения CD функция обработки события OnTimer выводит на индикатор (в поле метки Label1) номер трека и время воспроизведения.

Вид окна программы сразу после ее запуска в случае, если в CD-дисководе находится Audio CD, приведен на рис. 4.7. В случае, если в CD-дисководе диска нет или диск не звуковой, вместо информации о времени воспроизведения будет выведено сообщение "Вставьте Audio CD". Щелчок на кнопке Play (Button1) активизирует процесс воспроизведения. Во время воспроизведения на индикаторе отражается номер и длительность воспроизводимого трека, а также время от начала воспроизведения (рис. 4.8).



Рис. 4.7. В начале работы на индикаторе выводится информация о времени воспроизведения CD или сообщение о необходимости вставить в дисковод Audio CD



Рис. 4.8. Во время воспроизведения на индикаторе отображается информация о воспроизводимом треке


Текст программы приведен в листинге 4.3. Следует обратить внимание на событие Notify, которое может генерировать MediaPiayer. Событие Notify возникает в момент изменения состояния плеера при условии, что значение свойства Notify равно true. В рассматриваемой программе событие Notify используется для обнаружения факта открытия CD-дисковода пользователем.

Листинг 4.3. Проигрыватель компакт дисков

#define Webdings //на кнопках плеера стандартные символы,
// изображение которых взято из шрифта Webdings 
#ifdef Webdings 

// "текст" на кнопках при использовании
// шрифта Webdings 
#define PLAY "4" 
#define STOP "<" 
#define PREVIOUS "9" 
#define NEXT ":" 
#else 
// текст на кнопках при использовании 
// обычного шрифта, например, Arial 
#define PLAY "Play" 
#define STOP "Stop" 
#define PREVIOUS "Previous" 
#define NEXT "Next" 
#endif 
// эти макросы обеспечивают перевод интервала времени,
 // выраженного в миллисекундах в минуты и секунды 
#define MINUTE(ms) ( (ms/1000)/60) 
#define SECOND,(ms) ( (ms/1000) %60) 
// выводит в поле Label 1 информацию о текущем треке 
void __fastcall TForml::TrackInfo() 
{ 
int ms; // время звучания трека, мсек 
AnsiString st; 
Track = MCI_TMSF_TRACK(MediaPlayer->Position); 
MediaPlayer->TimeFormat = tfMilliseconds; 
ms = MediaPlayer-XTrackLength[Track]; 
MediaPlayer->TimeFormat = tfTMSF; 
st = "Трек "+ IntToStr(Track); 
st = st + ". Длительность "+ IntToStr(MINUTE(ms));
st = st + ":" + IntToStr(SECOND(ms)); 
Label1->Caption = st; } 
void __fastcall TForml::FormCreate(TObject *Sender) 
{ 
Buttonl->Caption = PLAY;
Button2->Caption = PREVIOUS; 
Button3->Caption = NEXT; 
MediaPlayer->Notify = true; // разрешить событие Notify } 
// изменение состояния плеера 
void __fastcall.TForml::MediaPlayerNotifу(TObject *Sender) 
{ 
switch ( MediaPlayer->Mode)
{
case mpOpen: // пользователь открыл дисковод (
Buttonl->Enabled = false; 
Button1->Caption = PLAY; 
Button1->Tag = 0; 
Button2->Enabled = false; 
Button3->Enabled = false; 
Label2->Caption = "00:00";
/* по сигналу от таймера будем проверять 
состояние дисковода */ 
Timer->Enabled = True; }
 }
MediaPlayer->Notify = true; 
}
// щелчок на кнопке Play/Stop 
void _fastcall TForml::ButtonlClick(TObject *Sender) 
{ 
if ( Buttonl-XTag = 0) { 
// щелчок на кнопке Play 
MediaPlayer->Play() ; 
Buttonl->Caption = STOP; 
Buttonl->Hint = "Стоп"; 
Buttonl->Tag = 1; 
Button3->Enabled = true; // доступна кнопка "следующий трек" 
MediaPlayer->Notify = true; 
Timer->Enabled = true; 
Tracklnfо(); 
}
 else { 
// щелчок на кнопке Stop 
Buttonl->Caption = PLAY;
Buttonl->Hint = "Воспроизведение"; 
Buttonl->Tag = 0; 
MediaPlayer->Notify = true; 
MediaPlayer->Stop();
Timer->Enabled = false; } } 
// сигнал от таймера: вывести номер трека
// и время воспроизведения 
void __fastcall TForml::TimerTimer(TObject *Sender) 
{ 
int trk; // трек 
int min, sec; // время 
AnsiString st; 
if ( MediaPlayer->Mode == mpPlaying) // режим воспроизведения 
{ 
// получить номер воспроизводимого трека
trk = MCI_TMSF_TRACK(MediaPlayer->Position); 
if ( trk != Track) // произошла смена трека
 { 
TrackInfo0 ;
 Track = trk; if { Track == 2) 
Button2->Enabled = true; // доступна кнопка "пред.трек" 
if ( Track == MediaPlayer-XTracks) 
Button3->Enabled = false; // кнопка "след.трек" недоступна } 
// вывод информации о воспроизводимом треке
 min = MCI_TMSF_MINUTE(MediaPlayer->Position); 
sec = MCIJTMSF_SECOND(MediaPlayer->Position); 
st.printf("%d:%.2d",min,sec); Label2->Caption = st; return; 
} 
/* Если дисковод открыт или в нем нет 
Audio CD, то Mode == mpOpen. 
Ждем диск, т. е. до тех пор, пока не будет 
Mode == mpStopped + кол-во треков > 1
*/ if ( (MediaPlayer->Mode == mpStopped) && 
(MediaPlayer-XTracks > 1)} < 
// диск вставлен
Timer->Enabled = false; 
Buttonl->Caption = PLAY; 
Buttonl->Enabled = true; 
Buttonl-XTag = 0; 
MediaPlayer->Notify = true; 
// получить информацию о времени звучания CD 
MediaPlayer-XTimeFormat = tfMilliseconds; 
int ms = MediaPlayer->Length; 
AnsiString st = "Audio CD. Время звучания: "; 
st = st + IntToStr(MINUTE(ms));
st = st + ":" + IntToStr(SECOND(ms)}; 
Labell->Caption = st; 
MediaPlayer-XTimeFormat = tfTMSF; 
Labell->Visible = true; Track = 0; 
return; 
} 
// дисковод открыт или в дисководе не Audio CD 
if (( MediaPlayer->Mode == mpOpen)|| 
(MediaPlayer->Mode == mpStopped) &&
(MediaPlayer->Tracks == 1))
 { 
Labell->Caption = "Вставьте Audio CD";
 if ( Labell->Visible) 
Labell->Visible = false; else Labell->Visible = true; 
} 
} 
// щелчок на кнопке "следующий трек"
void__fastcall TForml::Button3Click(TObject *Sender) 
{ MediaPlayer->Next(); 
// если перешли к последнему треку, то кнопку Next 
// сделать недоступной 
if ( MCI_TMSF_TRACK(MediaPlayer->
Position) == MediaPlayer->Tracks) 
Button3->Enabled = false; 
if (! Button2->Enabled) Button2->Enabled = true;
 Tracklnfо(); 
Label2->Caption = "0:00"; 
} 
// щелчок на кнопке "предыдущий трек" 
void__fastcall TForml::Button2Click(TObject *Sender) 
{ 
MediaPlayer->Previous(); // в начало текущего трека 
MediaPlayer->Previous(); // в начало предыдущего трека
if ( MCI_TMSF_TRACK(MediaPlayer->Position) == 1)
 Button2->Enabled = false; 
if ( ! Button3->Enabled) Button3->Enabled = true; 
Tracklnfо(); 
Label2->Caption = "0:00"; } 
// пользователь закрыл окно программы 
void __fastcall TForml::FormClose(TObject *Sender, TCloseAction SAction) 
{ 
MediaPlayer->Stop(); 
MediaPlayer->Close(); } 

Просмотр видеороликов



Как было сказано выше, компонент MediaPlayer позволяет просматривать видеоролики и сопровождаемую звуком анимацию. В качестве примера использования компонента рассмотрим программу Video Player, при помощи кoторой можно просмотреть небольшой ролик или анимацию. Вид формы программы Video Player приведен на рис. 4.9.

Компонент OpenDialog1 обеспечивает отображение стандартного диалогового окна Открыть файл для выбора файла. Окно Открыть файл становится доступным во время работы программы в результате щелчка на кнопке Eject (speedButtoni). Следует обратить внимание, что для управления процессом воспроизведения кнопки компонента MediaPiayerl не используются, поэтому свойству Visible компонента MediaPiayerl присвоено значение false.



Рис. 4.9. Форма программы Video Player


Для управления работой видеоплеера используются кнопки Play/Stop (speedButtoni) и Eject (speedButton2), представляющие собой компоненты SpeedButton.

Компонент SpeedButton находится на вкладке Additional (рис. 4.10) и представляет собой командную кнопку, на поверхности которой может быть картинка.



Рис. 4.10. Компонент SpeedButton


Кнопка SpeedButton может находиться в одном из четырех состояний: обычное (не нажата и доступна); нажата (пользователь установил указатель мыши на изображение кнопки и нажал кнопку мыши); зафиксирована; недоступна. Каждому состоянию кнопки может соответствовать своя картинка.

Свойства компонента SpeedButton приведены в табл. 4.9.

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

Свойство
Описание
Name
Имя компонента. Используется для доступа к компоненту и его свойствам
Glyph
Битовый обзраз, в котором находятся картинки для каждого из состояний кнопки. В битовом образе может быть до четырех изображений кнопки
NumGlyphs
Количество картинок в битовом образе Glyph
Flat
Свойство Flat определяет вид кнопки (наличие границы). Если значение свойства равно true, то граница кнопки появляется только при позиционировании указателя мыши на кнопке
Grouplndex
Идентификатор группы кнопок. Кнопки, имеющие одинаковый идентификатор группы, работают подобно радиокнопкам, т. е. нажатие одной из кнопок группы вызывает срабатывание других кнопок этой группы. Чтобы кнопку можно было зафиксировать, значение этого свойства не должно быть равно нулю
Down
Идентификатор состояния кнопки. Изменить значение свойства можно, если значение свойства GroupIndex не равно 0
AllowUp
Признак, показывающий, что нажатую (зафиксированную) кнопку можно отжать
Left
Расстояние от левой границы кнопки до левой границы формы
Top
Расстояние от верхней границы кнопки до верхней границы формы
Height
Высота кнопки
Width
Ширина кнопки
Enabled
Признак доступности кнопки. Если значение свойства равно true, то кнопка доступна. Если значение свойства равно false, то кнопка не доступна
Visible
Позволяет скрыть кнопку (false) или сделать ее видимой (true)
Hint
Подсказка— текст, который появляется рядом с указателем мыши при позиционировании указателя на командной кнопке (для того чтобы текст появился, значение свойства ShowHint должно быть true)
ShowHint
Разрешает (frue) или запрещает (false) отображение подсказки при позиционировании указателя на кнопке


Свойство ciiph представляет собой битовый образ, который содержит картинки для кнопок. Структура битового образа Gliph приведена на рис. 4.11. Следует обратить внимание на то, что смещение картинки на кнопке при ее нажатии, изменение цвета фона нажатой кнопки и цвета картинки на недоступной кнопке делает сам компонент. Поэтому в простейшем случае все картинки образа Gliph могут быть одинаковыми.



Рис. 4.11. Структура битового образа Glyph: картинки, соответствующие состоянию кнопки


Подготовить битовый образ для кнопки speedButton можно при помощи любого графического редактора, в том числе и Image Editor. После запуска Image Editor надо выбрать команду File | New | Bitmap File и в появившемся окне Bitmap Properties задать размер битового образа (например, 19x76 — если размер картинки на кнопке должен быть 19x19 пикселов). В качестве примера на рис. 4.12 приведен битовый образ для кнопки Play (speedButton2). Границы кнопок показаны условно. Обратите внимание, что изображение нажатой и зафиксированной кнопок смещены вверх и вправо относительно изображений нажатой и недоступных кнопок. Сделано это для того, чтобы во время работы программы у пользователя не создавалось впечатление, что кнопка "ушла".



Рис. 4.12. Битовый образ для кнопки Play


В табл. 4.10 приведены значения свойств компонентов SpeedButton1 и SpeedButton2 разрабатываемой программы. Текст программы Video Player приведен в листинге 4.4.

Таблица 4.10. Значение свойств компонентов SpeedButton1 и SpeedButton2

Свойство
SpeedButton1
SpeedButton2
Gliph
ejbtn.bmp
plbtn.bmp
NumGliphs
4
4
Flat
true
true
AllowUp
false
true
Grouplndex
0
1
Enabled
true
false
Width
25
25
Height
25
25
ShowHint
true
true
Hint
Eject
Play


Листинг 4.4. Видеоплеер

//обработка события Create
void __fastcall TForml::FormCreate(TObject *Sender)
{
MediaPlayerl->Display = Forml;
 // отображение ролика на поверхности
// формы
 }
// возвращает размер кадра AVI-файла
void __fastcall GetFrameSize(AnsiString f, int *w, int *h)
{
// в заголовке AVI-файла есть информация о размере кадра
struct {
char RIFF[4]; // строка RIFF 
long int nu_l[5]; //не используется
char AVIH[4]; // строка AVIH
long int nu_2[9]; //не используется
long int w; // ширина кадра
long int h; // высота кадра
} header;
TFileStream *fs; // поток (для чтения заголовка файла)
/* операторы объявления потока и его создания
можно объединить:
 TFileStream *fs = new TFileStream(f,fmOpenRead); */
fs = new TFileStream(f,fmOpenRead};
 // открыть поток для чтения
fs->Read(&header, sizeof(header));
 // прочитать заголовок файла
*w = header.w; *h = header.h;
delete fs; }
// щелчок на кнопке Eject (выбор видеоклипа)
void__fastcall TForral::SpeedButtonlClick(TObject *Sender)
{
OpenDialogl->Title = "Выбор клипа";
OpenDialogl->InitialDir = "";
OpenDialogl->FileName = "*.avi";
if ( ! OpenDialogl->Execute())
return; // пользователь нажал кнопку Отмена
/* При попытке открыть файл клипа, который уже открыт,
возникает ошибка. */
if ( MediaPlayerl->FileName = OpenDialogl->FileName) return;
/* Пользователь выбрал клип.
 Зададим размер и положение "экрана",
 на который будет выведен клип.
 Для этого надо знать размер кадров клипа. */
int fw, fh; // размер кадра клипа
int top,left; // левый верхний угол экрана
int sw, sh; // размер экрана (ширина, высота)
int mw, mh; // максимально возможный размер экрана
// (определяется текущим размером формы)
float kw, kh;
 // коэф-ты масштабирования кадра по ширине и высоте
float k; // коэфф-т масштабирования кадра
GetFrameSize(OpenDialogl->FileName,&fw, &fh);
 // получить размер кадра
/ / вычислим максимально возможный размер кадра
mw = Forml->ClientWidth;
mh = Forml->SpeedButtonl->Top-10;
if ( fw < mw)
kw = 1; // кадр по ширине меньше размера экрана
 else kw = (float) mw / fw;
if ( fh < mh)
kh = 1; // кадр по высоте меньше размера экрана
 else kh = (float) mh / fh;
// масштабирование должно быть пропорциональным
 if ( kw < kh)
k = kw; else k = kh; // здесь масштаб определен
sw = fw * k; // ширина экрана
sh = fh * k; // высота экрана 
left = (Forml->ClientWidth - sw) / 2;
top = (SpeedButtonl-XTop - sh) / 2; 
MediaPlayerl->FileName = OpenDialogl->FileName; 
MediaPlayerl->Open(); 

MediaPlayerl->DisplayRect = Rect(left,top,sw,sh);
SpeedButton2->Enabled = True;
// кнопка Play теперь доступна 
/* если размер кадра выбранного клипа
меньше размера кадра предыдущего клипа, 
то экран (область формы) надо очистить */ 
Forml->Canvas->
FillRect(Rect(0,0,ClientWidth,SpeedButtonl->Top)); 
// активизируем процесс воспроизведения MediaPlayerl->Play() ;
SpeedButton2->Down = True;
SpeedButton2->Hint = "Stop";
 SpeedButtonl->Enabled = False; } 
// щелчок, на кнопке Play/Stop (воспроизведение/стоп) 
void _fastcall TForml::SpeedButton2Click(TObject *Sender)
{
if (SpeedButton2->Down) { 
// нажата кнопка Play 
MediaPlayerl->Play(); 
SpeedButton2->Hint = "Stop"; 
SpeedButtonl->Enabled = False; // кнопка Eject недоступна 
} else 
{
// нажата кнопка Stop MediaPlayerl->Stop() ;
SpeedButton2->Hint = "Play"; 
SpeedButtonl->Enabled = True; // кнопка Eject доступна }
} 
11 сигнал от плеера 
void__fastcall TForml::MediaPlayerlNotify(TObject *Sender) 
{ 
if ( ( MediaPlayerl->Mode == mpStopped) &&
 ( SpeedButton2->Down))
{
SpeedButton2->Down = False; // "отжать" кнопку Play
SpeedButton2->Hint = "Play"; 
SpeedButtonl->Enabled = True; // сделать доступной кнопку Eject
}
 } 

Следует обратить внимание на следующее. В качестве экрана, на котором осуществляется воспроизведение видеороликов, используется поверхность формы. Поэтому установить значение свойства Display компонента MediaPlayer1 во время разработки формы нельзя. Кроме того, размер экрана должен быть равен или пропорционален размеру кадров ролика. Значение свойства Display устанавливает функция Обработки события Create для формы, а размер и положение экрана на форме — функция обработки события click на кнопке Eject (speecffiuttoni). Размер экрана устанавливается максимально возможным и таким, чтобы ролик воспроизводился без искажения (высота и ширина экрана пропорциональны высоте и ширине кадров). Размер кадров ролика возвращает функция GetFrameSize, которая извлекает нужную информацию из заголовка файла.

Создание анимации



Процесс создания файла анимации (AVI-файла) рассмотрим на примере. Пусть надо создать анимацию, которая воспроизводит процесс рисования эскиза Дельфийского храма (окончательный вид рисунка представлен на рис. 4.13, несколько кадров анимации — на рис. 4.14).

Для решения поставленной задачи можно воспользоваться популярной программой Macromedia Flash.

В Macromedia Flash анимация, которую так же довольно часто называют "роликом" (Movie), состоит из слоев. В простейшем случае ролик представляет собой один-единственный слой (Layer). Слой — это последовательность кадров (Frame), которые в процессе воспроизведения анимации выводятся последовательно, один за другим. Если ролик состоит из нескольких слоев, то кадры анимации формируются путем наложения кадров одного слоя на кадры другого. Например, один слой может содержать изображение фона, на котором разворачивается действие, а другой — изображение персонажей. Возможность формирования изображения путем наложения слоев существенно облегчает процесс создания анимации. Таким образом, чтобы создать анимацию, нужно распределить изображение по слоям и для каждого слоя создать кадры.



Рис. 4.13. Эскиз Дельфийского храма



Рис. 4.14. Кадры анимации процесса рисования Дельфийского храма


После запуска Macromedia Flash на фоне главного окна программы появляется окно Movie1 (рис. 4.15), которое используется для создания анимации. В верхней части окна, которая называется Timeline, отражена структура анимации, в нижней части, которая называется рабочей областью, находится изображение текущего кадра выбранного слоя. После запуска Macromedia Flash анимация состоит из одного слоя (Layer 1), который, в свою очередь, представляет собой один пустой (чистый) кадр.

Перед тем как приступить непосредственно к созданию кадров анимации, нужно задать общие характеристики анимации (ролика) — размер кадров и скорость их воспроизведения. Характеристики вводятся в поля диалогового окна Movie Properties (рис. 4.16), которое появляется в результате выбора из меню Modify команды Movie. В поле Frame Rate нужно ввести скорость воспроизведения ролика, измеряемую в "кадрах в секунду" (fps — frame per second, кадров в секунду), в поля Width и Height — ширину и высоту кадров. В этом же окне можно выбрать фон кадров (список Background Color).

После того как установлены характеристики ролика, можно приступить к созданию кадров анимации.

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



Рис. 4.15. Окно Movie в начале работы над новой анимацией



Рис. 4.16. Характеристики ролика отображаются в окне Movie Properties


Чтобы создать следующий кадр, нужно из меню Insert выбрать команду Keyframe. В результате в текущий слой будет добавлен кадр, в который будет скопировано содержимое предыдущего кадра (в большинстве случаев следующий кадр создается путем изменения предыдущего). Теперь можно нарисовать второй кадр. Аналогичным образом создаются остальные кадры анимации.

Иногда не нужно, чтобы новый кадр содержал изображение предыдущего. В этом случае вместо команды Keyframe надо воспользоваться командой Blank Keyframe.

Если некоторое изображение должно оставаться статичным в течение времени, кратного выводу нескольких кадров, то вместо того чтобы вставлять в слой несколько одинаковых кадров (Keyframe), можно сделать кадр статичным. Если кадр, изображение которого должно быть статичным, является последним кадром ролика, то в окне Timeline нужно выделить кадр, до которого изображение должно оставаться статичным, и из меню Insert выбрать команду Frame. Если кадр, изображение которого должно быть статичным, не является последним, то нужно выделить этот кадр и несколько раз из меню Insert выбрать команду Frame.

Можно значительно облегчить работу по созданию анимации, если разделить изображение на основное и фоновое, поместив каждое в отдельный слой (именно так поступают при создании мультфильмов). Сначала надо создать кадры слоя фона так, как было описано выше. Затем, выбрав из меню Insert команду Layer, нужно добавить слой основного действия.

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

Чтобы выводимая анимация сопровождалась звуком, нужно сначала сделать доступным соответствующий звуковой файл. Для этого надо из меню File выбрать команду Import и добавить в проект звуковой файл (рис. 4.17).



Рис. 4.17. Импорт звукового файла


Затем в окне Timeline нужно выделить кадр, при отображении которого должно начаться воспроизведение звукового фрагмента, используя диалоговое окно Sound (рис. 4.18), выбрать звуковой фрагмент и задать, если надо, параметры его воспроизведения. Количество повторов нужно ввести в поле Loops, эффект, используемый при воспроизведении, можно выбрать из списка Effect.



Рис. 4.18. Диалоговое окно Sound


В качестве примера на рис. 4.19 приведен вид окна Timeline в конце работы над анимацией. Анимация состоит из двух слоев. Слой Layer 2 содержит фон. Детали фона появляются постепенно, в течение 9 кадров. После этого фон не меняется, поэтому 9 кадр является статичным. Слой Layer 1 — слой основного действия, которое начинается после того, как будет выведен фон. Вывод анимации заканчивается стандартным звуком TADA (его длительность равна одной секунде). Начало воспроизведения звука совпадает с выводом последнего (49-го, если считать от начала ролика) кадра основного действия, поэтому этот кадр сделан статичным в течение вывода следующих 12 кадров (скорость вывода анимации — 12 кадров в секунду). Сделано это для того, чтобы процесс вывода анимации завершился одновременно с окончанием звукового сигнала.



Рис. 4.19. Пример анимации


После того как ролик будет готов, его надо сохранить. Делается это обычным образом, т. е. выбором из меню File команды Save.

Для преобразования файла из формата Macromedia Flash в AVI-формат нужно из меню File выбрать команду Export Movie и задать имя файла. Затем в появившемся диалоговом окне Export Windows AVI (рис. 4.20) нужно задать размер кадра (поля width и Height), из списка Video Format выбрать формат, в котором будет записана видеочасть ролика, а из поля Sound Format — формат звука.

Если установлен переключатель Compress video, то после щелчка на кнопке ОК появится диалоговое окно, в котором можно будет выбрать один из стандартных методов сжатия видео. При выборе видео и звукового формата нужно учитывать, что чем более высокие требования будут предъявлены к качеству записи звука и изображения, тем больше места на диске займет AVI-файл. Здесь следует иметь в виду, что завышенные требования не всегда оправданы.



Рис. 4.20. Диалоговое окно Export Windows AVI