Статьи

Опыт создания мультимедиа-приложения.

У меня на жестком диске скопилось достаточно много различных песен в форматах mp3 и wav. И место занимают, и выкинуть жалко. Выхода два: либо покупать новый жесткий диск (что кусаемо), либо сбрасывать все это на CD. Эта статья рассчитана в первую очередь на тех, у кого есть бреннер, чтобы записывать CD. Однако, я надеюсь, что она будет интересна и остальным различными приемами работы. Вообще то сбросить файлы на CD - особой сложности не представляет. Однако, как задачу-максимум, поставим перед собой создание программы-оболочки, для проигрывания файлов.

Что мы хотим получить в итоге? А в итоге мы хотим, чтобы вставив CD, автоматически запускалась наша оболочка, которая в автоматическом режиме проигрывала бы все музыкальные файлы из всех альбомов. При необходимости можно было бы переключиться на любой альбом или музыкальный файл, ну и, возможно, минимизировать форму, чтобы она позволяла заняться другими делами.

Создадим новый проект Standard EXE. Переименуем проект в MusicCD, а форму в frmMusic. Изменим некоторые свойства формы: AutoRedraw = True, BorderStyle = None, Icon - выберите любую понравившеюся иконку, ScaleMode = 3 (Pixel), StartUpPosition = 2 (CenterScreen). А в свойство Picture загрузите картинку, которая будет фоном у Вас. Визуально, картинка будет делиться на 3 части: область для вывода списка альбомов, область для вывода списка файлов из альбома и область управления формой. Как Вы нарисуете, так и будет. Я "увидел" свою программу в таком виде (уменьшенный вариант):

В синей области расположим ListBox: Name = lstSong, а в оранжевой второй: Name = lstPls, соответственно изменив им фоновый цвет. В правой нижней части расположим 3 PictureBox, которые у нас будут изображать кнопки управления. Для них надо будет подготовить картинки в 2-х видах: нажатая и отжатая кнопки. Для всех трех установим следующие свойства: Name = picTool, AutoRedraw = True, AutoSize = True, BorderStyle = 0 (None), Index - от 0 до 2, MousePointer = 99 (Custom), ScaleMode = 3 (Pixel)
И два набора по три picDown и picUp с картинками нажатых и отжатых кнопок. Все свойства те же, что и у picTool, за исключением Visible = False.
Следующий элемент управления - таймер: Name = tmrSong, Interval = 1000.
Теперь о главном. С помощью чего мы будем воспроизводить нашу музыку. Можно воспользоваться API-функциями, а можно, как в моем случае, использовать готовый ЭУ. Откроем меню Project/Components... и в диалоговом окне выберем Windows Media Player. Сделаем ему следующие установки: уменьшим высоту, чтобы не было видно экрана, Name = MP, ShowPositionControls = False, ShowStatusBar = True.

Ну вот, все предварительные работы сделаны, можно заняться и кодами. Добавим к проекту модуль и впишем в него API-функции, необходимые нам для возможности "перетаскивать" форму за любое место.
Public Declare Function ReleaseCapture Lib "user32" () _
    As Long
Public Declare Function SendMessage Lib "user32" _
    Alias "SendMessageA" _
    (ByVal hwnd As Long, _
    ByVal wMsg As Long, _
    ByVal wParam As Long, _
    lParam As Any) _
    As Long

Public Const HTCAPTION = 2
Public Const WM_NCLBUTTONDOWN = &HA1
Впишем глобальную переменную AppPath
Public AppPath As String
Вообще-то без этой переменной можно и обойтись, так как на CD все записывается один раз и перемещения файлов в дальнейшем не будет. Однако, с ее помощью нам будет легче отлаживать программу. Запишем запускающую процедуру:
Public Sub Main()
    If Right(App.Path, 1) = "\" Then
        AppPath = App.Path
    Else
        AppPath = App.Path & "\"
    End If
frmMusic.Show
End Sub

В форме запишем как мы будем перемещать форму:

Private Sub Form_MouseDown(Button As Integer, _
    Shift As Integer, X As Single, Y As Single)
Select Case Button
Case vbLeftButton
    'перемещаем форму вслед за "мышкой"
    Call ReleaseCapture
    Call SendMessage(Me.hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0&)
End Select
End Sub

Теперь самое время заняться обработкой нажатия кнопок. На MouseDown мы просто будем менять картинку, а на MouseUp - возвращаем прежнюю плюс обработка действия каждой клавиши (на данном этапе мы пока напишем коды для последней кнопки - выход из программы).
Private Sub picTool_MouseDown(Index As Integer, Button As Integer, _
    Shift As Integer, X As Single, Y As Single)
        picTool(Index).Picture = picDown(Index).Picture
End Sub

Private Sub picTool_MouseUp(Index As Integer, Button As Integer, _
    Shift As Integer, X As Single, Y As Single)
        picTool(Index).Picture = picUp(Index).Picture
        SendKeys vbNullChar

Select Case Index
    Case 0
        
    Case 1
        
    Case 2
        Unload Me
End Select
End Sub

Мне кажется, на данном этапе мы должны заняться внутренней структурой программы. Т.е. как расположены файлы в папках на диске, откуда мы читаем информацию и т.п. Вариантов решения здесь много. Например, можно хранить информацию о путях к файлу и соответствующее ему название песни в ini-файлах (о работе с ini-файлами Вы можете почитать здесь). Или же хранить эту информацию в базе данных: классической (mdb-файлы) или собственной (один из вариантов описывается в здесь). Но я хочу предложить другой способ, который позволит нам сделать данную оболочку универсальной и не возвращаться к кодированию, когда мы соберемся записывать другой CD-диск с другими песнями. Данный способ основывается на том, что файлы песен (чаще всего mp3-формат) взяты из интернета и уже имеют в своем заголовке имя песни, а перечень песен, находящихся в папке можно очень быстро и безболезненно создать в виде плэй-листа (*.pls) с помощью таких распространенных программ как WinAmp и Sonique. Примерная структура данных файлов (читаются с помощью простого Блокнота):
[playlist]
File1=Ах, Одесса\Школа бальных танцев.mp3
...
File13=Ах, Одесса\Ах, Одесса моя ненаглядная.mp3
NumberOfEntries=13

где до слэша идет название папки (папок), а после - название песни. Напишем процедуру считывания заголовков всех плэй-листов в ListBox (lstPls), с учетом того, что они будут лежать в корневой директории:
Private Sub LoadPls()
Dim sPls$

On Error Resume Next
    lstPls.Clear
    
    sPls = Dir(AppPath & "*.pls")
    sPls = Left(sPls, Len(sPls) - 4)
    Do While sPls <> vbNullString
        lstPls.AddItem sPls
        sPls = Dir
        sPls = Left(sPls, Len(sPls) - 4)
    Loop
End Sub

И запустим ее при загрузке формы:
Private Sub Form_Load()
    LoadPls
    lstPls.ListIndex = 0
End Sub
Обратите внимание, что установка фокуса на самом первом значении (ListIndex = 0) - обрабатывается как событие Click, чем мы и воспользуемся, для считывания, входящих в этот плэй-лист, песен. В разделе деклараций добавим две переменные, отвечающие за номер текущей папки (альбома) и номер текущей песни:
Private NumSong As Integer, NumAlbum As Integer

Private Sub lstPls_Click()
    ReedFile
    NumSong = 0
    NumAlbum = lstPls.ListIndex
End Sub

Public Sub ReedFile()
Dim F%, PathFile$, sTitle$
Dim FName$

'чтение данных из файла
lstSong.Clear
F = FreeFile
PathFile = AppPath & lstPls.List(lstPls.ListIndex) & ".pls"
Open (PathFile) For Input As #F

Input #F, sTitle
Do While Not EOF(F)
    Line Input #F, FName
    If Left(FName, 15) <> "NumberOfEntries" Then
        FName = Mid(FName, InStr(1, FName, "=", vbTextCompare) + 1)
        lstSong.AddItem FName
    End If
Loop
Close #F
End Sub

Напишем процедуру, которая будет обрезать полный путь к файлу до названия файла (без расширения), для последующего вывода на форме, как текущей песни. Для этого нам понадобится еще одна функция, которую необходимо объявить в модуле:
Public Declare Function GetFileTitle Lib "comdlg32.dll" _
    Alias "GetFileTitleA" _
    (ByVal lpszFile As String, _
    ByVal lpszTitle As String, _
    ByVal cbBuf As Integer) _
    As Integer
А сама процедура помещается в форме:
Private Sub TitleSong(SongNum As Integer)
Dim Buffer As String, sPath As String

    sPath = AppPath & lstSong.List(SongNum)
    Buffer = String(255, 0)
    GetFileTitle sPath, Buffer, Len(Buffer)
    Buffer = Left$(Buffer, InStr(1, Buffer, Chr$(0)) - 1)
    Buffer = "Song: " & Mid(Buffer, 1, Len(Buffer) - 4)
    
    Cls
    CurrentX = 24
    CurrentY = 12
    With Font
        .Name = "Time New Roman Cyr"
        .Bold = True
        .Italic = True
        .Size = 12
    End With
    ForeColor = vbCyan
Print Buffer
End Sub

Теперь по дабл-клику, будем пересылать выбранную песню на медиаплеер. При этом установим проверку на последнюю песню в альбоме и последний альбом на диске. Если это случилось - то переходим, соответственно, на первую песню следующего альбома или к первому альбому:
Private Sub lstSong_DblClick()
    MP.FileName = AppPath & lstSong.List(lstSong.ListIndex)
    TitleSong lstSong.ListIndex
    NumSong = lstSong.ListIndex + 1
    If NumSong = lstSong.ListCount Then
        NumSong = 0
        NumAlbum = NumAlbum + 1
        If NumAlbum = lstPls.ListCount Then
            NumAlbum = 0
        End If
    lstPls.ListIndex = NumAlbum
    End If
End Sub

Точно такую же проверку необходимо установить и в обработке события таймера. Однако здесь немного сложнее, таймер, кроме всего прочего должен отслеживать конец песни. Поэтому и процедура выглядит несколько более громоздко.
Private Sub tmrSong_Timer()
    If (MP.PlayState <> mpPlaying) Then
        If MP.CurrentPosition >= MP.Duration Or MP.CurrentPosition = -1 Then
            MP.FileName = AppPath & lstSong.List(NumSong)
            TitleSong NumSong
            If lstSong.ListCount <> 0 Then
                lstSong.ListIndex = NumSong
            End If
            NumSong = NumSong + 1
            If NumSong > lstSong.ListCount - 1 Then
                NumSong = 0
                NumAlbum = NumAlbum + 1
                If NumAlbum = lstPls.ListCount Then
                    NumAlbum = 0
                End If
            lstPls.ListIndex = NumAlbum
            End If
        End If
    End If
End Sub

Ну и напоследок, не забудем выключить плеер, при выходе из формы.
Private Sub Form_Unload(Cancel As Integer)
    MP.Stop
End Sub

Мы, практически, закончили с основной формой. У нас незанятыми остались только 2 кнопки, которые будут вызывать дополнительные формы. Добавьте еще 2 формы к проекту. Назовите одну frmAbout, а другую - frmMin. Измените свойства каждой из форм: BorderStyle = 0 (None), ScaleMode = 3 (Pixel).
И последний раз обратимся к кодам в frmMusic. Привяжем вывод вспомогательных форм к нажатиям на кнопки в событии picTool_MouseUp:
...
Select Case Index
    Case 0
        frmAbout.Show vbModal
    Case 1
        Me.Hide
        frmMin.Show
    Case 2
        Unload Me
End Select
...

Форма frmMin - не несет "смысловой" нагрузки. Она просто, в виде узкой полоски, заменяет основную форму, когда та прячется. Я даже не стал выводить на ней отдельную кнопку закрытия, а просто нарисовал ее.

 При загрузке формы, позиционируем ее в левом верхнем углу, а при нажатии левой клавиши - мы сможем ее перемещать. Обратите внимание, что для перемещения мы выбираем область формы без кнопки:
Private Sub Form_Load()
    Move 0, 0
End Sub

Private Sub Form_MouseDown(Button As Integer, _
    Shift As Integer, X As Single, Y As Single)
    Select Case Button
        Case vbLeftButton
            If (X > 0 And X < 260) Then
                Call ReleaseCapture
                Call SendMessage(Me.hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0&)
            End If
    End Select
End Sub

А в событии MouseUp - сделаем обработку выгрузки формы и "проявления" основной формы на экране:
Private Sub Form_MouseUp(Button As Integer, _
    Shift As Integer, X As Single, Y As Single)
    Select Case Button
        Case vbLeftButton
            If (X > 260 And X < 289) And (Y > 4 And Y < 18) Then
                frmMusic.Show
                Unload Me
            End If
    End Select
End Sub

С минимизированной формой закончено. Переходим к форме frmAbout. Здесь, как и в предыдущей форме минимум похожего кода

Private Sub Form_MouseDown(Button As Integer, _
    Shift As Integer, X As Single, Y As Single)
    Select Case Button
        Case vbLeftButton
            If (X > 236 And X < 273) And (Y > 24 And Y < 41) Then
            Else
                Call ReleaseCapture
                Call SendMessage(Me.hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0&)
            End If
    End Select
End Sub


Private Sub Form_MouseUp(Button As Integer, _
    Shift As Integer, X As Single, Y As Single)
    Select Case Button
        Case vbLeftButton
            If (X > 236 And X < 273) And (Y > 24 And Y < 41) Then
                Unload Me
            End If
    End Select
End Sub

Компилируем проект и... Нет, на CD-диск сбросим чуть-чуть позже. Сейчас мы напишем ма-а-а-ленький файл, который будет автоматически запускать нашу оболочку при вставке CD в дисковод. Откройте стандартный Блокнот и сделайте следующую запись:
[autorun]
OPEN=MusicCD.exe
И сохраните файл как AUTORUN.INF

Вот теперь с чистой совестью можно переносить файлы на CD. Еще раз напомню: в корневой директории должны лежать файлы autorun.inf, musiccd.exe и файлы плей-листов; а музыкальные файлы должны быть аккуратно разложены по папочкам.

Я, конечно, понимаю, что представленная в данной статье программа не является "высшим пилотажем" программистского искусства. Просто я пытался показать основы создания мультимедийных дисков, используя одно из основных преимуществ VB - быстроту создания приложений. Вы сами можете дальше модифицировать программу. Например, добавить графику в виде слайд-шоу, или вывод названия текущей песни в виде "бегущей" строки, или ... Ну в общем, что подскажет Вам Ваша фантазия.

Маленькое замечание на последок. Если Вы будете запускать данный диск ТОЛЬКО со своего компьютера - никаких проблем. Однако, если Вы предполагаете, что Вашим диском будут пользоваться Ваши друзья, а у них ОС ниже Windows Me или 2000 (т.е. отсутствуют библиотеки для VB6), создайте для этого отдельную папочку, куда сложите необходимые файлы. А это будут: msdxm.ocx, msvbvm60.dll, STDOLE2.TLB, REGSVR32.EXE, Reg.bat. Причем, Reg.bat Вам придется написать самому. Это несложно. В любом текстовом редакторе наберите:
regsvr32.exe msvbvm60.dll
regsvr32.exe msdxm.ocx
regsvr32.exe STDOLE2.TLB

И сохраните файл, как Reg.bat. Теперь даже при отсутствии необходимых библиотек на компьютере - нужно просто запустить Reg.bat.
Удачи!


Назад

Скачать пример

Hosted by uCoz