Для этого нам понадобится какой нибудь компилятор (библиотека портированна на все нормальные языки программирования), и немного упорства, чтобы прочитать эту статью. Ну или чтобы скопипастить (ссылку на все исходники с готовым проектом я добавлю в конце).
Итак ближе к делу. Я буду использовать лазарус (кроссплатформная среда разработки для фрипаскаля), так как мне лень лишний раз возится, но логику объясню вне конкретного языка, для твоей системы и языка исходники тут (https://www.videolan.org/vlc/libvlc.html). В частности для джава (https://github.com/caprica/vlcj) и сиплюсплюс (https://code.videolan.org/videolan/libvlcpp). Для паскаля сурсы будут в моем проекте, но ссылка также (https://wiki.videolan.org/Using_libvlc_with_Delphi/) тут.
Создаем новый проект десктопного приложения, и сразу добавляем формы, в моем случае я добавил сразу 5 форм (в идеале даже 6 или больше), для области рисования видео, для плейлиста, кнопок управления, меню и тд. Так как мой интерфейс будет содержать всякие финтефлюшки.
По сути все эти формы у меня будут составными компонентами одного окна, я делаю так для более простого восприятия кода и эффекта прозрачности с плавным переходом без изобретения велосипеда.
У всех окон я убираю стандартный бордюр (так как любой колхозный плеер имеет свои, это канон), и добавляю на форму 6 панелек и таймер, панели размещаю и привязываю так чтобы получился бордюр окна с заголовком, но только в 1 пиксель.
Теперь нужно реализовать их функционал, для изменения позиции окна плеера на экране и его разера. Для этого я создаю 3 глобальных переменных (две для координат, одну вспомогательную для определения направления и способа изменения размера, так как весь код я помещу в таймер).
Для всех панелек я создаю по два стандартных события, событие нажатия клавиши мыши, и ее отпускания. При нажатии где то на хоне панели мы будем включать таймер и отправлять в глобальную переменную условный текст, по которому будем определять че и куда надо изменять. По событии отпускания.
// вспомогательная переменная для получения координат курсора
help_last_resize_position:TPoint;
// еще одна, для получения размера окна плеера и его позиции
help_last_resize_position2:TPoint;
// а эта для таймера, чтобы определять какие манипуляции надо делать
rsz_move_type:string;
И на самом деле у меня для всех событий отпускания клавиши одна процедура\функция\события, которое я просто создал для одной панельки, и потом присвоил эту процедуру в качестве события отпускания для всех, так как она просто отключает таймер.
Для каждой конкретной панельки нам нужны свои данные, а именно координаты мыши в момент срабатывания события (их отдает сама процедура, но можно использовать функцию виндоус GetCursorPos(); где в качестве параметра переменная для получения координат, типа координаты).
В принципе можем также собирать всю информацию разом и копипастить код (или вынести в отдельную функцию, если ты фригидный дурачек). И изменять только содержимое нашей вспомогательной переменной для таймера, чтобы определять тип изменения размера.
// процедура для обработки простого перемещения окна по экрану
// типа тык по заголовку окна
procedure TMP.BRDTRMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
Begin
// получаем во вспомогательную переменную
// координаты тыка мыши по оси Х
help_last_resize_position.X:=X;
// получаем во вспомогательную переменную
// координаты тыка мыши по оси У
help_last_resize_position.Y:=Y;
// получаем в другую вспомогательную переменную
// отступ слева (отступ окна плеера, от левого
// края экрана, в пикселях), к которому прибавляем
// ширину окна плеера
help_last_resize_position2.X:=MP.Left+MP.Width;
// получаем в другую вспомогательную переменную
// отступ сверху (отступ окна плеера, от верхнего
// края экрана, в пикселях), к которому прибавляем
// высоту окна плеера
help_last_resize_position2.Y:=MP.Top+MP.Height;
// получаем во вспомогательную переменную тип
// манипуляции с окном программы, в моем случе
// по слову top я буду определять что это простое
// перемещение окна программы
rsz_move_type:='top';
// включаем наш таймер, который был изначально выключен
Rsz.Enabled:=true;
end;
Это только пример одной панельки, но в исходниках будут все, чтобы лишни раз не забивать голову, другие операции мы выполняем при помощи убогой математики, и перемещения окна программы, к примеру
ШиринаОкнаПрограммы = ШиринаОкнаПрограммы + (ТекущиеКоординатыМышиПоОсиХ - (ОтступОкнаПрограммыОтЛевогоКраяЭкрана+ШиринаОкнаПрограммы ));
Или пример для изменения размера справа, где мы изменяем положение отступа окна слева и ширину
ОтступОкнаПрограммыОтЛевогоКраяЭкрана = ТекущиеКоординатыМышиПоОсиХ -КоординатыМышиВМоментНачалаИзмененияРазмера;
ШиринаОкнаПрограммы = ОтступОкнаПрограммыОтЛевогоКраяЭкрана + ШиринаОкнаПрограммы + (КоординатыМышиВМоментНачалаИзмененияРазмера -ТекущиеКоординатыМышиПоОсиХ );
Как то так. Чтобы не забивать голову вот мой код.
// волшебный код который не требует комментариев
if rsz_move_type = 'move' then
begin
MP.Left:=Mouse.CursorPos.X-help_last_resize_position.X;
MP.Top:=Mouse.CursorPos.Y-help_last_resize_position.Y;
end;
if rsz_move_type = 'right_bottom' then
begin
MP.Width:=MP.Width + (Mouse.CursorPos.X - (MP.Left+MP.Width));
MP.Height:=MP.Height + (Mouse.CursorPos.Y - (MP.Top+MP.Height));
end;
if rsz_move_type = 'right' then
begin
MP.Width:=MP.Width + (Mouse.CursorPos.X - (MP.Left+MP.Width));
end;
if rsz_move_type = 'bottom' then
begin
MP.Height:=MP.Height + (Mouse.CursorPos.Y - (MP.Top+MP.Height));
end;
if rsz_move_type = 'left' then
begin
MP.Left:=Mouse.CursorPos.X-help_last_resize_position.X;
MP.Width:=help_last_resize_position2.X+(help_last_resize_position.X-Mouse.CursorPos.X);
end;
if rsz_move_type = 'top' then
begin
MP.Top:=Mouse.CursorPos.Y-help_last_resize_position.Y;
MP.Height:=help_last_resize_position2.Y+(help_last_resize_position.Y-Mouse.CursorPos.Y);
end;
// помимо изменения размера и положения окна плеера
// перетаскиваю вслед за ним и задаю новые размеры для
// плейлистов, панели кнопок плеера и тд
TopMenu.Left:=MP.Left+1;
TopMenu.Top:=MP.Top+1;
TopMenu.Width:=MP.Width-2;
TopMenu.Visible:=true;
TopMenu.BringToFront;
PlayerControls.Left:=MP.Left+1;
PlayerControls.Top:=MP.Top+(MP.Height-51);
PlayerControls.Width:=MP.Width-2;
PlayerControls.Visible:=true;
PlayerControls.BringToFront;
if PMenu.Visible = true then
begin
PMenu.Left:=MP.Left;
PMenu.Top:=MP.Top+51;
PMenu.Height:=MP.Height-102;
PMenu.Width:=400;
end;
if Playlist.Visible = true then
begin
Playlist.Visible:=true;
Playlist.Left:=(MP.Left+MP.Width)-Playlist.Width;
Playlist.Top:=MP.Top+51;
Playlist.Height:=MP.Height-102;
end;
Теперь когда у нас есть окно плеера подтянем картинки со звуками на экран, подключением библиотеки lib_vlc.dll. Все функции из этой библиотеки интуитивно понятны и одинаковы для всех языков. Полный список функций из библиотек можно посмотреть на сайте (https://videolan.videolan.me/vlc/group__libvlc.html).
Подключаем исходники связывающие библиотеку с описанными функциями-заголовками (для паскаля это uses PasLibVlcUnit). Создаем две глобальных переменных, первая переменная типа libvlc_instance_t_ptr, вторая переменная типа libvlc_media_player_t_ptr, для экземпляра библиотеки и плеера, название может быть любым, у меня они называются из примеров p_li и p_mi (неудачные сокращения от либрарей инстанс и медиа инстанс).
Создаем функцию, в который выполняем загрузку и инициацию экземпляра библиотеки, и из нее уже вызываем функцию, которая создаст нам экземпляр готового плеера.
function INITVLC:boolean;
begin
// загружаем библиотеку и линкуем заголовки
// для того чтобы эта функция работала корректно
// на компьютере должен быть vlc media player
// я же использую ее так как у меня кривая сборка
// винды, в которой не регистрируются дллешки
libvlc_dynamic_dll_init();
// загружаем библиотеку из какого нибудь места
// в качестве аргумента функции я передаю
// содержимое моей глобальной переменной app_path,
// в которую я поместил путь до моей программы,
// к которой добавляю название библиотеки с плеером
//libvlc_dynamic_dll_init_with_path(app_path+'libvlc.dll');
// создаю условие, если содержимое переменной
// libvlc_dynamic_dll_error из PasLibVlcUnit
// содержит что то большее чем ничего, вызываю
// стандартное диалоговое окно системы, и вывожу
// код ошибки из libvlc_dynamic_dll_error
if (libvlc_dynamic_dll_error <> '') then
begin
// вызываю диалог
MessageDlg(libvlc_dynamic_dll_error, mtError, [mbOK], 0);
// уничтожаю экземпляр программы
// и завершаю работу приложения
Application.Terminate();
// экстренно прирываю выполнение дальнейшего кода
exit;
end;
// с объектом библиотеки PasLibVlcUnit
// создаю новый экземпляр перменной, в
// которую помещаю дополнительные параметры
// для загрузки библиотеки
with TArgcArgs.Create([
WideString(libvlc_dynamic_dll_path),
'--intf=dummy',
'--ignore-config',
'--quiet',
'--no-video-title-show',
'--no-video-on-top'
]) do
begin
// вызываю функцию из библиотеки PasLibVlcUnit,
// которая создает новый экземпляр условного
// скрытого плеера vlc с аргументами и ассоциирую
// ее с переменной p_li
p_li := libvlc_new(ARGC, ARGS);
// уничтожаю объект TArgcArgs, так как он больше
// не нужен
Free;
end;
// создаю условие, если переменная экземпляра p_li
// содержит что то, кроме ничего продолжаю действия
if (p_li <> NIL) then
begin
// ассоциирую с переменной p_mi результат выполнения
// функции libvlc_media_player_new, в которой передаю
// в качестве аргумента переменную с загруженным
// экземпляром библиотеки lib_vlc.dll
p_mi := libvlc_media_player_new(p_li);
end;
// возвращяю результат работы функции как true
result:=true;
end;
Представим что все понятно и все получилось с первого раза. А еще предположим что мы разместили на форме все финтифлюшки как хотели и они работают корректно. Давайте сразу опишем функции для открытия файла, воспроизведения, паузы, и стопа.
Все проще чем кажется, мы просто используем простенькие функции из нашей линькованной библиотеки, и в качестве аргумента для этих функции передаем нашу глобальную переменную с плеером, или библиотекой, в зависимости от действия.
function StopVideo:boolean;
begin
// создаю условие, если содержимое
// переменной p_mi с медиаплеером
// не равно ничему, выполняю содержимое
// условия
if (p_mi <> NIL) then
begin
// вызываю функцию из библиотеки
// PasLibVlcUnit, которая выполняет паузу,
// в качестве аргумента указываю
// переменную с которой ассоциирован
// экземпляр плеера
libvlc_media_player_pause(p_mi);
// выполняю перерисовку области экрана
// это для моих финтифлюшек, этот код не
// обязателен
MP.Monitor1.Repaint;
MP.Monitor1.ParentBackground:=false;
MP.Monitor1.ParentBackground:=true;
end;
// возвращяю результат выполнения функции как true
result:=true;
end;
function PlayVideo(filename:WideString):boolean;
var
// создаю переменную типа медиаобъект
// из библиотеки PasLibVlcUnit
p_md : libvlc_media_t_ptr;
// слздаю вспомогательную переменную
// для конвертирования имени файла
// типа строка анси
a_st : AnsiString;
// и еще одну типа символ
p_st : PAnsiChar;
begin
// конвертирую содержимое аргумента
// функции PlayVideo в фют8
a_st := UTF8Encode(fileName);
// получаю первый символ из пути,
// который конвертирую в формат анси,
// не совсем понятно для чего это
p_st := PAnsiChar(@a_st[1]);
// создаю условие, если содержимое
// переменной, с которой ассоциированна библиотека
// lib_vlc.dll больше чем ничего, продолжаю действия
if (p_li <> NIL) then
begin
// вызываю функцию из библиотеки PasLibVlcUnit
// которая получает информацию об файле, его тип,
// размер и тд, в качестве параметра передаю
// содержимое вспомогательных переменных, с которыми
// я ассоциировал конвертированный в формат ютф8
// путь к файлу с имененм, результат выполнения
// функции помещяю в другую вспомогательную перменную p_md
p_md := libvlc_media_new_path(p_li, p_st);
// создаю условие, если содержимое
// переменной p_md больше чем ничего,
// продолжаю действия
if (p_md <> NIL) then
begin
// создаю условие, если содержимое
// переменной с экземпляром медиаплеера
// больше чем ничего, продолжаю действия
if (p_mi <> NIL) then
begin
// вызываю функцию из библиотеки PasLibVlcUnit,
// которая позволяет перехватить из программы,
// в библиотеку обработку нажатия клавиш клавиатуры,
// в качестве параметров передаю переменную с медиаплеером
// и указатель 0, так как обрабатывать клавишы
// будет моя программа
libvlc_video_set_key_input(p_mi, 0);
// выполняю аналогичную операцию для мыши
libvlc_video_set_mouse_input(p_mi, 0);
// вызываю функцию из библиотеки PasLibVlcUnit,
// которая позволяет назначить какой нибудь объект,
// у которого есть в своем содержимом область для
// рисования в качестве экрана для видео, в качестве
// параметров передаю переменную с экземпляром плеера,
// и индекс объекта с областью рисования в формате
// системы, у меня это панелька с названием Monitor1
libvlc_media_player_set_display_window(p_mi, MP.Monitor1.Handle);
// вызываю функцию из библиотеки PasLibVlcUnit,
// которая позволяет ассоциировать медиаобъект с
// экземпляром плеера, в качестве параметра передаю
// экземпляр медиплеера из глобальной переменной и
// содержимое вспомогательной переменной с информацией
// о медиафайле
libvlc_media_player_set_media(p_mi, p_md);
end;
// вызываю функцию из библиотеки PasLibVlcUnit,
// которая позволяет определить и декодировать файл
libvlc_media_release(p_md);
end;
end;
// возвращяю результатом выполнения функции true
result:=true;
end;
И наконец функция для начал воспроизведения. У меня эта функция объеденяет в себе возможности воспроизводить\пауза, так как у плеера может быть несколько состояний (файл загружен, файл не найден, файл воспроизводиться и тд), необходимо обработать их все. Опишу для состояния пауза, так как остальные интуитивно понятны.
procedure TPlayerControls.Image1Click(Sender: TObject);
begin
// создаю условие если результат выполнения
// функции из библиотеки PasLibVlcUnit под названием
// libvlc_media_player_get_state вернул значение,
// которое соответствует условному ключевому слову
// из библиотеки libvlc_Paused, выполняю действия условия
if libvlc_media_player_get_state(p_mi) = libvlc_Paused then
begin
// вызываю функцию воспроизведения
libvlc_media_player_play(p_mi);
// это финтефлюшки, изменяю иконку кнопки
// воспроизведение с воспроизводить на паузу
Self.Image1.Picture:=Self.src_img_pause.Picture;
// внезапно прерываю выполнение процедуры
exit;
end;
if libvlc_media_player_get_state(p_mi) = libvlc_Playing then
begin
libvlc_media_player_pause(p_mi);
Self.Image1.Picture:=Self.src_img_play.Picture;
exit;
end;
if libvlc_media_player_get_state(p_mi) = libvlc_Ended then
begin
libvlc_media_player_play(p_mi);
Self.Image1.Picture:=Self.src_img_pause.Picture;
exit;
end;
if libvlc_media_player_get_state(p_mi) = libvlc_Stopped then
begin
libvlc_media_player_play(p_mi);
Self.Image1.Picture:=Self.src_img_pause.Picture;
exit;
end;
end;
И вот у нас уже есть готовый прототип программы, который может воспроизводить видео, осталось создать кнопку и разместить диалоговое окно открытия файла, внутри события кнопки открыть, вызвать нашу функцию, для открытия медиафайла, и передать ей результат выполнения диалогового окна для выбора файла.
Теперь давайте добавим полосочку таймера, и плейлист. Для полоски таймера я использую еще две панельки, одна над другой, разиных цветов, по мере продвижения времени, я буду изменять размер одной полоски, которая будет находится над другой, другая будет представлять собой всю временную шкалу.
Плейлист я размещу в отдельном окне и возьму для него стандартную заготовки из системных библиотек TListBox (в с++ cli это ListBox как не парадоксально, и JList вjdk). Еще добавлю новый таймер, который будет получать текущую позицию времени воспроизводимого файла, и обновлять прогресс панельки со временем.
Давайте опишем функцию таймера, так как он будет работать каждую секунду все время и проверять состояние плеера, исходя из чего выполнять перерасчет прогресса временной шкалы.
Для начала у меня есть вспомогательная функция, которая конвертирует секунды в привычный формат, так как у меня отображается еще и время видео. Она не обязательна, но сурс просто добавлю чтобы бы.
function ConvertMsToNormalTime(i:TCaption):TCaption;
var a:string;
b:real;
c,d:integer;
min,sec,hours:integer;
begin
a:='';
c:=0;
d:=round(StrToFloat(i));
min:=0;
sec:=0;
hours:=0;
while c < d do
begin
inc(sec);
if sec = 60 then
begin
inc(min);
sec:=0;
end;
if min = 60 then
begin
inc(hours);
min:=0;
end;
inc(c);
end;
if hours < 10 then
begin
a:=a+'0'+IntToStr(hours)+':';
end else
begin
a:=a+IntToStr(hours)+':';
end;
if min < 10 then
begin
a:=a+'0'+IntToStr(min)+':';
end else
begin
a:=a+IntToStr(min)+':';
end;
if sec < 10 then
begin
a:=a+'0'+IntToStr(sec);
end else
begin
a:=a+IntToStr(sec);
end;
result:=a;
end;
Теперь сама функция таймера-обновлятеля прогресса временной шкалы.
procedure TMP.MoveTimerTimer(Sender: TObject);
// создаю вспомогательные переменные типа
// реальное число (для быдлокодеров поясню что
// это число с плавающей запятой)
var a,s1,s2,s3:real;
// создаю вспомогательные переменные типа число
// (целое число)
var b,c:integer;
begin
// создаю условие, если с переменной
// для экземпляра ассоциированно что
// то что больше ничего, выполняю код
// условия
if (p_mi <> NIL) then
begin
// создаю условие, если функция
// libvlc_media_player_get_state для
// получения статуса плеера из
// библиотеки PasLibVlcUnit возвращяет
// значение, которое соотвествует
// описанному в библиотеке PasLibVlcUnit
// libvlc_Playing значение, выполняю код условия
if (libvlc_media_player_get_state(p_mi) = libvlc_Playing) then
begin
// ассоциирую со вспомогательной
// переменной значени 0
b:=0;
// начинаю цикл с условием
// повторять до тех пор, пока
// значение переменной b меньше 100
while b < 100 do
begin
// со вспомогательной переменной
// ассоциирую результат выполнения функции
// libvlc_media_player_get_position, которая
// позволяет получить текущую позицию в милисекундах
// воспроизводимого видео, из библиотеки PasLibVlcUnit,
// в качестве параметра передаю глобальную переменную
// с которой ассоциирован экземпляр плеера, и конвертируя
// встроенной функцией паскаля Real привожу данные к типу
// число с плавующей точкой, которое округляю до секунд
s1:=RoundTo(Real(libvlc_media_player_get_position(p_mi)),-3);
// создаю условие, если 1 деленный
// на 100 умноженный на содержимоей
// вспомогательной переменной b больше
// значения s1 выполняю условие, иначе
// выполняю альтернативное действие
// (функция libvlc_media_player_get_position
// возвращяет значение в диапозоне от 0.0 до
// 1.0)
if ((1 / 100) * Real(b) >= s1) then
begin
// переношу значение переменной b
// в другую вспомогательную переменную c
// и прекращяю цикл
c:=b;
b:=100;
end ELSE
begin
c:=100;
end;
inc(b);
end;
// для панельки прогресса задаю ширину,
// которая равна округленному процентному
// соотношению всей временной шкалы,
// которая у меня представлена в другой
// панельке
PlayerControls.Time2.Width:=Round((PlayerControls.Time1.Width / 100) * c);
// в надпись (или обхект Textlabel) помещаю результат
// выполнения вспомогательной функции для конвертирования
// секунд в привычный формат, в которую передаю (конвертируя
// в текст значение с плавующей точкой), которое получаю
// из функции библиотеки PasLibVlcUnit, которая возвращяет
// текущее время воспроизведения в милисекундах
PlayerControls.Label1.Caption:=ConvertMsToNormalTime(FloatToStr(libvlc_media_player_get_time(p_mi) / 1000));
// аналогичную операцию проделываю для другой надписи,
// в которой находится полное время видео
PlayerControls.Label2.Caption:=ConvertMsToNormalTime(FloatToStr(Real(libvlc_media_player_get_length(p_mi)) / 1000))+' ('+IntToStr(c)+'%)';
end;
// создю условие, если результат выполнения функции
// libvlc_media_player_get_state возвращяет значение соотвествующие
// libvlc_Ended из библиотеки PasLibVlcUnit, выполняю действия условия
if libvlc_media_player_get_state(p_mi) = libvlc_Ended then
begin
// задаю ширину панельки прогресса, равную ширине
// всей панельки времени
PlayerControls.Time2.Width:=PlayerControls.Time1.Width;
// ещё раз получаю текущее время воспроизведения
// видео (позицию воспроизведения)
PlayerControls.Label1.Caption:=ConvertMsToNormalTime(FloatToStr(libvlc_media_player_get_time(p_mi) / 1000));
// отключаю таймеры моих финтифлюшек
// этот код не обязателен
MP.MoveTimer.Enabled:=false;
MP.Player_Next.Enabled:=true;
end;
end;
end;
Ну и в дополнение код для события тыка по прогресс бару. Для панельки, которая отвечает за всю временную шкалу создаем событие тыка, после эту же функцию ассоциируем с аналогичным событием второго панельки, которая отвечает за текущее время.
procedure TPlayerControls.Time1Click(Sender: TObject);
// создаем вспомогательные переменные
// типа целое число
var b,c:integer;
begin
// со вспомогательной переменной ассоциируем
// координаты курсора по оси Х, из которых
// вычитаем все отступы от левого края экрана,
// до нашей панельки с прогрессом
c:=Mouse.CursorPos.X - (1+MP.Left+Time1.left);
// начинаем цикл для получения процентного
// значения панельки воспроизведения
b:=0;
while b <= 99 do
begin
// создаем условие, если конвертированное
// в число с плавующей точкой значение
// ширины панельки текущего времени деленное
// на 100 и умноженное на значение переменной b
// больше или равно значениею переменной c
// выполняем дийствия условия
if Real(Time1.Width / 100) * b >= c then
begin
// из библиотеки PasLibVlcUnit вызываем функцию для
// изменения времени воспроизведения, в качестве параметра
// указываем переменную с которой ассоциирован экземпляр
// плеера и новое время в формате числа с плавующей точкой,
// которое получаем из умножения 1 на значение переменной b
libvlc_media_player_set_position(p_mi, StrToFloat(FloatToStr(Real(1) / Real(99) * b)));
// вызываем функцию для воспроизведения
// видео, из библиотеки PasLibVlcUnit, которая
// начинает воспроизведение видео, в качестве параметра
// указываем переменную с которой ассоциирован экземпляр
libvlc_media_player_play(p_mi);
b:=100;
end;
inc(b);
end;
end;
Вот у нас есть уже рабочий плеер, и в нем даже есть временная шкала. Давайте я еще немного расскажу про плейлист и в принципе альфа версия плеера будет готова. Так как у меня плеер планировался преимущественно как видеоплеер, как альтернатива тому же vlc media player, с функционалом больше приближенным к ютюбу и вообще интерфейсом веб плеера, у меня нет в программе получения расширенной информации о медиа.
Это получить не так сложно, тем более что vlc уже все сам сделал, просто нужно взять, написав соответствующую функцию-запрос (вики по vlc lib в помощь). У меня плейлист будет содержать информацию о размере файла, имя файла и расположение.
При этом во время загрузки первого файла, как и WMP, мой плеер ищет все другие воспроизводимые форматы в той же папке и помещает их в плейлист. Насколько мне известно vlc работает со всеми основными форматами медиа.
В моей программе планировался совмещенный режим с просмотром фотографии, поэтому у меня список немного другой.
*.mp4;*.mp3;*.mp2;*.wmv;*.wma;*.avi;*.asf;*.mov;*.mkv;*.wav;*.ogg;*.ogm;*.flac;*.flv;*.mxf;*.smf;*.mid;*.3gp;*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.ico;*.tif;*.tiff;
В лазарусе для этого есть функция FindAllFiles(), у вас может быть другая (скорее всего стандартный интерфейс с результирующим листом, или функция FindFirst, FindNext). Я просто помещаю в список листа все полные пути к файлам, которые перерисовываю в событии отрисовки элементов списка TListBox.
procedure TPlaylist.ListBox1DrawItem(Control: TWinControl; Index: Integer;
ARect: TRect; State: TOwnerDrawState);
// создаю числовую переменную
var b:integer;
begin
// с объектом канвас у ListBox начинаю действия
with ListBox1.Canvas do
begin
// создаю условие, если значение
// передаваемого аргумента с текущим
// индексом в листе, которое, деленное
// имеет остаток 0, выполняю условия,
// иначе перехожу к альтернативному условию
if (Index) mod 2 = 0 then
begin
// у объхекта канвас листбокса1
// свойства цвета фона закраски задаю
// из глобальной вспомогательной переменной,
// в которой содержится код цвета
Brush.Color := style_base_color;
// аналогично для цвета отрисовки
Font.Color := style_text_color;
// заполняю фоновым цветом
// всю область отрисовки
FillRect(ARect);
// для текстовой отрисовки
// задаю размер шрифта в 10
Font.Size:=10;
// отрисовываю текст в координатах,
// которые были получены в качесте аргумента,
// отрисовываю имя файла, полученное из
// значения строки списка, которое пропускаю
// через функцию, которая отрезает из названия
// расширение и путь (то есть оставляет только имя)
TextOut(ARect.Left+4, ARect.Top, GetFileNameFromFullPath(ListBox1.Items[Index]));
// для текстовой отрисовки
// задаю размер шрифта 6
Font.Size:=6;
// отрисовываю в сдвинутых координатах, относительно
// и внутри области отрисовки, отрисовываю полный
// путь к файлу с имененм
TextOut(ARect.Left+4, ARect.Top+16, ListBox1.Items[Index]);
end else
begin
// Альтернативное условие,
// делаю все тоже саоме,
// олько инвертирую цвета отрисовки
// и заливки
Brush.Color := style_text_color;
FillRect(ARect);
Font.Color := style_base_color;
Font.Size:=10;
TextOut(ARect.Left+4, ARect.Top, GetFileNameFromFullPath(ListBox1.Items[Index]));
Font.Size:=6;
TextOut(ARect.Left+4, ARect.Top+16, ListBox1.Items[Index]);
end;
end;
end;
Ну и в качестве бонуса модная нынче лгбт подцветка, которая у меня реализована только на заголовок с названием файла, так как выглядит как мне показалось колхозно, и для вырезания годных цветов для переливания как на кулерах лень делать. У меня он выключен, поэтому нужно включить таймер PlayerRGB.
В общем на этом я думаю можно закончить, так как альфа плеера по сути описана, а что то дополнительное для слабаков. Надеюсь данная статья будет полезна, поделись своим мнением и если есть какие либо ошибки и предложения, ты всегда можешь дополнить меня в комментах, спасибо за внимание^^