Мультимедиа


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

C++ Builder предоставляет в распоряжение программиста два компонента, которые позволяют разрабатывать мультимедийные программы:

  •  Animate — обеспечивает вывод простой, не сопровождаемой звуком анимации;
 

MediaPlayer — позволяет решать более сложные задачи, например воспроизводить видеоролики, звук и сопровождаемую звуком анимацию.

 

Компонент Animate


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

Компонент 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.

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

После запуска программы в форме будет выведен первый кадр анимации, которая находится в каталоге проекта. Если ни одного файла с расширением 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 (   3).

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

Таблица 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" представлены на  5, текст — в листинге 4.2, а значения свойств компонента MediaPiayer1 — в табл. 4.7.

Таблица 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 можно создать вполне приличный проигрыватель компакт-дисков. Вид формы и диалогового окна программы приведен на  6. Помимо компонентов, показанных на рисунке, в форме есть компонент MediaPiayer. Так как кнопки компонента MediaPiayer во время работы программы не используются (для управления плеером служат кнопки Button1, Button2 и Buttons), свойству visible присвоено значение false, а сам компонент находится за границей формы.

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

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



Символ Webdings


Обычный символ — например, шрифт Arial


Код символа (шестнадцатеричный)



9


39



4


34


:




<



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

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

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

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

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

Кнопка 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 приведена на  11. Следует обратить внимание на то, что смещение картинки на кнопке при ее нажатии, изменение цвета фона нажатой кнопки и цвета картинки на недоступной кнопке делает сам компонент. Поэтому в простейшем случае все картинки образа Gliph могут быть одинаковыми.

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

В табл. 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-файла) рассмотрим на примере. Пусть надо создать анимацию, которая воспроизводит процесс рисования эскиза Дельфийского храма (окончательный вид рисунка представлен на  13, несколько кадров анимации — на  14).

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

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


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

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

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

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

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

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

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

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

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

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


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

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

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

 

 
На главную | Содержание | < Назад....Вперёд >
С вопросами и предложениями можно обращаться по nicivas@bk.ru. 2013 г. Яндекс.Метрика