Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

В этом выпуске рассылки рассказывается о том, как можно управлять приводом CD-ROM


Информационный Канал Subscribe.Ru

A

Выпуск №6. Управление CD-ROM

 

Рад всех приветствовать!

Я уже было совсем забросил заниматься этой рассылкой - шутка ли прошло больше года с момента последнего выпуска. За это время много чего произошло. Я наконец-то закончил учебу в институте, свободного время стало больше, но полениться тоже охота :)

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

Управление CD/DVD приводом.

Итак, в этом выпуске я хотел бы немного рассказать об управлении CD / DVD приводом.

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

Для управления проводом можно воспользоваться WinAPI функцией mciSendCommand . Эта функция делает много всего хорошего и разного, в том числе может открывать и закрывать привод CD - ROM . С помощью этой функции так же можно определить - есть ли диск в приводе или его там нет. Единственное, что мне не удалось сделать этой функцией - это определить, открыт ли лоток привода или нет. Это не совсем удобно. Возможно есть какой-то хитрый способ. Да что там определение "открытости" лотка, даже чтобы просто открыть лоток пришлось изрядно помучаться :)

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

Для управления CD / DVD приводом или несколькими приводами я сваял небольшой класс. Взять его Вы можете здесь. Вот его описание:

CAxCDManager();

Конструктор по умолчанию

CAxCDManager(bool bUseScrlLock);

Этот конструктор не используется .

int GetDrivesCount() const;

Возвращает количество CD / DVD приводов.

TCHAR GetDriveName(int iDrive) const;

Возвращает букву привода по его порядковому номеру. Если указан номер несуществующего привода, то возвращается '?' вместо имени.

TCHAR operator[] (int i) const;

Делает то же самое, что и GetDriveName .

TCHAR GetSelectedDrive() const;

Возвращает букву выбранного привода.

bool SelectDrive(int iDrive);

Выбирает указанный привод в качестве текущего по его номеру.

bool SelectDrive(TCHAR chDrive);

Выбирает указанный привод в качестве текущего по его имени.

bool IsOpened() const;

Возвращает статус - открыт или не открыт. Тут стоит заметить, что как я говорил раньше мне не удалось найти возможность определения такого состояния привода, поэтому эту возможность пришлось эмулировать. Сделано это в виде набора триггеров, соответствующих каждому приводу. Изначально предполагается, что все приводы закрыты и что открытие/закрытие приводов осуществляется через интерфейс класса. Если, например, вручную открыть CD-ROM .

bool IsCDPresent() const;

Возвращает статус - есть ли установленный в приводе диск. Подробнее см. ниже.

bool IsRunning() const;

Класс сделан как multithreaded , эта функция возвращает статус того, есть ли запущенные вторичные потоки.

bool Open();

Открывает текущий выбранный привод.

bool Close(bool bDetectCD = false);

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

bool OpenClose ( bool bDetectCD = false );

Обе предыдущие функции, которые объединены в одну. Один вызов открывает привод, другой его закрывает.

void RefreshState();

Обновляет внутреннее состояние класса - сколько приводов, какие буквы они занимают.

Стоит заметить, что для компиляции приведенного класса, ему нужна функция IsCDPresent . Эта функция у меня определена в отдельном файле, где лежат еще кое-какие функции общего назначения (например функция сопоставления маски и строки). Чтобы не загромождать место описанием других функций, приведу описание лишь самой IsCDPresent , вот оно:

 

bool IsCDPresent(TCHAR chDriveName)

{

bool bResult = false;

MCI_OPEN_PARMS op;

MCI_STATUS_PARMS param;

DWORD flags;

TCHAR szDriveName[4];

 

::memset(szDriveName , 0 , sizeof(szDriveName));

::memset(&op, 0, sizeof(op));

::memset(&param, 0, sizeof(param));

 

op.lpstrDeviceType = "cdaudio";

::lstrcpy(szDriveName , "?:");

 

szDriveName[0] = chDriveName;

op.lpstrElementName = szDriveName;

flags = MCI_OPEN_TYPE | MCI_OPEN_ELEMENT | MCI_OPEN_SHAREABLE;mciSendCommand(0,MCI_OPEN,flags,(unsigned long)&op);

 

if (op.wDeviceID)

{

param.dwItem = MCI_STATUS_MEDIA_PRESENT;

MCIERROR err = mciSendCommand(op.wDeviceID, MCI_STATUS, MCI_STATUS_ITEM , (DWORD) (LPMCI_STATUS_PARMS) &param);

if ((err == 0) && (param.dwReturn == TRUE))

bResult = true;

mciSendCommand(op.wDeviceID, MCI_CLOSE, MCI_WAIT, 0);

}

 

return bResult;

};

 

 

Ее можно определить где-то в другом файле.

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

Для того, чтобы можно было пользоваться классом AxCDManager , нужно :

  1. Подключить заголовочный файл AxCdManager.h
  2. Добавить к проекту два . cpp -файла: AxCdManager . cpp и AxThread . cpp (поддержка многопоточности)
  3. Включить пространство имен AxWinLib директивой namespace или создать класс по полному квалифицированному имени.

Данный класс можно использовать в любых проектах, как в WTL , так и MFC и WinAPI .

Заключение

Несмотря на то, что казалось бы такое простое действие, как открытие привода CD - ROM должно выполняться элементарно, мне пришлось довольно много порыться в Сети, чтобы наконец понять, как это делается правильно. Когда я наконец нашел работающий пример, то оказалось, что расхождения моем коде (который никак не хотел работать) и примером оказались на уровне 1-2 байт, нюанс был, насколько помню, в форме передачи имени используемого диска.

На сегодня все. До скорой встречи. Надеюсь, не через год :)



http://subscribe.ru/
http://subscribe.ru/feedback/
Подписан адрес:
Код этой рассылки: comp.soft.prog.winapiwtlatl
Отписаться

В избранное