On-Line Библиотека www.XServer.ru - учебники, книги, статьи, документация, нормативная литература.
       Главная         В избранное         Контакты        Карта сайта   
    Навигация XServer.ru








 

5. Запись и воспроизведение видео

5.1. Обзор Video for Windows

5.2. Создание и редактирование avi-файлов

5.3. Работа с окном MCI

Эта глава посвящена системе Microsoft Video for Windows версии 1.1 (рис. 5.1), которая поставляется отдельно в качестве расширения для Microsoft Windows и Microsoft Windows for Workgroups. Новые версии операционной системы Windows, например, Windows NT версии 3.5, поставляются со встроенной системой Video for Windows Runtime, позволяющей проигрывать avi-файлы и другие мультимедиа-файлы.

5.1. Microsoft Video for Windows версии 1.1

Video for Windows предоставляет в распоряжение пользователей новую технологию работы со звуковой информацией, видеоинформацией и другими типами данных. С помощью Video for Windows пользователь может создавать файлы с расширением имени avi, содержащие одновременно несколько потоков данных. Например, в файле может храниться видеофильм со звуковым сопровождением на нескольких национальных языках. Во время воспроизведения пользователь может выбрать нужный ему язык, указав соответствующий поток звуковых данных.

В качестве источника видео можно использовать видеокамеру, подключенную к компьютеру через видеоадаптер. В этом случае для создания avi-файла следует использовать приложение VidCap . Можно также создать видеоролик из отдельных кадров, сохраненных в виде файлов в одном из нескольких наиболее популярных графических форматов, из анимационных файлов fli и flc в формате Autodesk Animation . В составе Video for Windows поставляется приложение Screen Capture, с помощью которого можно создавать демонстрационные ролики, "снимая" изменения на экране компьютера.

Что же касается звукового сопровождения, то есть возможность одновременной записи звука и видео, причем для ввода звука в этом случае используется обычный звуковой адаптер. Можно добавить звук позже в уже готовый avi-файл, "озвучив" его после съемки и монтажа. Для этого следует воспользоваться приложением VidEdit . Просматривать avi-файлы можно с помощью приложения Media Player .

Для создания приложений, работающих с Video for Windows, вам следует приобрести Video for Windows Development Kit версии 1.1 (рис. 5.2), а также транслятор Microsoft C++ версии 7.0 или Microsoft Visual C++ версий 1.0 или 1.5.

5.2. Video for Windows Development Kit версии 1.1

В состав Video for Windows Development Kit входит документация в виде гипертекста (Programmer Guide), набор библиотек и include-файлов, большое количество примеров приложений. Вместе с Video for Windows и Video for Windows Development Kit поставляется Video for Windows Runtime , который вы можете распространять вместе с разработанными вами приложениями или созданными вами avi-файлами. Кроме необходимых драйверов и dll-библиотек в состав Video for Windows Runtime входит приложение Media Player.

5.1. Обзор Video for Windows

Video for Windows содержит DLL-библиотеки и драйверы, обеспечивающие интерфейс между приложениями и устройствами мультимедиа, предназначенными для работы cо звуковыми данными и видеоданными.

Приложения, проигрывающие файлы мультимедиа (в том числе avi-файлы), могут воспользоваться драйвером mciavi.drv , предоставляющим в распоряжение приложения высокоуровневый интерфейс MCI. Однако более предпочтительно использование интерфейса, который обеспечивается библиотекой msvideo.dll . Эта библиотека является надстройкой над интерфейсом MCI, значительно упрощающей его использование. Она нужна не только для проигрывания, но и для записи. В этой главе мы приведем исходные тексты приложений, работающих через интерфейс библиотеки msvideo.dll.

Вызывая функции интерфейса Video for Windows, приложения не имеют дело с внутренней структурой avi-файлов, так как библиотека avifile.dll обеспечивает им всю необходимую поддержку.

Приложения, предназначенные для записи звуковых данных и видеоданных, могут воспользоваться удобным высокоуровневым интерфейсом, предоставляемым библиотекой avicap.dll . Создавая приложения для записи видео, вам не придется заботиться о внутренней структуре avi-файлов, о компрессии (сжатии) данных при записи, об интерфейсе с драйверами устройства (или устройств) записи. При необходимости, вы, тем не менее, можете воспользоваться интерфейсом более низкого уровня, который обеспечивается библиотекой avifile.dll.

Редакторы файлов мультимедиа могут использовать библиотеки avifile.dll и msvideo.dll для доступа к данным и средствам отображения, а также системам компресии данных.

В составе Video for Windows имеются две системы компресии.

Первая из них - устанавливаемый менеджер компресии ICM (Installable Compression Manager ) предназначен для сжатия и восстановления видеоданных в реальном времени. Он может восстанавливать сжатые данные динамически во время проигрывания avi-файла. При создании новых avi-файлов можно использовать различные алгоритмы компресии. Собственно компрессия и восстановление выполняются драйверами компресии. Несколько таких драйверов поставляется в составе Video for Windows. Имеется возможность создания новых драйверов компресии при помощи Video for Windows Development Kit.

Вторая система - звуковой менеджер компресии ACM (Audio Compression Manager ). Он выполняет компрессию и восстановление звуковых данных в реальном времени. Вы можете использовать для компресии звуковых данных алгоритмы, реализуемые готовыми драйверами, или созданными вами с помощью Video for Windows Development Kit.

Окно MCI

Библиотека msvideo.dll содержит определение класса окна MCI, на базе которого можно очень легко создавать приложения, управляющие устройствами для воспроизведения видео, воспроизведения и записи звуковых данных, воспроизведения MIDI, а также приложения, управляющие устройствами чтения компакт-дисков.

Окно MCI создать также просто, как и обычное окно. Более того, для его создания можно использовать привычную вам функцию CreateWindow , хотя есть и специальная функция MCIWndCreate . При создании окна вы можете использовать в дополнение к стандартным стилям окна некоторые другие. Например, вы можете указать, что окно MCI должно иметь набор органов управления для запуска проигрывания, записи, доступа к меню и полосу просмотра (рис. 5.3).

5.3. Окно MCI

Зная идентификатор окна MCI, вы можете управлять окном, используя набор макрокоманд, таких, как MCIWndRecord (включение режима записи) и MCIWndPlay (включение режима воспроизведения). Есть также средства для передачи окну обычных команд или командных строк MCI.

Вы можете создать окно MCI как перекрывающееся (overlapped) или дочернее (child), расположив его в любом месте экрана или родительского окна.

В большинстве случаев для проигрывания файлов мультимедиа возможности окна MCI более чем достаточны. Поэтому в нашей книге основное внимание мы уделим именно окну MCI.

Окно класса AVICap

Для создания приложений, записывающих видео, лучше всего воспользоваться классом окна AVICap , определенном в библиотеке avicap.dll . Создав окно на базе класса AVICap, приложение получит в свое распоряжение простой интерфейс для записи видео и звуковых данных в avi-файл, для предварительного просмотра видео и выполнения других операций.

В классе AVICap предусмотрены средства динамического переключения устройств записи видео и звука, что удобно в тех случаях, когда возможно поочередное использование нескольких таких устройств, установленных в компьютере. Приложение может создать avi-файл, предназначенный для записи, скопировать содержимое одного avi-файла в другой, установить частоту кадров, вывести на экран диалоговую панель, с помощью которой пользователь сможет задать формат записи. Есть средства для работы с палитрами и универсальным буфером обмена Clipboard.

Для записи звука класс окна AVICap пользуется срествами библиотеки mmsystem.dll, подробно рассмотренными нами ранее.

Драйвер mciavi.drv

Драйвер mciavi.drv предназначен для проигрывания файлов мультимедиа, содержащих звуковые данные и видео (как с поддержкой цветовых палитр, так и в режиме True Color). Звуковые данные могут быть моно- или стереофоническими с частотой дискретизации 44,1 Кгц, 22,05 Кгц или 11,025 Кгц. С помощью драйвера mciavi.drv можно проигрывать avi-файлы, содержащие звук и видео, только видео или только звук.

При воспроизведении видео со звуком возникает проблема синхронизации. К сожалению, производительность компьютера и особенно его видеоподсистемы не всегда оказывается достаточной для воспроизведения всех кадров, записанных в avi-файле, с нужной скоростью. В случае необходимости драйвер mciavi.drv пропускает некоторые кадры. Из-за инерционности зрения качество изображения во многих случаях остается при этом вполне удовлетворительным. Однако перерывы в воспроизведении звуковых данных или пропуски фрагментов звуковых данных недопустимы. Поэтому в процессе пропуска видеокадров драйвер mciavi.drv обеспечивает предварительную выборку звуковых данных и непрерывность воспроизведения звуковой информации.

В дополнение к командам MCI, рассмотренным нами ранее и предназначенным для управления звуковыми устройствами и устройствами чтения компакт-дисков, драйвер mciavi.drv позволяет использовать команды, имеющие отношение к воспроизведению видео. В частности, с помощью этих команд можно указать параметры окна, в котором будет выполняться просмотр видео. Однако, как мы уже говорили, самый простой способ проигрывания avi-файлов заключается в использовании интерфейса окна MCI вместо классического интерфейса MCI.

Средства для работы с avi-файлами

Файлы avi имеют довольно сложную внутреннюю структуру и состоят из большого числа вложенных фрагментов. Структура avi-файла приведена в документации, которая поставляется вместе с Video for Windows Development Kit. Мы не будем ее описывать, так как в большинстве случаев вам не потребуется выполнять непосредственное чтение или запись avi-файлов. Все функции, необходимые для работы с avi-файлами, имеются в библиотеке avifile.dll.

Заметим, что в отличие от, например, wav-файла, avi-файл может содержать несколько потоков данных, обрабатываемых одновременно. Все данные хранятся в виде блоков (кадров), причем для обеспечения непрерывности воспроизведения звуковых данных последние чередуются с видеоданными. Как правило, для сокращения объема avi-файла используются различные методы компресии, поэтому звуковые данные и видеоданные обычно хранятся в сжатом виде. Таким образом, сложность внутренней структуры avi-файла сильно затрудняет работу с ним на низком уровне без использования функций библиотеки avifile.dll.

Функции, предназначенные для работы с avi- и wav-файлами, определенные в библиотеке avifile.dll, позволяют работать на уровне потоков данных и кадров. Вы можете получать информацию об avi-файле и о потоках данных, читать и писать потоки данных, получать отдельные кадры, причем при необходимости эти данные будут автоматически разжаты или сжаты. Есть средства для копирования потоков из разных файлов, позиционирования внутри потока, создания временных потоков в оперативной памяти. Вы можете скопировать весь avi-файл или любую его часть в Clipboard.

В распоряжении приложений есть функции GetOpenFileNamePreview и GetSaveFileNamePreview , аналогичные по своему назначению функциям GetOpenFileName и GetSaveFileName библиотеки commdlg.dll, но дополнительно обеспечивающие возможность предварительного просмотра avi-файлов или прослушивания wav-файлов. Мы используем функцию GetOpenFileNamePreview в приложении MCIWNDC, исходные тексты которого приведены в этой главе.

Компрессия данных

Для компресии видеоданных можно использовать один из компрессоров , поставляемых вместе с Video for Windows, или приобретенный отдельно.

Если видеоизображение содержит большие площади однотонного цвета, хорошие результаты получаются при использовании метода компресии Microsoft RLE . Этим методом имеет смысл пользоваться для сжатия видеофильмов, записанных с экрана компьютера при помощи приложения Screen Capture. Особенно хорошие результаты получаются в том случае, если изображение меняется от кадра к кадру не очень сильно.

Метод компресии Cinepak Codek дает хорошие результаты при необходимости подготовить avi-файл для записи на компакт-диск со скоростью передачи данных 150 Кбайт в секунду (одинарная скорость). Для хранения видеоданных используется формат True Color (в нем для представления цвета используются 24 бита данных). При необходимости воспроизведения в режимах более низкого цветового разрешения выполняется автоматическое преобразование цветов и, если это нужно, создание цветовых палитр. Учтите, что процесс сжатия изображения может длиться часами даже при использовании высокопроизводительного компьютера.

Более быстро, хотя и не так качественно, как Cinepak Codek, работает метод Microsoft Video 1 . При использовании этого метода вы можете выбрать 8-битовый или 16-битовый формат для храненеия цвета.

Метод Intel Indeo Video R3.1 хранит изображения в формате True Color. Формат видеоданных совместим с видеоадаптером Smart Video Recorder, позволяющим получать при записи сжатые данные в реальном времени.

Создавая avi-файл, рекомендуется попробовать несколько методов и остановиться на том, который обеспечивает хорошее качество при приемлимых размерах файла.

Приложения могут обращаться непосредственно к менеджеру ICM для сжатия и восстановления видеоданных, причем ICM по запросу приложения может вывести восстановленные данные на экран. Как правило, явное обращение к ICM требуется только для приложений, редактирующих видеоданные. Средства записи и воспроизведения видео, предоставляемые окнами AVICap и MCI, выполняют компрессию автоматически в прозрачном для приложения режиме.

Аналогично используется компрессор звуковых данных ACM. Система ACM может выполнять не только компрессию и восстановление звуковых данных, но также преобразование и фильтрацию (например, с помощью соответствующего фильтра можно добавить эхо). ACM устанавливается между приложением и библиотекой mmsystem.dll и работает с помощью механизма перехвата вызовов этой библиотеки. Для выполнения преобразований формата ACM обращается к драйверам преобразования формата, которые устанавливаются в системе вместе с Video for Windows или дополнительно.

Пользователь может управлять системой ACM при помощи приложения Sound Mapper , которое доступно из Control Panel после установки Video for Windows (рис. 5.4).

5.4. Настройка параметров приложения Sound Mapper

В поле Sound Mapper Drivers отображается список установленных драйверов и их приоритет (который можно изменить, воспользовавшись кнопкой "Priority..."). Для работы будет выбран первый подходящий по своим возможностям драйвер, причем выбор будет выполняться с учетом приоритетов.

В поле Sound Device Preferences можно выбрать устройство для проигрывания или записи (если их несколько).

Систему ACM можно рассматривать как расширение библиотеки mmsystem.dll, обеспечивающее возможность работы с новыми форматами звуковых данных. Когда приложение пытается открыть устройство, поддерживающее тот или иной формат звуковых данных, ACM либо предоставляет приложению физическое устройство, либо подбирает компрессор или декомпрессор, преобразующий указанный формат в один из форматов, поддерживаемых физическим устройством.

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

Функции для рисования битовых изображений DIB

Video for Windows добавляет в Windows программный интерфейс, с помощью которого приложения могут рисовать изображения DIB на экране. Имена этих функций начинаются с DrawDib , что, очевидно, говорит об их назначении. Функция DrawDibDraw может все, что может функция StretchDIBits , однако работает быстрее. Дополнительно при отображении вызывается система ICM, выполняющая восстановление сжатых изображений непосредственно перед выводом на экран. Если исходное изображение имеет формат True Color, а устройство вывода обладает средним или низким цветовым разрешением, функции выполняют рисование с использованием смешивания (dithering) цветов.

5.2. Создание и редактирование avi-файлов

Перед тем как приступить к изучению программного интерфейса Video for Windows (вернее, его небольшой части, касающейся окна MCI) неплохо было бы научиться создавать и редактировать avi-файлы, пользуясь утилитами, входящими в состав Video for Windows и Video for Windows Development Kit. Существует несколько способов создания avi-файлов, и не все они связаны с использованием видеокамеры и адаптера для ввода изображения. Даже если у вас нет оборудования для ввода в компьютер видео, все равно вы можете создавать мультфильмы и демонстрационные ролики.

Создание видео из отдельных кадров

Подготовьте несколько десятков или сотен (а может быть, тысяч?) bmp-файлов, содержащих отдельные кадры мультфильма. Имена файлов должны оканчиваться их порядковым номером, например, pic001.bmp, pic002.bmp, ..., pic867.bmp и т. д.. Разумеется, размеры и цветовое разрешение всех кадров должны быть одинаковые, а что же касается содержимого, тут можно полностью положиться на ваш вкус. Если кадры должны сменяться, например, десять раз в секунду, то для создания десятисекундного мультфильма вам нужно подготовить "всего" сто рисунков.

Запустите приложение VidEdit , которое поставляется в составе Video for Windows (рис. 5.5).

5.5. Редактор avi-файлов VidEdit

С помощью меню "File" вы можете загрузить для редактирования готовый avi-файл (строка "Open...") или создать новый (строка "New"). Для создания avi-файла из последовательности bmp-файлов выберите из этого меню строку "Insert...". В списке "List Files of Type" появившейся диалоговой панели "Insert File" выберите строку "DIB Sequence".

Замените в поле "File Name" шаблон *.dib на *.bmp и выберите первый файл из подготовленной вами последовательности. Укажите формат файла как "DIB Sequence" и нажмите кнопку "OK". Последовательность bmp-файлов будет преобразована в avi-файл.

Сохраните созданный файл, выбрав из меню "File" строку "Save As...". На экране появится диалоговая панель "Save Video File", напоминающая стандартную диалоговую панель "Save As" из библиотеки commdlg.dll. Единственное существенное отличие заключается в том, что при помощи кнопки "Compression Options..." вы можете задать алгоритм сжатия, который будет использован при сохранении avi-файла (рис. 5.6).

5.6. Диалоговая панель для выбора алгоритма сжатия

Для начала используйте параметры, указанные на рис. 5.6. При необходимости вы можете изменить скорость воспроизведения видео, выбрав в меню "Video" строку "Synchronize...". На экране появится диалоговая панель "Synchronize", предназначенная для выполнения синхронизации видео и звука (рис. 5.7).

5.7. Диалоговая панель "Synchronize"

Изменив значение частоты кадров в поле "Video Speed", вы измените скорость воспроизведения видео.

Последовательность bmp-файлов (а также отедльные bmp-файлы) можно вставлять в любое место видео. Кроме графических файлов в формате DIB, редактор VidEdit позволяет вставлять отдельные изображения в форматах PC Paintbrush, TIFF, TGA, GIF и других популярных графических форматов.

Создание avi-файла из файлов анимации

С помощью строки "Insert..." меню "File" вы можете вставить flc - или fli -файлы анимации в формате Autodesk Animation , подготовленные, например, с помощью таких программ, как 3D-Studio или Autodesk Animator. Для этого в списке "List Files of Type" диалоговой панели "Insert File" выберите строку "Autodesk Animation" и укажите нужный файл. Он будет преобразован в формат avi.

Запись в avi-файл содержимого области экрана

В состав Video for Windows входит приложение Screen Capture , с помощью которого вы можете создавать демонстрационные и рекламные ролики, записывая в avi-файл изображение любой области экрана.

Запустите приложение Screen Capture. Оно появится на экране в виде пиктограммы. Установите на эту пиктограмму курсор и сделайте щелчок левой клавишей мыши. Появится меню (рис. 5.8).

5.8. Меню приложения Screen Capture

Выберите строку "Set Capture File..." и с помощью появившейся диалоговой панели выберите avi-файл, в который будет записан видеоролик. Затем нужно указать область экрана, содержимое которой будет записано в avi-файл. Так как производительность компьютера может оказаться недостаточной для записи крупноформатного видео, в документации рекомендуется использовать область размером не больше чем 320 х 240 пикселов.

Затем выберите строку "Preferences..." и задайте режимы работы приложения (рис. 5.9).

5.9. Диалоговая панель "Preferences"

В поле "Frame Rate" укажите частоту кадров. Если вместе с записью видео нужно выполнять запись звуковых данных, включите переключатель "Capture Audio" и укажите нужный формат звуковых данных, нажав на кнопку "Change...". По умолчанию для остановки процесса записи используется клавиша <Esc>. Вы можете заменить ее на другую в поле "Stop Recording Key".

Для запуска процесса записи выберите строку "Capture!" в меню приложения Screen Capture. Начнется запись видео и, возможно, звуковых данных.

Запись с помощью видеоадаптера

Для того чтобы создавать полноценные видеофрагменты, вам следует приобрести специальный видеоадаптер для ввода видеосигнала. В продаже есть два принципиально разных типа таких адаптеров. Простейшие видеоадаптеры, которые мы отнесем к первому типу, позволяют записывать лишь отдельные кадры. В некоторых случаях этого достаточно (например, вы сможете снять "пластилиновый" мультфильм, составив его из множества отдельных кадров). Видеоадаптеры второго типа способны записывать поток видеоинформации в реальном масштабе времени, причем одновременно выполняется компрессия данных.

Приобретая видеоадаптер поинтересуйтесь, сможете ли вы с помощью этого адаптера записывать видео в реальном масштабе времени с компрессией данных, или же вам будет доступна только запись отдельных кадров. Кроме того, очень важно, чтобы вместе с видеоадаптером поставлялся драйвер для Windows версии 3.1, способный работать вместе с Microsoft Video for Windows версии 1.1. Только тогда вы сможете без проблем записывать avi-файлы, подключив к видеоадаптеру лазерный проигрыватель видеодисков, видеокамеру или видеомагнитофон. В противном случае вам придется создавать avi-файл из отдельных кадров, что не всегда приемлимо и отнимает очень много времени.

Для создания avi-файла с помощью видеоадаптера вам следует использовать приложение VidCap , которое поставляется вместе с Video for Windows. Это приложение способно работать в трех режимах: в режиме покадровой записи, в автоматическом режиме и в автоматическом режиме с автоматическим же управлением лазерным проигрывателем видеодисков или видеомагнитофоном.

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

Второй режим удобен для записи видеофильмов непосредственно в avi-файл. Учтите, что размер созданного файла может достигать в зависимости от продолжительности записи и метода компрессии десятков и сотен мегабайт, поэтому подготовьте быстродействующий диск соответствующего размера. Важное значение имеет также производительность процессора, поэтому компьютер с процессором i386 едва ли подойдет для записи видео в реальном масштабе времени.

Третий режим доступен в том случае, если источник видеосигнала (лазерный проигрыватель или видеомагнитофон) имеет возможность дистанционного управления от компьютера с использованием интерфейса MCI. В этом режиме приложение VidCap способно управлять устройством и позиционировать носитель данных.

Если вас по каким-либо причинам не устраивают возможности приложения VidCap, вы можете создать собственное при помощи Video for Windows Development Kit на базе окна класса AVICap . Примеры приложений, выполняющих запись видео (которые называются Cap Test и CapCPP ), поставляются с исходными текстами в составе Video for Windows Development Kit.

Озвучивание видео

Вы можете записать звук одновременно с записью видео, или добавить его позже при помощи приложения VidEdit. Для добавления звука в "немое" видео откройте avi-файл из приложения VidEdit и выберите из меню "File" строку "Insert...". В списке "List Files of Type" появившейся диалоговой панели "Insert File" выберите строку "Microsoft Waveform". Далее укажите wav-файл, содержащий добавляемый звук.

Все! Файл озвучен и его нужно сохранить. Полезно также перед озвучиванием сделать копию исходного файла.

В некоторых случаях вам может потребоваться выполнить синхронизацию видео и звукового сопровождения. Для выполнения синхронизации используйте диалоговую панель "Synchronize" (рис. 5.7). В этой диалоговой панели вы можете задать скорость проигрывания видео и смещение звуковых данных относительно начала фильма в миллисекундах (в поле Audio Offset).

5.3. Работа с окном MCI

В этом разделе мы научимся создавать приложения для проигрывания файлов мультимедиа и дорожек компакт-дисков (а также для записи звуковых файлов) с использованием окна MCI.

Однако перед тем как приступить к описанию способов работы с этим окном, рассмотрим пример простейшего приложения, использующего окно MCI для проигрывания файлов мультимедиа.

Приложение MCIWND

Приложение MCIWND создает окно MCI (рис. 5.10) и... все!

5.10. Окно MCI

Это окно, когда в него ничего не загружено, имеет стандартный заголовок и три органа управления - кнопку воспроизведения, кнопку доступа к меню и полосу просмотра.

Запустите загрузочный модуль этого приложения и нажмите кнопку доступа к меню (рис. 5.11).

5.11. Кнопка доступа к меню

На экране появится почти стандартная диалоговая панель "Open", с помощью которой вы сможете выбрать файл мультимедиа для просмотра или прослушивания (рис. 5.12).

5.12. Диалоговая панель "Open"

Обратите внимание, что в правом нижнем углу диалоговой панели имеются органы управления (кнопка и полоса просмотра), предназначенные для предварительного просмотра или прослушивания содержимого файла. Это очень удобно, так как при поиске файла не нужно много раз открывать и закрывать диалоговую панель "Open".

После загрузки wav-файла меню приложения модифицируется (рис. 5.13).

5.13. Меню для работы с wav-файлом

В нем появляется строка "Close", с помощью которой можно закрыть файл, строка "Copy", позволяющая скопировать содержимое файла в Clipboard, а также строка "Command...". Последняя предназначена для передачи устройству произвольной управляющей строки MCI (соответствующая диалоговая панель показана на рис. 5.14).

5.14. Диалоговая панель для передачи управляющей строки MCI

При выборе avi-файлов можно посмотреть их содержимое в небольшом окне (рис. 5.15).

5.15. Выбор avi-файла

Для работы с avi-файлами используется расширенное меню (рис. 5.16).

5.16. Меню для работы с avi-файлами

Строка "View" предназначена для управления размером окна. С помощью строк "Volume" и "Speed" можно регулировать, соответственно, громкость звука и скорость воспроизведения видео. Строка "Configure..." предназначена для установки параметров проигрывателя. При ее выборе на экране появляется диалоговая панель "Video Playback Options" (рис. 5.17).

5.17. Диалоговая панель "Video Playback Options"

В поле "Video Mode" вы можете включить режим отображения видео в окне (переключатель "Window") или на полном экране видеомонитора (переключатель "Full Screen"). Переключатель "Zoom by 2" позволяет уменьшить размер окна в два раза.

Если включен переключатель "Skip video frames if behind", для обеспечения непрерывности звука при необходимости будут пропускаться видеокадры.

Таким образом, приложение MCIWND выполняет довольно много функций. Вы, возможно, будете удивлены тем, что исходный текст приложения занимает не более двух страниц (листинг 5.1).


Листинг 5.1. Файл mciwnd/mciwnd.c


#include <windows.h>
#include <vfw.h>

static char szAppName[]="MCIWnd";
static HWND hwnd;

// =====================================
// Функция WinMain
// =====================================
int PASCAL
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        LPSTR lpszCmdLine, int nCmdShow)
{
   MSG msg;
   WORD wVersion;

   // Проверяем версию Video for Windows
   wVersion = HIWORD(VideoForWindowsVersion());
   if(wVersion < 0x010a)
   {
     MessageBox(NULL, "Используйте Video for Windows"
        " версии 1.1 или более поздней версии",
        "MCIWnd Error", MB_OK | MB_ICONHAND);
     return FALSE;
   }

   // Создаем окно класса MCIWND
   hwnd = MCIWndCreate(NULL, hInstance,
            MCIWNDF_SHOWNAME | MCIWNDF_SHOWMODE |
            WS_OVERLAPPEDWINDOW | WS_VISIBLE, NULL);

   if(hwnd == NULL)
     return -1;

   // Устанавливаем заголовок окна
   SetWindowText(hwnd, szAppName);

   // Запускаем цикл обработки сообщений
   while(GetMessage(&msg,NULL,0,0))
   {
      TranslateMessage(&msg);
      DispatchMessage(&msg);

      if(!IsWindow(hwnd))
          PostQuitMessage(0);
   }
   return msg.wParam;
}

Исходный текст приложения подготовлен для трансляторов Microsoft C++ версии 7.0 или Microsoft Visual C++ версий 1.0 или 1.5, так как поставляющаяся в составе Video for Windows Development Kit библиотека vfw.lib совместима именно с этими трансляторами.

После файла windows.h в исходный текст необходимо включить файл vfw.h , который поставляется вместе с Video for Windows Development Kit. Он содержит определения всех необходимых констант, структур данных и прототипы функций.

В самом начале работы приложение вызывает функцию VideoForWindowsVersion , возвращающую в старшем слове версию Video for Windows:

wVersion = HIWORD(VideoForWindowsVersion());

Версия Video for Windows должна быть не ниже 1.1.

Далее приложение создает окно MCI, вызывая для этого функцию MCIWndCreate :

hwnd = MCIWndCreate(NULL, hInstance,
         MCIWNDF_SHOWNAME | MCIWNDF_SHOWMODE |
         WS_OVERLAPPEDWINDOW | WS_VISIBLE, NULL);

Функция MCIWndCreate позволяет определить обычные стили окна, такие как WS_OVERLAPPEDWINDOW и WS_VISIBLE, а также специфические для окна MCI - MCIWNDF_SHOWNAME и MCIWNDF_SHOWMODE. Позже мы рассмотрим подробнее эту функцию и дополнительные стили окна.

После создания окна запускается цикл обработки сообщений, который имеет одну особенность - в нем периодически вызывается функция IsWindow , которая определена в стандартном программном интерфейсе Windows:

if(!IsWindow(hwnd)) PostQuitMessage(0);

Эта функция проверяет идентификатор окна, передаваемого ей через параметр. Если этот идентификатор правильный, возвращается TRUE. После того как пользователь уничтожит окно MCI, его идентификатор станет недействительным. В этом случае функция IsWindow вернет значение FALSE и будет вызвана функция PostQuitMessage, в результате чего работа приложения завершится.

Вот и все! По сложности исходного текста это приложение напоминает наши первые приложения из 10 тома "Библиотеки системного программиста", однако выполняемые им функции во много раз сложнее. Все дело тут, разумеется, в реализации класса окна MCI.

Файл описания ресурсов приведен в листинге 5.2.


Листинг 5.2. Файл mciwnd/mciwnd.rc


AppIcon  ICON  mciwnd.ico

Файл определения модуля для приложения MCIWND не имеет никаких особенностей (листинг 5.3).


Листинг 5.3. Файл mciwnd/mciwnd.def


NAME        MCIWNDPL
DESCRIPTION 'Приложение MCIWND, (C) 1994, Frolov A.V.'
EXETYPE     windows
STUB        'winstub.exe'
STACKSIZE   8196
HEAPSIZE    1024
CODE        preload moveable discardable
DATA        preload moveable multiple

Теперь о том, как из исходного текста создать загрузочный модуль приложения MCIWND.

При использовании транслятора Microsoft C++ версии 7.0 вы можете воспользоваться файлом makefile , представленном в листинге 5.3.


Листинг 5.3. Файл mciwnd/makefile


NAME = mciwnd
OBJ  = mciwnd.obj
LIBS = libw slibcew vfw

!if "$(DEBUG)" == "NO"
DEF     =
CLOPT   =
MASMOPT =
LINKOPT =
!else
DEF     = -DDEBUG
CLOPT   = -Zid
MASMOPT = -Zi
LINKOPT = /CO/LI
!endif

CC  = cl -c -W3 -AS -Zp -G2sw -Oxas $(DEF) $(CLOPT) -DWIN31
ASM = masm -Mx $(MASMOPT)
LINK= link /NOE/NOD/LI/MAP/AL:16/ONERROR:NOEXE $(LINKOPT)
RC  = rc 
.c.obj:
        $(CC) $*.c
.asm.obj:
        $(ASM) $*;
goal: $(NAME).exe
$(NAME).exe: $(OBJ) $(NAME).res $(NAME).def makefile
        $(LINK) $(OBJ), $(NAME), $(NAME),$(LIBS), $(NAME).def
        $(RC) -31 $(NAME).res
        -mapsym $(NAME).map
$(NAME).res: $(NAME).rc $(NAME).ico
        $(RC) -r $(NAME).rc
clean:
        del $(NAME).exe
        del *.res
        del *.obj
        del *.map
        del *.sym
        del *.pdb
copy:
        copy $(NAME).exe ..\..\bin
        copy $(NAME).sym ..\..\bin
depend:
        mv makefile makefile.old
        sed "/^# START Dependencies/,/^# END Dependencies/D" makefile.old > makefile
        del makefile.old
        echo # START Dependencies >> makefile
        includes -l *.c *.asm >> makefile
        echo # END Dependencies >> makefile

Особенностью транслятора Microsoft C++ версии 7.0 (а также версии 8.0, входящей в состав Visual C++, и трансляторов более ранних версий, запускаемых в среде MS-DOS) является использование переменных среды. Для правильной установки переменных среды подготовьте bat-файл, содежащий следующие команды (предполагается, что транслятор установлен в каталоге g:msvc, а Video for Windows Development Kit - в каталоге g:\vfwdk):

@echo off
set TOOLROOTDIR=G:\MSVC
set PATH=G:\MSVC\BIN;%PATH%
set INCLUDE=G:\MSVC\INCLUDE;g:\vfwdk\inc;%INCLUDE%
set LIB=G:\MSVC\LIB;g:\vfwdk\lib;g:\windev\lib;%LIB%
set INIT=G:\MSVC;%INIT%

Находясь в среде MS-DOS, сделайте текущим каталог, содержащий все файлы приложения MCIWND, и, после запуска приведенного выше пакетного файла, запустите программу nmake без параметров. В результате будет создан загрузочный модуль приложения.

Для того чтобы загрузочный модуль не содержал отладочной информации, добавьте в начало файла makefile следующую строку:

DEBUG = NO

Можно также запустить программу nmake с параметром DEBUG=NO:

nmake DEBUG=NO

Намного удобнее работать в среде Visual C++. Вместе с исходными текстами приложения MCIWND на дискете поставляется файл проекта mciwnd.mak, предназначенный для системы Visual C++.

Запустите Visual C++ и из меню "Project" выберите строку "Open...". С помощью появившейся диалоговой панели откройте файл проекта mciwnd.mak. Нажмите на самую левую кнопку в полосе инструментов. Появится список файлов, имеющих отношение к проекту. Выберите файл исходного текста. Возможно, что при этом вместо русских букв в окне редактирования вы увидите нечто, не поддающееся прочтению. В этом случае следует установить для редактора шрифт с русскими буквами.

Для изменения шрифта сделайте текущим окно редактирования и выберите в меню "Options" строку "Font...". На экране появится диалоговая панель "Font". Выберите в ней подходящий шрифт, имеющий русские буквы, и нажмите кнопку "Use as Default Font". При этом для всех создаваемыех вновь окон будет использоваться выбранный вами шрифт. Для завершения работы с диалоговой панелью нажмите кнопку "OK".

Не забудьте добавить пути к каталогам vfwdk\inc, wfwdk\lib и windev\lib с помощью диалоговой панели "Directories", которую можно вызвать, если в меню "Options" выбрать строку "Directories...".

После всех этих подготовительных действий выберите из меню "Project" строку "Build MCIWND.EXE". Будет запущен процесс создания загрузочного модуля (в фоновом режиме). После завершения этого процесса можно запустить приложение, выбрав из этого же меню строку "Execute MCIWND.EXE", или перейти в режим отладки, воспользовавшись меню "Debug".

Использование класса окна MCI

Приложение может создать окно MCI, указав его параметры, управлять им с помощью передачи сообщений через удобный в использовании набор макрокоманд и функций, а также удалить окно MCI. Этих функций и макрокоманд так много, что мы не можем описать их все подробно из-за ограниченного объема нашей книги. Рассмотрим некоторые, самые полезные на наш взгляд, функции и макрокоманды, предназначенные для работы с окном MCI. Полную информацию вы сможете найти в документации, которая поставляется вместе с Video for Windows Development Kit.

Создание окна

Для создания окна MCI проще всего воспользоваться функцией MCIWndCreate .

Функция MCIWndCreate

HWND MCIWndCreate(
   HWND hwndParent,     // идентификатор родительского окна
   HINSTANCE hInstance, // идентификатор приложения
   DWORD dwStyle,       // стиль окна
   LPSTR szFile);       // имя устройства или путь к файлу

Параметры функции:

hwndParent

Через этот параметр приложение передает функции идентификатор родительского окна, то есть окна, создавшего окно MCI. Если родительского окна нет, в качестве этого параметра можно указать NULL

hInstance

Идентификатор приложения, полученных через параметры функции WinMain или LibMain (для DLL-библиотеки)

dwStyle

Стиль создаваемого окна. Можно указывать стили, стандартные для функции CreateWindow, а также дополнительные, список которых приведен ниже. Если стандратные стили не указаны (что допустимо), то если есть родительское окно, используются стили WS_CHILD, WS_BORDER, и WS_VISIBLE. Если же параметр hwndParent указан как NULL, используются стили WS_OVERLAPPEDWINDOW и WS_VISIBLE. Для создания невидимого окна следует использовать один из стандартных стилей, например, WS_CHILD

szFile

Указатель на текстовую строку, содержащую имя устройства (например, "cdaudio") или путь к файлу

Возвращаемое значение:

Идентификатор созданного окна при успешном завершении или NULL при ошибке

Привдем список дополнительных стилей, которые можно использовать при создании окна MCI.

СтильОписание
MCIWNDF_NOAUTOSIZEWINDOW Размер окна не изменяется при изменении размера изображения
MCIWNDF_NOAUTOSIZEMOVIE При изменении размеров окна не следует выполнять масштабирование изображения для полного заполнения внутренней области окна
MCIWNDF_NOPLAYBAR Если задан этот стиль, не отображается полоса просмотра
MCIWNDF_NOMENU Не отображается кнопка для доступа к меню
MCIWNDF_RECORD Отображается кнопка записи, в меню добавляется строка "New"
MCIWNDF_NOERRORDLG При возникновении ошибки на экран не выводится диалогоая панель с описанием этой ошибки. Приложение может получить описание самой последней возникшей ошибки при помощи функции MCIWndGetError
MCIWNDF_NOTIFYMODE При изменении режима родительское окно получит извещающее сообщение MCIWNDM_NOTIFYMODE
MCIWNDF_NOTIFYPOS При изменении текущей позиции приложение получит извещающее сообщение MCIWNDM_NOTIFYPOS
MCIWNDF_NOTIFYMEDIA При замене носителя данных (например, звукового компакт-диска) приложение получит извещающее сообщение MCIWNDM_NOTIFYMEDIA
MCIWNDF_NOTIFYSIZE Родительское окно получит извещающее сообщение MCIWNDM_NOTIFYSIZE при изменении размера окна MCI
MCIWNDF_NOTIFYERROR При возникновении ошибки родительское окно получит сообщение MCIWNDM_NOTIFYERROR
MCIWNDF_NOTIFYALL Окно MCI будет извещать родительское окно в случае возникновения любых событий
MCIWNDF_SHOWNAME В заголовке окна будет отображаться имя устройства или путь к файлу
MCIWNDF_SHOWPOS В заголовке окна будет отображаться текущая позиция
MCIWNDF_SHOWMODE В заголовке окна будет отображаться текущий режим работы
MCIWNDF_SHOWALL Будут использованы все возможности окна MCI (то есть все органы управления, отображение информации в заголовке и т. д.)

Другой способ создания окна MCI заключается в регистрации класса окна MCIWND_WINDOW_CLASS функцией MCIWndRegisterClass , не имеющей парамеров, и создании на базе этого класса окна функцией CreateWindow . В случае успеха функция MCIWndRegisterClass возвращает значение FALSE.

Удаление окна

Если окно MCI больше не нужно, его можно удалить макрокомандой MCIWndDestroy . Идентификатор удаляемого окна MCI передается этой функции в качестве единственного параметра:

#define MCIWndDestroy(hwnd) (VOID)MCIWndSM(hwnd, WM_CLOSE, 0, 0)

Макро MCIWndSM определяется как функция SendMessage (см. файл mciwnd.h, поставляемый вместе с Video for Windows Development Kit и включаемый в файл vfw.h).

Для того чтобы закрыть устройство, открытое ранее в окне MCI без удаления окна, используйте макрокоманду MCIWndClose, передав ей идентификатор окна.

Загрузка файла или выбор устройства

При создании окна MCI вы можете указать имя устройства или файл мультимедиа, передав указатель на соответствующую текстовую строку через последний параметр функции MCIWndCreate. Можно использовать и другие способы.

Макрокоманда MCIWndOpen позволяет для созданного ранее окна открыть устройство или файл, например:

MCIWndOpen(hwnd, "push.wav", MCIWNDOPENF_NEW);

Через первый параметр передается идентификатор окна MCI, через второй - указатель на строку, содержащую имя устройства или файла. В третьем параметре при создании нового файла нужно указать флаг MCIWNDOPENF_NEW .

Напомним, что закрыть устройство или файл можно с помощью макрокоманды MCIWndClose .

Функция MCIWndOpenDialog позволяет вывести на экран диалоговую панель, с помощью которой пользователь может выбрать файл и загрузить его в окно MCI. В качестве единственного параметра этой функции следует передать идентификатор окна MCI. Функция возвращает значение 0L (размером в двойное слово) в случае успеха или код ошибки.

Для выбора файла можно также использовать функцию GetOpenFileNamePreview , входящую в программный интерфейс Video for Windows и аналогичную функции GetOpenFileName из библиотеки commdlg.dll . Диалоговая панель, появляющаяся на экране при вызове этой функции, содержит окно для предварительного прослушивания или просмотра файла (рис. 5.15).

Новый файл создается макрокомандой MCIWndNew , которой в качестве первого параметра следует передать идентификатор окна MCI, а в качестве второго - указатель на текстовую строку, содержащей имя устройства. Пример использования этой макрокоманды ести в приложении MCIWNDC, которое мы скоро рассмотрим.

Управление проигрыванием

Макрокоманда MCIWndPlay включает режим проигрывания для окна MCI, идентификатор которого передается ей в качестве единственного параметра.

Если вам нужно начать проигрывание с заданной позиции, воспользуйтесь макрокомандой MCIWndPlayFrom . Первый параметр этой макрокоманды задает идентификатор окна MCI, второй (размером в двойное слово) - позицию для начала проигрывания. Есть возможность задать конечную позицию. Макрокоманда MCIWndPlayFromTo , имеющая три параметра, аналогична макрокоманде MCIWndPlayFrom , но позволяет через третий параметр задать конечную позицию, при достижении которой проигрывание будет остановлено.

Вы даже можете запустить проигрывние в обратную сторону - от конца к началу файла (если драйвер устройства позволит вам это сделать). Достаточно вызвать макрокоманду MCIWndPlayReverse . Она имеет один параметр (идентификатор окна MCI) и запускает проигрывание от текущей позиции к началу файла.

Макрокоманда MCIWndSetRepeat позволяет включить режим циклического проигрывания. Через первый параметр этой макрокоманде передается идентификатор окна MCI, через второй для включение режима циклического проигрывания нужно передать значение TRUE.

Макрокоманды MCIWndStop и MCIWndPause предназначены для выполнения, соответственно, останова и временного останова проигрывания. Для того чтобы продолжить проигрывание после временного останова, используйте макрокоманду MCIWndResume . Все три макрокоманды имеют только один параметр - идентификатор окна MCI.

Управление записью и сохранение данных

Для включения режима записи с текущей позиции предназначена макрокоманда MCIWndRecord . В качестве единственного параметра ей нужно передать идентификатор окна MCI. С помощью этой макрокоманды вы сможете организовать запись звуковых данных (как это сделано в нашем приложении MCIWNDC, которое мы рассмотрим чуть позже).

С помощью окна MCI вы не можете записывать avi-файлы, для этого предназначено окно класса AVICap.

Для сохранения записанных данных можно воспользоваться макрокомандами MCIWndSave или MCIWndSaveDialog .

Макрокоманда MCIWndSave имеет два параметра - идентификатор окна MCI и указатель на текстовую строку, в которой должен находиться путь к файлу. Записанные данные будут сохранены в этом файле.

При вызове макрокоманды MCIWndSaveDialog , имеющий один параметр (идентификатор окна MCI) на экран выводится диалоговая панель, позволяющая пользователю сохранить данные в файле. Это модифицированная диалоговая панель "Save As..." с возможностью предварительного просмотра или прослушивания содержимого файлов мультимедиа. Кстати, эту же панель вы можете вывести и отдельно с помощью функции GetSaveFileNaamePreview , аналогичной функции GetSaveFileName из библиотеки commdlg.dll.

Позиционирование

Макрокоманда MCIWndSeek позволяет установить новую позицию для окна MCI, идентификатор которого передается ей в качестве первого параметра (здесь имеется в виду не расположение окна MCI на экране, а текущая позиция при проигрывании мультимедиа-файла). Через второй параметр передается значение новой позиции в формате двойного слова.

Макрокоманды MCIWndHome и MCIWndEnd позволяют установить текущую позицию, соотетственно, в начало и конец. Обе эти макрокоманды имеют только один параметр - идентификатор окна MCI.

С помощью макрокоманды MCIWndStep можно выполнить продвижение текущей позиции на один шаг. Величина шага задается в формате двойного слова в качестве второго параметра. Первый параметр - как всегда, идентификатор окна MCI.

Другие макрокоманды

Перечислим некоторые другие полезные макрокоманды, имеющие отношение к окну MCI.

Макрокоманды MCIWndCanConfig , MCIWndCanEject , MCIWndCanPlay , MCIWndCanRecord , MCIWndCanSave , MCIWndCanWindow позволяют определить, соответственно, возможность конфигурирования, автоматической смены носителя, проигрывания, записи, сохранения и проигрывания в окне. Все эти макрокоманды имеют один параметр - идентификатор окна MCI. Если та или иная возможность поддерживается, соответствующая макрокоманда возвращает значение TRUE, в противном случае FALSE.

В любой момент времени приложение может изменить стиль окна MCI, вызвав макрокоманду MCIWndChangeStyles . Пример испльзования этой макрокоманды есть в приложении MCIWNDC (см. ниже). Для определения текущего стиля окна MCI можно воспользоваться макрокомандой MCIGetStyles .

Несколько макрокоманд предназначены для определения характеристик файла или такого носителя данных, как звуковой компакт-диск, загруженного в окно MCI. С помощью макрокоманд MCIWndGetLength , MCIWndGetStart , MCIWndGetEnd , MCIWndGetPosition , MCIWndGetPositionString приложение может определить, соотетственно, длину файла, начальную позицию, конечную позицию, текущую позицию и текущую позицию в виде текстовой строки.

Приложение может установить скорость проигрывания, громкость и размеры окна MCI, вызвав, соответственно, макрокоманды MCIWndSetSpeed , MCIWndSetVolume , MCIWndSetZoom . Есть макрокоманды, с помощью которых можно определить текущее значение для скорости проигрывания, громкости и размеров окна MCI - MCIWndGetSpeed , MCIWndGetVolume и MCIWndGetZoom .

Есть макрокоманды для изменения формата времени и определени текущего формата времени (MCIWndSetTimeFormat , MCIWndGetTimeFormat , MCIWndUseFrames , MCIWndUseTime ), для обновления информации о позиции при замене носителя данных (MCIWndValidateMedia ), для работы с таймером, палитрами и некоторые другие.

Если же этого обширного списка все же не хватит, то с помощью макрокоманды MCIWndSendString вы сможете передать окну любую команду MCI, лишь бы ее поддерживало используемое устройство. Ответ драйвера на посланную команду можно получить в виде текстовой строки при помощи макрокоманды MCIWndReturnString .

Извещения для родительского окна

При создании окна MCI вы можете указать (определив соответствующие стили), что в случае возникновения ошибки, замены носителя данных, изменения режима, текущей позиции или размера окна отображения родительское окно должно получать извещающие сообщения. Рассмотрим эти сообщения.

MCIWNDM_NOTIFYERROR

Сообщение MCIWNDM_NOTIFYERROR передается родительскому окну при возникновении ошибки. Параметр wParam содержит идентификатор окна MCI, параметр lParam - указатель на текстовую строку с описанием ошибки.

MCIWNDM_NOTIFYMEDIA

При изменении носителя данных (устройства или файла) родительское окно получает сообщение MCIWNDM_NOTIFYMEDIA . Параметр lParam содержит указатель на текстовую строку с именем файла или устройства. Если устройство или файл закрыты, этот параметр имеет значение NULL. Параметр wParam не используется.

MCIWNDM_NOTIFYMODE

При изменении режима работы родительское окно получает сообщение MCIWNDM_NOTIFYMODE , причем код нового режима находится в параметре lParam. Параметр wParam не используется.

MCIWNDM_NOTIFYPOS

Сообщение MCIWNDM_NOTIFYPOS передается родительскому окну при изменении текущей позиции. Новая позиция находится в параметре lParam. Параметр wParam не используется.

MCIWNDM_NOTIFYSIZE

Если пользователь изменил размер окна MCI, родительское окно получает сообщение MCIWNDM_NOTIFYSIZE . Параметр wParam содержит идентификатор окна MCI, параметр lParam не используется и равен нулю.

Приложение MCIWNDC

Теперь нашей задачей будет создание такого приложения, которое выполняет управление окном MCI с помощью перечисленных выше макрокоманд.

Приложение MCIWNDC (рис. 5.18) может проигрывать avi- и wav-файлы, файлы в стандарте MIDI, а также дорожки звуковых компакт-дисков. Кроме этого, приложение может записывать wav-файлы.

5.18. Меню "File" приложения MCIWNDC

Для проигрывания файлов мультимедиа их следует открыть при помощи строки "Open..." меню "File". При этом на экран будет выведена диалоговая панель "Open" с возможностью предварительного просмотра или прослушивания содержимого файла (рис. 5.19).

5.19. Диалоговая панель "Open" приложения MCIWNDC

Меню "Movie" (рис. 5.20) и "Styles" (рис. 5.22) предназначены для управления окном MCI.

5.20. Меню "Movie" приложения MCIWNDC

Строки "Play", "Play Reverse", "Record" и "Stop" предназначены, соответственно, для проигрывания, проигрывания в обратном направлении, записи и выполнения останова.

С помощью строк "Home" и "End" выполняется позиционирование на начало и конец файла. Строки "Step Fwrd" и "Step Back" дают возможность выполнять пошаговое перемещение вперед и назад.

Выбрав строку "Info...", вы увидите на экране диалоговую панель "Media Info" (рис. 5.21), в которой будет отображено имя устройства, путь к загруженному в окно MCI файлу и размер этого файла.

5.21. Диалоговая панель "Media Info"

С помощью строки "Play Bar" меню "Styles" (рис. 5.22) вы можете убрать или возвратить на место органы управления окном MCI.

5.22. Меню "Styles" приложения MCIWNDC

Диалоговая панель, используемая при сохранении записанных wav-файлов, содержит средства предварительного просмотра или прослушивания (рис. 5.23).

5.23. Диалоговая панель "Save As..." приложения MCIWNDC

Приложение MCIWNDC способно также проигрывать дорожки звуковых компакт-дисков. Внешний вид окна MCI, которое используется для этого, показан на рис. 5.24.

5.24. Окно MCI для проигрывания дорожек звукового компакт-диска

Несмотря на обилие возможностей, исходный текст приложения MCIWNDC занимает немного места (листинг 5.4).


Листинг 5.4. Файл mciwndc/mciwndc.cpp


// ------------------------------------------------
// Приложение MCIWNDC
// Использование класса окна MCIWnd для 
// проигрывания и записи файлов мультимедиа
// ------------------------------------------------

#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <commdlg.h>
#include <memory.h>
#include <vfw.h>
#include "mciwndc.h"

// Прототипы функций
BOOL    InitApp(HINSTANCE);
LRESULT CALLBACK _export WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL mciwndSelectFile(LPSTR lpszFileName);

// Глобальные переменные
char const szClassName[]   = "MCIWNDCClass";
char const szMovieClass[]  = MCIWND_WINDOW_CLASS;
char const szWindowTitle[] = "MCIWnd Player & Recorder";
HINSTANCE  hInst;
HWND hwndMovie = NULL;

// =====================================
// Функция WinMain
// =====================================
int PASCAL
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        LPSTR lpszCmdLine, int nCmdShow)
{
  MSG  msg;      // структура для работы с сообщениями
  HWND hwnd;     // идентификатор главного окна приложения
  WORD wVersion; // версия Video for Windows

  if(hPrevInstance)
    return FALSE;

  // Проверяем версию Video for Windows
  wVersion = HIWORD(VideoForWindowsVersion());
  if(wVersion < 0x010a)
  {
    MessageBox(NULL, "Используйте Video for Windows"
        " версии 1.1 или более поздней версии",
        "MCIWnd Error", MB_OK | MB_ICONHAND);
    return FALSE;
  }

  if(!InitApp(hInstance))
    return FALSE;
    
  hInst = hInstance;

  hwnd = CreateWindow(
    szClassName,         // имя класса окна
    szWindowTitle,       // заголовок окна
    WS_OVERLAPPEDWINDOW, // стиль окна
    CW_USEDEFAULT,       // размеры и расположение окна
    CW_USEDEFAULT,       
    400, 350, 0, 0, hInstance, NULL);
                       
  if(!hwnd)
    return FALSE;

  ShowWindow(hwnd, nCmdShow);
  UpdateWindow(hwnd);

  while(GetMessage(&msg, 0, 0, 0))
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return msg.wParam;
}

// =====================================
// Функция InitApp
// Выполняет регистрацию класса окна
// =====================================

BOOL InitApp(HINSTANCE hInstance)
{
  ATOM aWndClass; // атом для кода возврата
  WNDCLASS wc;    // структура для регистрации

  memset(&wc, 0, sizeof(wc));
  wc.lpszMenuName  = "APP_MENU";
  wc.style         = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc   = (WNDPROC) WndProc;
  wc.cbClsExtra    = 0;
  wc.cbWndExtra    = 0;
  wc.hInstance     = hInstance;
  wc.hIcon         = LoadIcon(hInstance, "APPICON");
  wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  wc.lpszClassName = (LPSTR)szClassName;

  aWndClass = RegisterClass(&wc);
  return (aWndClass != 0);
}

// =====================================
// Функция WndProc
// =====================================

LRESULT CALLBACK _export
WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch (msg)
  {
// ------------------------------------------------------------
// WM_INITMENU
// Инициализация меню
// ------------------------------------------------------------
    case WM_INITMENU:
    {                                       
      // Определяем стиль окна MCI  
      WORD wStyles = MCIWndGetStyles(hwndMovie);
      
      // Если окно MCI имеет панель управления,
      // отмечаем строку "Play Bar" меню "Styles"
      CheckMenuItem(GetMenu(hwnd), CM_STPBAR, 
        (wStyles & MCIWNDF_NOPLAYBAR) ? MF_UNCHECKED : MF_CHECKED);
      return 0;
    }

// ------------------------------------------------------------
// WM_COMMAND
// Обработка сообщений от меню
// ------------------------------------------------------------
    case WM_COMMAND:
    {
      switch (wParam)
      {
        // -------------------------------------------------
        // Строка "About" меню "Help"
        // -------------------------------------------------
        case CM_HELPABOUT:
        {
          MessageBox(hwnd,
            "MCIWnd Player & Recorder, v.1.0\n"
            "(C) Frolov A.V., 1994",
            "About MCIWNDC", MB_OK | MB_ICONINFORMATION);
          return 0;
        }

        // -------------------------------------------------
        // Строка "New Waveaudio" меню "File"
        // -------------------------------------------------
        case CM_FILENEW:
        {
          // Если окно MCI уже было создано, удаляем его
          if(hwndMovie)
            MCIWndDestroy(hwndMovie);

          // Создаем новое окно для записи звука,
          // открываем драйвер устройства waveaudio
          hwndMovie = MCIWndCreate(
            hwnd, hInst,
            WS_VISIBLE | WS_CHILD | WS_BORDER |
            MCIWNDF_RECORD, 
            (LPSTR)"waveaudio");
             
          // Создаем новый файл
          MCIWndNew(hwndMovie, "waveaudio");
          return 0;
        }

        // -------------------------------------------------
        // Строка "Save Waveaudio As..." меню "File"
        // -------------------------------------------------
        case CM_FILESAVEAS:
        {
          // Создаем диалоговую панель "Save As..." для
          // сохранения файла
          MCIWndSaveDialog(hwndMovie);
          return 0;
        }

        // -------------------------------------------------
        // Строка "CD Audio" меню "File"
        // -------------------------------------------------
        case CM_FILECDAUDIO:
        {
          // Если окно MCI уже было создано, удаляем его
          if(hwndMovie)
            MCIWndDestroy(hwndMovie);

          // Создаем новое окно для проигрывания CD,
          // открываем драйвер устройства cdaudio
          hwndMovie = MCIWndCreate(
            hwnd, hInst,
            WS_VISIBLE | WS_CHILD | WS_BORDER |
            MCIWNDF_RECORD, 
            (LPSTR)"cdaudio");
          return 0;
        }

        // -------------------------------------------------
        // Строка "Open" меню "File"
        // -------------------------------------------------
        case CM_FILEOPEN:
        {
          char szBuff[256];
          
          // Если окно MCI уже было создано, удаляем его
          if(hwndMovie)
            MCIWndDestroy(hwndMovie);
          
          // Выбираем файл для загрузки в окно MCI
          if(mciwndSelectFile(szBuff))
          {
             // Создаем окно MCI
             hwndMovie = MCIWndCreate(
               hwnd, hInst,
               WS_VISIBLE | WS_CHILD | WS_BORDER |
               MCIWNDF_RECORD,
               (LPSTR)szBuff);
          }
          return 0;
        }

        // -------------------------------------------------
        // Строка "Close" меню "File"
        // -------------------------------------------------
        case CM_FILECLOSE:
        {
          // Удаляем окно MCI
          MCIWndDestroy(hwndMovie);
          hwndMovie = NULL;
          return 0;
        }

        // -------------------------------------------------
        // Меню "Movie"
        // -------------------------------------------------
        case CM_MVIPLAY:    // "Play"
        {
          // Проигрывание
          MCIWndPlay(hwndMovie);
          return 0;
        }

        case CM_MVIRPLAY:   // "Play Reverse"
        {
          // Проигрывание в обратном направлении
          MCIWndPlayReverse(hwndMovie);
          return 0;
        }

        case CM_MVISTOP:    // "Stop"
        {
          // Останов
          MCIWndStop(hwndMovie);
          return 0;
        }

        case CM_MVIRECORD:  // "Record"
        {
          // Запись
          MCIWndRecord(hwndMovie);
          return 0;
        }             
        
        case CM_MVIHOME:    // "Home"
        {
          // Позиционирование в начало
          MCIWndHome(hwndMovie);
          return 0;
        }

        case CM_MVIEND:     // "End"
        {
          // Позиционирование в конец
          MCIWndEnd(hwndMovie);
          return 0;
        }

        case CM_MVISTEP:    // "Step Fwrd"
        {
          // Шаг вперед
          MCIWndStep(hwndMovie, 1);
          return 0;
        }

        case CM_MVIRSTEP:   // "Step Back"
        {
          // Шаг назад
          MCIWndStep(hwndMovie, -1);
          return 0;
        }

        case CM_MVIINFO:    // "Info..."
        {              
          char szBuff[512], szBuff1[256];
          long dwSize;
          
          // Если окно MCI создано, выводим информацию
          // о загруженном в него файле
          if(hwndMovie)
          {
            // Имя устройства
            MCIWndGetDevice(hwndMovie, (LPSTR)szBuff, 512);
            lstrcat(szBuff, (LPSTR)"\n");
          
            // Путь к файлу или имя устройства
            MCIWndGetFileName(hwndMovie, (LPSTR)szBuff1, 256);
            lstrcat(szBuff, (LPSTR)szBuff1);
            lstrcat(szBuff, (LPSTR)"\n");

            // Размер файла
            dwSize = MCIWndGetLength(hwndMovie);
            wsprintf(szBuff1, "Size: %ld ", (long)dwSize);
            lstrcat(szBuff, (LPSTR)szBuff1);

            // Формат времени
            MCIWndGetTimeFormat(hwndMovie, (LPSTR)szBuff1, 256);
            lstrcat(szBuff, (LPSTR)szBuff1);

            MessageBox(hwnd, szBuff,
              "Media Info", MB_OK | MB_ICONINFORMATION);
          }
          return 0;
        }
        // -------------------------------------------------
        // Меню "Styles"
        // -------------------------------------------------
        case CM_STPBAR:     // "Play Bar"
        {
          // Определяем стили окна MCI
          WORD wStyles = MCIWndGetStyles(hwndMovie);
      
          // Инвертируем состояние стиля MCIWNDF_NOPLAYBAR
          MCIWndChangeStyles(hwndMovie, MCIWNDF_NOPLAYBAR, 
            (wStyles & MCIWNDF_NOPLAYBAR) ? 0 : MCIWNDF_NOPLAYBAR);
          return 0;
        }

        // -------------------------------------------------
        // Строка "Exit" меню "File"
        // Завершение работы приложения
        // -------------------------------------------------
        case CM_FILEEXIT:
        {
          DestroyWindow(hwnd);
          return 0;
        }
        default:
          return 0;
      }
    }

    // Отслеживаем изменения в системной палитре
    case WM_PALETTECHANGED:
    {
      SendMessage(hwndMovie, msg, wParam, lParam);
      break;
    }
    case WM_QUERYNEWPALETTE:
    {
      return SendMessage(hwndMovie, msg, wParam, lParam);
    }

// ------------------------------------------------------------
// WM_DESTROY
// Уничтожение главного окна приложения
// ------------------------------------------------------------
    case WM_DESTROY:
    {
      PostQuitMessage(0);
      return 0;
    }
    default:
      break;
  }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}

//-----------------------------------------------------
// mciwndSelectFile
// Выбор файла
//-----------------------------------------------------
BOOL mciwndSelectFile(LPSTR lpszFileName)
{
  OPENFILENAME ofn;

  char szFile[256];
  char szFileTitle[256];
  char szFilter[256] =
     "Video Files\0*.avi\0"
     "Waveaudio Files\0*.wav\0"
     "MIDI Files\0*.mid;*.rmi\0"
     "Any Files\0*.*\0";
  szFile[0] = '\0';
  memset(&ofn, 0, sizeof(OPENFILENAME));

  // Инициализируем нужные нам поля
  ofn.lStructSize       = sizeof(OPENFILENAME);
  ofn.hwndOwner         = NULL;
  ofn.lpstrFilter       = szFilter;
  ofn.nFilterIndex      = 1;
  ofn.lpstrFile         = szFile;
  ofn.nMaxFile          = sizeof(szFile);
  ofn.lpstrFileTitle    = szFileTitle;
  ofn.nMaxFileTitle     = sizeof(szFileTitle);
  ofn.lpstrInitialDir   = NULL;
  ofn.Flags =   OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST
               | OFN_HIDEREADONLY;
  // Выбираем входной файл
  if (GetOpenFileNamePreview(&ofn))
  {
    // Копируем путь к выбранному файлу
    lstrcpy(lpszFileName, (LPSTR)szFile);
    return TRUE;
  }
  else
    return FALSE;
}

После проверки версии Video for Windows функция WinMain создает обычным образом главное окно приложения MCIWNDC и запускает цикл обработки сообщений. Эта часть приложения не имеет каких-либо особенностей.

При выборе строки "New Waveaudio" из меню "File" проверяется содержимое глобальной переменной hwndMovie, в которой хранится идентификатор окна MCI. Сразу после запуска приложения эта переменная содержит нулевое значение.

Если же окно MCI было создано ранее, оно удаляется при помощи макрокоманды MCIWndDestroy:

if(hwndMovie)
  MCIWndDestroy(hwndMovie);

Далее создается окно MCI, причем одновременно открывается устройство waveaudio:

hwndMovie = MCIWndCreate(
  hwnd, hInst,
  WS_VISIBLE | WS_CHILD | WS_BORDER |
  MCIWNDF_RECORD, 
  (LPSTR)"waveaudio");

Создаваемое при этом окно MCI является видимым, дочерним и имеет рамку. Среди органов управления присутствует кнопка записи, так как указан стиль окна MCIWNDF_RECORD.

Затем создается новый файл, для чего используется макрокоманда MCIWndNew:

MCIWndNew(hwndMovie, "waveaudio");

Сохранение записанных звуковых данных выполняется очень просто - с помощью макрокоманды MCIWndSaveDialog, позволяющей пользователю выбрать путь и имя файла:

MCIWndSaveDialog(hwndMovie);

При выборе строки "CD Audio" в меню "File" окно MCI создается следующим образом:

hwndMovie = MCIWndCreate(
  hwnd, hInst,
  WS_VISIBLE | WS_CHILD | WS_BORDER |
  MCIWNDF_RECORD, 
  (LPSTR)"cdaudio");

Обратите внимание, что указан стиль MCIWNDF_RECORD. Так как драйвер устройства чтения компакт-дисков не поддерживает (увы!) операцию записи, среди органов управления окна MCI кнопка записи так и не появится. Поэтому при создании собственного приложения для проигрывания компакт-дисков средствами окна MCI вам не нужно указывать этот стиль.

Если приложение MCIWNDC используется для проигрывания файла, окно MCI создается при выборе строки "Open..." в меню "File". В этом случае приложение вызывает функцию mciwndSelectFile, которая позволяет пользователю выбрать файл и записывает путь к файлу в переменную szBuff. Далее окно MCI создается следующим образом:

hwndMovie = MCIWndCreate(
  hwnd, hInst,
  WS_VISIBLE | WS_CHILD | WS_BORDER |
  MCIWNDF_RECORD,
  (LPSTR)szBuff);

При создании окна MCI указан стиль MCIWNDF_RECORD, однако кнопка записи появится только при загрузке wav-файла, так как запись средствами окна MCI возможна только для устройства "waveaudio".

При выборе из меню "File" строки "Close" окно MCI удаляется функцией MCIWndDestroy.

Обработка сообщений от меню "Movie" сводится в основном к вызову соответствующей макрокоманды. Например, при выборе из этого меню строки "Play" вызывается макрокоманда MCIWndPlay:

case CM_MVIPLAY:    // "Play"
{
  MCIWndPlay(hwndMovie);
  return 0;
}

Аналогичным образом обрабатываются остальные команды, за исключением команд позиционирования на один шаг вперед и один шаг назад:

case CM_MVISTEP:    // "Step Fwrd"
{
  MCIWndStep(hwndMovie, 1);
  return 0;
}
case CM_MVIRSTEP:   // "Step Back"
{
  MCIWndStep(hwndMovie, -1);
  return 0;
}

Второй параметр макрокоманды MCIWndStep указывает величину шага в миллисекундах или кадрах (в зависимости от текущего формата времени), причем отрицательным значениям соответствует позиционирование в обратном направлении.

При выборе из меню "Movie" строки "Info..." приложение определяет и выводит на экран информацию об используемом устройстве и загруженном файле.

Для определения имени устройства используется макрокоманда MCIWndGetDevice :

MCIWndGetDevice(hwndMovie, (LPSTR)szBuff, 512);

Через первый параметр этой макрокоманде передается идентификатор окна MCI. Второй параметр - указатель на буфер, в который следует записать имя устройства. Третий параметр - размер буфера.

Путь к загруженному устройству или имя устройства (если файл не используется) определяется с помощью макрокоманды MCIWndGetFileName аналогичным образом:

MCIWndGetFileName(hwndMovie, (LPSTR)szBuff1, 256);

Размер файла вычисляется макрокомандой MCIWndGetLength , возвращающей значение в формате двойного слова:

dwSize = MCIWndGetLength(hwndMovie);

Единица измерения размера зависит от текущего формата времени, который определяется в виде текстовой строки при помощи макрокоманды MCIWndGetTimeFormat :

MCIWndGetTimeFormat(hwndMovie, (LPSTR)szBuff1, 256);

Теперь о меню "Styles".

При выборе из этого меню строки "Play Bar" приложение определяет текущий стили окна, и затем инвертирует стиль MCIWNDF_NOPLAYBAR:

case CM_STPBAR:     // "Play Bar"
{
  WORD wStyles = MCIWndGetStyles(hwndMovie);
  MCIWndChangeStyles(hwndMovie, MCIWNDF_NOPLAYBAR, 
    (wStyles & MCIWNDF_NOPLAYBAR) ? 0 : MCIWNDF_NOPLAYBAR);
  return 0;
}

Правильную отметку строки "Play Bar" в меню обеспечивает обработчик сообщения WM_INITMENU:

case WM_INITMENU:
{                                       
  WORD wStyles = MCIWndGetStyles(hwndMovie);
  CheckMenuItem(GetMenu(hwnd), CM_STPBAR, 
    (wStyles & MCIWNDF_NOPLAYBAR) ? MF_UNCHECKED : MF_CHECKED);
  return 0;
}

Этот обработчик отмечает или нет строку "Play Bar" меню "Styles" в зависимости от того, имеет ли окно MCI стиль MCIWNDF_NOPLAYBAR, или нет.

Обработка сообщений об изменении системной палитры WM_PALETTECHANGED и о необходимости реализации палитры WM_QUERYNEWPALETTE заключается в непосредственной передаче соответствующих сообщений окну MCI, поэтому выполняется очень просто:

case WM_PALETTECHANGED:
{
  SendMessage(hwndMovie, msg, wParam, lParam);
  break;
}
case WM_QUERYNEWPALETTE:
{
  return SendMessage(hwndMovie, msg, wParam, lParam);
}

Файл mciwndc.h (листинг 5.5) содержит определения констант, используемых в приложении MCIWNDC.


Листинг 5.5. Файл mciwndc/mciwndc.h


#define CM_HELPABOUT   301
#define CM_FILEEXIT    302
#define CM_FILEOPEN    303
#define CM_FILECLOSE   304
#define CM_FILENEW     305
#define CM_FILESAVEAS  306
#define CM_FILECDAUDIO 307

#define CM_MVIPLAY     401
#define CM_MVIRPLAY    402
#define CM_MVIHOME     403
#define CM_MVIEND      404
#define CM_MVISTEP     405
#define CM_MVIRSTEP    406
#define CM_MVISTOP     407
#define CM_MVIRECORD   408
#define CM_MVIINFO     409

#define CM_STPBAR      501

Файл определения ресурсов приложения представлен в листинге 5.6.


Листинг 5.6. Файл mciwndc/mciwndc.rc


#include "mciwndc.h"
AppIcon ICON mciwndc.ico
APP_MENU MENU 
BEGIN
  POPUP "&File"
    BEGIN
      MENUITEM "&Open...",       CM_FILEOPEN
      MENUITEM "&Close",         CM_FILECLOSE
      MENUITEM SEPARATOR
      MENUITEM "&New Waveaudio", CM_FILENEW
      MENUITEM "Save Waveaudio &As...", CM_FILESAVEAS
      MENUITEM SEPARATOR
      MENUITEM "CD Audio",       CM_FILECDAUDIO
      MENUITEM SEPARATOR
      MENUITEM "E&xit",          CM_FILEEXIT
    END

  POPUP "&Movie"
    BEGIN
      MENUITEM "&Play",         CM_MVIPLAY
      MENUITEM "Play &Reverse", CM_MVIRPLAY
      MENUITEM "R&ecord",       CM_MVIRECORD
      MENUITEM "&Stop",         CM_MVISTOP
      MENUITEM SEPARATOR
      MENUITEM "&Home",         CM_MVIHOME
      MENUITEM "&End",          CM_MVIEND
      MENUITEM SEPARATOR
      MENUITEM "Step &Fwrd",    CM_MVISTEP
      MENUITEM "Step &Back",    CM_MVIRSTEP
      MENUITEM SEPARATOR
      MENUITEM "&Info...",      CM_MVIINFO
    END
  POPUP "St&yles"
    BEGIN
      MENUITEM "&Play Bar",     CM_STPBAR
    END

  POPUP "&Help"
    BEGIN
      MENUITEM "&About...", CM_HELPABOUT
    END
END

Файл определения модуля приложения MCIWNDC представлен в листинге 5.7.


Листинг 5.7. Файл mciwndc/mciwndc.def


NAME        MCIWNDC
DESCRIPTION 'Приложение MCIWNDC, (C) 1994, Frolov A.V.'
EXETYPE     windows
STUB        'winstub.exe'
STACKSIZE   10240
HEAPSIZE    1024
CODE        preload moveable discardable
DATA        preload moveable multiple

Для трансляции приложения в среде MS-DOS системой Microsoft C++ версии 7.0 или 8.0 (входящий в Visual C++ версии 1.0) вы можете использовать makefile, представленный в листинге 5.8.


Листинг 5.8. Файл mciwndc/makefile


NAME = mciwndc
OBJ  = mciwndc.obj
LIBS = libw slibcew commdlg vfw

!if "$(DEBUG)" == "NO"
DEF     =
CLOPT   =
MASMOPT =
LINKOPT =
!else
DEF     = -DDEBUG
CLOPT   = -Zid
MASMOPT = -Zi
LINKOPT = /CO/LI
!endif

CC  = cl -c -W3 -AS -Zp -G2sw -Oxas $(DEF) $(CLOPT) -DWIN31
ASM = masm -Mx $(MASMOPT)
LINK= link /NOE/NOD/LI/MAP/AL:16/ONERROR:NOEXE $(LINKOPT)
RC  = rc 
.c.obj:
        $(CC) $*.c
.asm.obj:
        $(ASM) $*;
goal: $(NAME).exe
$(NAME).exe: $(OBJ) $(NAME).res $(NAME).def makefile
        $(LINK) $(OBJ), $(NAME), $(NAME),$(LIBS), $(NAME).def
        $(RC) -31 $(NAME).res
        -mapsym $(NAME).map
$(NAME).res: $(NAME).rc
        $(RC) -r $(NAME).rc
clean:
        del $(NAME).exe
        del *.res
        del *.obj
        del *.map
        del *.sym
        del *.pdb
copy:
        copy $(NAME).exe ..\..\bin
        copy $(NAME).sym ..\..\bin
depend:
        mv makefile makefile.old
        sed "/^# START Dependencies/,/^# END Dependencies/D" makefile.old > makefile
        del makefile.old
        echo # START Dependencies >> makefile
        includes -l *.c *.asm >> makefile
        echo # END Dependencies >> makefile
Назад       Содержание       Вперёд