о файле, найденном функцией FindFirst
Листинг 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; // кнопка Следующий кадр недоступна }
Листинг 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.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();
}
Листинг 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, которая извлекает нужную информацию из заголовка файла.
Содержание раздела