В данном посте научимся транслировать VCL mp3 плеер, написанный нами ранее в веб. То есть выглядеть это будет примерно следующим образом.
Как это сделать (вариант 1)?
Это пожалуй лучший вариант – мы просто будем записывать в таг дополнительную информацию об имени файла mp3 и при сохранении в HTML пользоваться ей.
При добавлении плеера и mp3 файла соответственно.
1 2 3 4 5 6 |
... //Устанавливаем в таг путь до файла .mp3 ItemNo:=RichViewEdit1.GetItemNo(RichViewEdit1.GetCurrentItem); ItemTag:=TAudioPanel(Component).FilePath; RichViewEdit1.SetItemTag(ItemNo,ItemTag); ... |
Вот как это выглядит полностью
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
procedure TMainForm.AddAudio(Sender: TObject); var button:tbutton; audioPanel:TAudioPanel; ComponentName:string; Component:TComponent; TempCompName:string; DirectoryToCopyAudio:string; i:integer; ItemNo:integer; DestName: string; ItemTag: string; begin // RichViewEdit1.SetItemExtraIntProperty(ItemNo1, rvepShared, 1) if OpenDialog.Execute then begin //Ограничение TMediaPlayer - может быть открыто только одно устройство //т.е. по русски - только один файл for i := 0 to Self.ComponentCount-1 do begin if (Self.Components[i] is TAudioPanel) then if (Self.Components[i] as TAudioPanel).FilePath=OpenDialog.FileName then begin showmessage('Такой аудиофайл уже добавлен в данный документ'); exit; end; end; //Создание и добавление аудиоплеера inc(FAudioPanelNumber); ComponentName:=FAudioPanelNamePrefix+(FAudioPanelNumber).ToString; TAudioPanel.Create(Self).Name:=ComponentName; Component:=FindComponent(ComponentName); RichViewEdit1.InsertControl(ComponentName,TAudioPanel(Component),rvvaAbsBottom); //Копируем в папку files\audio\ DirectoryToCopyAudio:=ExtractFileDir(Application.ExeName); DirectoryToCopyAudio:=DirectoryToCopyAudio+'\files\audio\'; // Создаем директорию, если не существовала if not TDirectory.Exists(DirectoryToCopyAudio) then begin try TDirectory.CreateDirectory(DirectoryToCopyAudio); except on E:Exception do showmessage(E.ClassName+' поднята ошибка, с сообщением : '+E.Message); end; end; //Копируем аудиофайл в нашу директорию, в папку files/audio try DestName:=DirectoryToCopyAudio+ExtractFileName(OpenDialog.FileName); // Если файла там не существует, тогда копируем его туда if not TFile.Exists(DestName) then TFile.Copy(OpenDialog.FileName,DestName); except on E:Exception do showmessage(E.ClassName+' поднята ошибка, с сообщением : '+E.Message); end; TAudioPanel(Component).FilePath:=OpenDialog.FileName; //Устанавливаем в таг путь до файла .mp3 ItemNo:=RichViewEdit1.GetItemNo(RichViewEdit1.GetCurrentItem); ItemTag:=TAudioPanel(Component).FilePath; RichViewEdit1.SetItemTag(ItemNo,ItemTag); // showmessage(RichViewEdit1.GetItemTag(ItemNo)); TAudioPanel(Component).Caption:=''; TAudioPanel(Component).OpenMusicFile; // Ставим защиту от Del и BackSpace, а также говорим TRichView, не уничтожать добавленные контролы // Удаление будет происходить при нажати Del for I := 0 to RichViewEdit1.ItemCount-1 do begin RichViewEdit1.SetItemExtraIntProperty(i, rvepShared, 1); RichViewEdit1.SetItemExtraIntProperty(i, rvepDeleteProtect, 1) end; end; end; |
При сохранении в HTML воспользуемся процедурой SaveItemToFile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
procedure TMainForm.MySaveItemToFile(Sender: TCustomRichView; const Path: String; RVData: TCustomRVData; ItemNo: Integer; SaveFormat: TRVSaveFormat; Unicode: Boolean; var OutStr: TRVRawByteString; var DoDefault: Boolean); var FilePath:string; DestDir: string; DestName: string; FileName: string; begin if (RVData.GetItemStyle(ItemNo)=rvsComponent) and (SaveFormat=rvsfHTML) then begin FilePath:=RichViewEdit1.GetItemTag(ItemNo); DestDir:='/files/audio/'; DestName:=DestDir+ExtractFileName(FilePath); OutStr :='<audio src="'+DestName+'" width="200" controls></audio>'; DoDefault := False; end; end; |
Присвоим её в OnCreate
1 2 3 4 5 6 7 8 |
procedure TMainForm.FormCreate(Sender: TObject); begin //... RichViewEdit1.OnSaveItemToFile:=MySaveItemToFile; //... end; |
Как это сделать (вариант 2, не оптимальный)?
Вот один из вариантов… Как оказалось впоследствии этот вариант не самый эффективный, так как при изменении позиции контрола, скажем при нажатии на Enter, номер его Itema смещается. Для этого нужно как-то обновлять.
Заведём 2 поля для хранения номеров элементов (items в TRichView) и названий компонентов.
1 2 |
FItemNumberSL:TStringList; FComponentNameSL:TStringList; |
Будем записывать в них в момент добавления плеера в TRichView следующим образом
1 2 3 4 5 |
... //Записываем в стринглисты номер итема и имя компонента FItemNumberSL.Add(ItemNo.ToString()); FComponentNameSL.Add(ComponentName); ... |
Вот как это выглядит полностью
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
//------------------Добавление аудиоплеера procedure TMainForm.AddAudio(Sender: TObject); var button:tbutton; audioPanel:TAudioPanel; ComponentName:string; Component:TComponent; TempCompName:string; i:integer; ItemNo:integer; begin // RichViewEdit1.SetItemExtraIntProperty(ItemNo1, rvepShared, 1) if OpenDialog.Execute then begin //Ограничение TMediaPlayer - может быть открыто только одно устройство //т.е. по русски - только один файл for i := 0 to Self.ComponentCount-1 do begin if (Self.Components[i] is TAudioPanel) then if (Self.Components[i] as TAudioPanel).FilePath=OpenDialog.FileName then begin showmessage('Такой аудиофайл уже добавлен в данный документ'); exit; end; end; //Создание и добавление аудиоплеера inc(FAudioPanelNumber); ComponentName:=FAudioPanelNamePrefix+(FAudioPanelNumber).ToString; TAudioPanel.Create(Self).Name:=ComponentName; Component:=FindComponent(ComponentName); RichViewEdit1.InsertControl(ComponentName,TAudioPanel(Component),rvvaAbsBottom); // RichViewEdit1.InsertStringWTag(); //Устанавливаем таг, по которому будем потом искать этот контрол ItemNo:=RichViewEdit1.GetItemNo(RichViewEdit1.GetCurrentItem); RichViewEdit1.SetItemTag(ItemNo,'Mytag'); //Записываем в стринглисты номер итема и имя компонента FItemNumberSL.Add(ItemNo.ToString()); FComponentNameSL.Add(ComponentName); TAudioPanel(Component).FilePath:=OpenDialog.FileName; TAudioPanel(Component).Caption:=''; TAudioPanel(Component).OpenMusicFile; // Ставим защиту от Del и BackSpace, а также говорим TRichView, не уничтожать добавленные контролы // Удаление будет происходить при нажати Del for I := 0 to RichViewEdit1.ItemCount-1 do begin RichViewEdit1.SetItemExtraIntProperty(i, rvepShared, 1); RichViewEdit1.SetItemExtraIntProperty(i, rvepDeleteProtect, 1) end; end; end; |
Аналогично нам нужно обновлять списки при удалении компонентов
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
... //Удаляем из списков номер итема и имя компонента ComponentName:=TAudioPanel((Self.Components[Local_i] as TAudioPanel)).Name; IndexToDelete:=FComponentNameSL.IndexOf(ComponentName); if IndexToDelete<>-1 then begin FItemNumberSL.Delete(IndexToDelete); FComponentNameSL.Delete(IndexToDelete); end; ... |
Вот как это выглядит полностью
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
//------------------Удаление аудио-панели procedure TMainForm.DeleteFocusedAudioPanel(var Msg: tagMSG; var i: Integer); var ComponentName: string; Local_i,j,ItemNo: Integer; FilePath:string; IndexToDelete:integer; begin // //Удаление аудиопанелей if Msg.message = WM_KeyDown then begin if msg.wParam = VK_DELETE then for Local_i := 0 to Self.ComponentCount - 1 do begin if (Self.Components[Local_i] is TAudioPanel) and ((Self.Components[Local_i] as TAudioPanel).Focused) then begin // Снимаем блокировку для всех нетекстовых итемов for j := 0 to RichViewEdit1.ItemCount-1 do RichViewEdit1.SetItemExtraIntProperty(j, rvepDeleteProtect, 0); // Remove Control просто удаляет его, но не уничтожает // RichViewEdit1.RemoveControl(TAudioPanel((Self.Components[Local_i] as TAudioPanel))); //Удаление области, занимаемой контролом RichViewEdit1.SelectControl(TAudioPanel((Self.Components[Local_i] as TAudioPanel))); RichViewEdit1.DeleteSelection; //Удаляем из списков номер итема и имя компонента ComponentName:=TAudioPanel((Self.Components[Local_i] as TAudioPanel)).Name; IndexToDelete:=FComponentNameSL.IndexOf(ComponentName); if IndexToDelete<>-1 then begin FItemNumberSL.Delete(IndexToDelete); FComponentNameSL.Delete(IndexToDelete); end; // Ставим блокировку для всех нетекстовых итемов for j := 0 to RichViewEdit1.ItemCount-1 do RichViewEdit1.SetItemExtraIntProperty(j, rvepDeleteProtect, 1); //Собственно удаление контрола из памяти TAudioPanel((Self.Components[Local_i] as TAudioPanel)).Free; break; end; end; end; end; |
Последнее событие, которое нам нужно обработать, это MySaveItemToFile, отвечающее за сохранение в файл и экспорт в HTML.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
procedure TMainForm.MySaveItemToFile(Sender: TCustomRichView; const Path: String; RVData: TCustomRVData; ItemNo: Integer; SaveFormat: TRVSaveFormat; Unicode: Boolean; var OutStr: TRVRawByteString; var DoDefault: Boolean); var ControlNo:integer; i:integer; FilePath:string; IndexOfComponent:integer; ComponentName:string; MyComponent:TComponent; MyControl:TControl; begin if (RVData.GetItemStyle(ItemNo)=rvsComponent) and (SaveFormat=rvsfHTML) then begin IndexOfComponent:=FItemNumberSL.IndexOf(ItemNo.ToString); if IndexOfComponent<>-1 then begin ComponentName:=FComponentNameSL[IndexOfComponent]; MyComponent:=Self.FindComponent(ComponentName); //MyControl:=TAudioPanel(MyComponent); FilePath:=TAudioPanel(MyComponent).FilePath; end; OutStr := '<audio src="'+FilePath+'" width="200" controls></audio>'; DoDefault := False; end; end; |
Сам обработчик сохранения в HTML выглядит следующим образом
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
procedure TMainForm.bSaveHTMLClick(Sender: TObject); var HtmlFileName:string; begin if SaveDialog.Execute then begin HtmlFileName:=SaveDialog.FileName; //RichViewEdit1.SaveHTML(HtmlFileName,'MyTitle','',[]); RichViewEdit1.SaveHTMLEx(HtmlFileName,'','','','','',[]); end; end; |
Вот в принципе и всё !!!