Создадим программу,
которая будет отслеживать загрузку компакт диска и выдавать о нем информацию.
Создайте новое приложение. Разместите на форме 5 компонентов Label и один
Button. Удалите свойство Caption у компонентов Label и установите свойство Font
в Courier New для равномерного отображения информации. Задайте свойство Caption
у Button – “Извлечь”. Подключите два заголовочных файла: dbt.h и mmsystem.hpp, в
первом находятся необходимые определения для отслеживания изменения конфигурации
устройств, во втором – для работы с устройствами мультимедиа. Добавьте в общий
раздел класса формы объявление следующих переменных и функций:
AnsiString drv;
void __fastcall MyWndProc(TMessage&
Message);
char __fastcall FirstDriveFromMask (ULONG
unitmask);
void __fastcall EjectCD(AnsiString
S);
void __fastcall GetCDInfo(AnsiString
S);.
Переменная drv служит для хранения буквы привода CD-ROM.
Функция MyWndProc() – основная функция, которая будет отслеживать загрузку
компакт диска. Функция FirstDriveFromMask() – возвращает букву накопителя.
Функция EjectCD() служит для извлечения компакт диска из привода, а GetCDInfo()
– получает информацию о компакт диске. Теперь перейдем к определению наших
функций. Перейдите в редактор кода файла Unit1.cpp и добавьте определения
функций как показано в листинге 1.
void __fastcall TForm1::MyWndProc(TMessage& Message)
{
if(Message.Msg == WM_DEVICECHANGE)
{
if(Message.WParam ==
DBT_DEVICEARRIVAL)
{
PDEV_BROADCAST_HDR lpdb =
(PDEV_BROADCAST_HDR)Message.LParam;
if(lpdb->dbch_devicetype
== DBT_DEVTYP_VOLUME)
{
PDEV_BROADCAST_VOLUME lpdbv =
(PDEV_BROADCAST_VOLUME)lpdb;
if(lpdbv->dbcv_flags & DBTF_MEDIA)
{
drv = FirstDriveFromMask(lpdbv ->dbcv_unitmask);
drv += ":\\";
GetCDInfo(UpperCase(drv));
}
}
}
}
else
{
WndProc(Message);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::GetCDInfo(AnsiString S)
{
DWORD VolSN, MaxCompLen, FSFlag, FC, SPC, BPS, NC;
char VolName[256], FSName[15];
if(GetVolumeInformation(UpperCase(S).c_str(), VolName, 255, &VolSN,
&MaxCompLen,
&FSFlag,
FSName, 15))
{
Label1->Caption = "Дисковод\t\t" +
UpperCase(S);
Label2->Caption = "Метка\t\t\t" +
AnsiString(VolName);
Label3->Caption = "Серийный номер
диска\t" + IntToStr((__int64)VolSN);
Label4->Caption = "Номер диска
(HEX)\t" + IntToHex((__int64)VolSN, 8);
Label5->Caption = "Файловая система\t"
+ AnsiString(FSName);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::EjectCD(AnsiString S)
{
MCIERROR Err;
MCI_OPEN_PARMS OpenParm;
DWORD Flags;
WORD DeviceID;
Flags = MCI_OPEN_TYPE | MCI_OPEN_ELEMENT;
OpenParm.wDeviceID = NULL;
OpenParm.dwCallback = NULL;
OpenParm.lpstrDeviceType = "CDAudio";
OpenParm.lpstrElementName = S.c_str();
Err = mciSendCommand(NULL, MCI_OPEN, Flags,
(DWORD)(LPMCI_OPEN_PARMS)&OpenParm);
DeviceID = OpenParm.wDeviceID;
Err = mciSendCommand(DeviceID, MCI_SET, MCI_SET_DOOR_OPEN,
0);
Err = mciSendCommand(DeviceID, MCI_CLOSE, 0, NULL);
}
//---------------------------------------------------------------------------
char __fastcall TForm1::FirstDriveFromMask(ULONG unitmask)
{
char i;
for(i = 0; i < 26; ++i)
{
if(unitmask & 0x1)
break;
unitmask = unitmask >> 1;
}
return(i + 'A');
}
Листинг 1.
Функция MyWndProc()
перехватывает широковещательное сообщение Windows WM_DEVICECHANGE и отслеживает
загрузку компакт диска:
if(Message.WParam == DBT_DEVICEARRIVAL)
{
…
},
если вы хотите отслеживать выгрузку компакт диска, используйте следующий код:
if(Message.WParam == DBT_DEVICEREMOVECOMPLETE)
{
…
}.
Функция GetCDInfo() использует стандартную функцию Windows
API GetVolumeInformation().
Те, кто читает факи (FAQ – Frequently Asked Questions), может
сказать, что для выгрузки компакт диска достаточно использовать команду
mciSendString("Set cdaudio door closed wait", NULL, 0, NULL) или
mciSendString("close cd", 0, 0, 0). А если CD-ROM больше одного? Как говорил
известный персонаж “Золотой портсигар – два, куртка кожаный – три”. Всегда будет
выгружаться первый из установленных в системе. Функция EjectCD() работает с
любым разумным количеством приводов. Вставьте вызов этой функции в обработчик
события OnClick компонента Button.
Функция FirstDriveFromMask() возвращает букву привода в
который был вставлен компакт диск.
Для того чтобы наше приложение обрабатывало загрузку компакт
диска, необходимо переопределить оконную процедуру обработки сообщений. Это
делает следующая строка кода:
WindowProc = MyWndProc;.
Вставьте этот код в событие OnCreate формы приложения.
Создайте выполняемый файл. Протестируйте полученную программу.