Если вы пишете программу, связанную с мультимедиа, вам наверняка потребуется возможность открывать и закрывать CD-ROM программно. Обычно это рекомендуется делать при помощи API-функции mciSendString из библиотеки winmm.dll. Её декларация:
Declare Function mciSendString Lib "winmm.dll" _
Alias "mciSendStringA" (ByVal lpstrCommand As String, _
ByVal lpstrReturnString As String, ByVal uReturnLength As Long, _
ByVal hwndCallback As Long) As Long
Эта функция посылает командную строку мультимедийным устройствам. Открыть дисковод можно так:
mciSendString "set cdaudio door open", 0, 127, 0
Команда на закрытие дисковода:
mciSendString "set cdaudio door closed", 0, 127, 0
Но что же делать, если у пользователя на компьютере установлено два (как у меня), или более CD-ROM устройства? Предложенные выше функции будут открывать-закрывать только лишь одно устройство. В этом случае на помощь придёт низкоуровневая API-функция DeviceIoControl. Вот её декларация.
Declare Function DeviceIoControl Lib "kernel32" ( _
ByVal hDevice As Long, ByVal dwIoControlCode As Long, _
lpInBuffer As Any, ByVal nInBufferSize As Long, _
lpOutBuffer As Any, ByVal nOutBufferSize As Long, _
lpBytesReturned As Long, lpOverlapped As Any) As Long
Как видно из декларации, первый параметр функции - это дескриптор нужного нам устройства. Получить его можно с помощью замечательной функции CreateFile.
Declare Function CreateFile Lib "kernel32" _
Alias "CreateFileA" (ByVal lpFileName As String, _
ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, _
lpSecurityAttributes As Any, _
ByVal dwCreationDisposition As Long, _
ByVal dwFlagsAndAttributes As Long, _
ByVal hTemplateFile As Long) As Long
Полученный дескриптор, когда он больше не будет нужен, обязательно нужно закрыть при помощи функции CloseHandle:
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Есть одна тонкость при вызове CreateFile - к пути дисковода нужно спереди добавить префикс "\\.\", для того, чтобы функция "знала", что мы имеем дело именно с устройством, а не с дисковой папкой. Таким образом, для дисковода с буквой Е, параметр lpFileName будет иметь вид:
lpFileName = "\\.\e:"
Сначала объявим необходимые константы.
Const FILE_SHARE_READ = &H1&
Const FILE_SHARE_WRITE = &H2&
Const OPEN_EXISTING = 3&
Const GENERIC_READ = &H80000000
Const GENERIC_WRITE = &H40000000
Const INVALID_HANDLE_VALUE = -1
А вот главные, "секретные", константы для DeviceIoControl. Значений этих не найти в заголовочных файлах. Они получены выполнением специальных макросов в среде Visual C++:
Const IOCTL_STORAGE_EJECT_MEDIA = &H2D4808
Const IOCTL_STORAGE_LOAD_MEDIA = &H2D480C
Теперь, когда у нас всё подготовлено, пишем функцию, открывающую дисковод (возвращает в случае неудачи False):
Public Function EjectCD(ByVal drivePath As String) As Boolean
Dim drFullPath As String
Dim hDevice As Long, nBytesReturned As Long
drivePath = Replace(drivePath, "\", "")
drFullPath = "\\.\" & LCase(drivePath)
hDevice = CreateFile( _
drFullPath, _
GENERIC_READ, _
FILE_SHARE_READ Or FILE_SHARE_WRITE, _
ByVal 0&, OPEN_EXISTING, 0, 0)
If hDevice <> INVALID_HANDLE_VALUE Then
EjectCD = CBool(DeviceIoControl(hDevice, _
IOCTL_STORAGE_EJECT_MEDIA, 0, 0, 0, 0, _
nBytesReturned, ByVal 0&))
CloseHandle hDevice
End If
End Function
Функция закрывающая дисковод LoadCD, будет отличаться лишь тем, что вместо константы IOCTL_STORAGE_EJECT_MEDIA подставляем IOCTL_STORAGE_LOAD_MEDIA.
Не очень просто, но ведь работает! После тестирования функций, можно создать класс для работы с дисководами, включить его в проект ActiveX DLL или EXE, откомпилировать, и забыть, как страшный сон.
Будьте осторожны с функцией DeviceIoControl !. С её помощью можно ещё и форматировать диски. Ошибка в константе - и большой привет!
Автор - Цзяофань
|