Windows 檔案總管提供「彈出」光碟機選單,卻無「關閉」選項。本文展示如何使用 MCI (Media Control Interface) 命令以程式控制光碟機托架開合,支援指定盤符或首個邏輯光碟機。
CD_OpenCloseDrive
#include
#include
#pragma comment(lib, "winmm.lib")
// bOpenDrive: TRUE=彈出, FALSE=關閉
// cDrive: 盤符字元 (如 'G'),或 1 代表第一個邏輯光碟機
void CD_OpenCloseDrive(BOOL bOpenDrive, TCHAR cDrive) {
MCI_OPEN_PARMS openParms = {0};
MCI_STATUS_PARMS statusParms = {0};
DWORD flags;
TCHAR driveName[4] = _T("X:");
openParms.lpstrDeviceType = (LPCSTR)MCI_DEVTYPE_CD_AUDIO;
if (cDrive > 1) { // 指定盤符
driveName[0] = cDrive;
openParms.lpstrElementName = driveName;
flags = MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_OPEN_ELEMENT | MCI_OPEN_SHAREABLE;
} else { // 使用第一個光碟機
flags = MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE;
}
if (mciSendCommand(0, MCI_OPEN, flags, (DWORD_PTR)&openParms) == 0) {
UINT deviceId = openParms.wDeviceID;
statusParms.dwItem = MCI_STATUS_READY;
// 等待裝置就緒(可選,視裝置而定)
mciSendCommand(deviceId, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD_PTR)&statusParms);
if (bOpenDrive)
mciSendCommand(deviceId, MCI_SET, MCI_SET_DOOR_OPEN, 0);
else
mciSendCommand(deviceId, MCI_SET, MCI_SET_DOOR_CLOSED, 0);
mciSendCommand(deviceId, MCI_CLOSE, MCI_WAIT, 0);
}
}
CD_OpenCloseAllDrives
void CD_OpenCloseAllDrives(BOOL bOpenDrives) {
TCHAR driveRoot[4] = _T("?:\\");
DWORD driveMask = GetLogicalDrives();
int bitPos = 0;
while (driveMask) {
if (driveMask & 1) {
driveRoot[0] = _T('A') + bitPos;
if (GetDriveType(driveRoot) == DRIVE_CDROM) {
CD_OpenCloseDrive(bOpenDrives, driveRoot[0]);
}
}
driveMask >>= 1;
++bitPos;
}
}
#include
#pragma comment(lib, "winmm.lib")
| 項目 | 說明 |
|---|---|
MCI_DEVTYPE_CD_AUDIO | 告知 MCI 開啟 CD 音訊裝置,支援托架控制命令 |
MCI_OPEN_SHAREABLE | 允許多程式共用裝置,避免「裝置已被使用」錯誤 |
MCI_SET_DOOR_OPEN/CLOSED | 實際控制托架馬達的核心命令 |
MCI_WAIT | 同步等待命令完成,避免關閉裝置過早導致命令失敗 |
GetLogicalDrives + GetDriveType | 枚舉所有邏輯磁碟並篩選 CDROM 型別 |
MCI_STATUS 輪詢就緒狀態CD_OpenCloseAllDrives 或指定盤符MCI 提供簡潔的高階介面控制 CD-ROM 托架,核心在於 MCI_OPEN 取得裝置 ID,隨後發送 MCI_SET_DOOR_OPEN/CLOSED。封裝為 CD_OpenCloseDrive/CD_OpenCloseAllDrives 即可輕鬆整合至任何 C++ 專案。