手動按壓光碟機彈出鍵不僅麻煩,多光碟機環境下更難分辨對象。本系列教學示範如何用 Delphi 建立一個常駐系統托盤的光碟機控制工具:動態掃描所有光碟機、自動建立對應選單項目、支援單一/批次開啟關閉、可設定開機自動執行。
專案架構概覽
- TPopupMenu:右鍵彈出選單,動態產生光碟機項目
- MCI API:透過
mciSendCommand 控制 CDAudio 裝置彈出/收回托盤
- Registry:管理
HKLM\Software\Microsoft\Windows\CurrentVersion\Run 實現開機自啟
- GetDriveType:掃描 A:~Z: 識別
DRIVE_CDROM 類型磁碟機
介面設計:彈出選單結構

| 選單項名稱 | Caption | 類型/說明 | 關鍵事件 |
| mMenuTitle | ==光碟機控制== | 分隔標題 | 無 |
| mOpenCDROM | 開啟 CDROM 托盤 | 父選單,動態生成子項 | MenuOpenCdrom (子項共用) |
| mCloseCDROM | 關閉 CDROM 托盤 | 父選單,動態生成子項 | MenuCloseCdrom (子項共用) |
| mAutoRun | 設定開機自動執行 | 功能項 | mAutoRunClick |
| mNotAutoRun | 取消自動執行 | 功能項 | mNotAutoRunClick |
| mCloseApp | 關閉控制程式 | 功能項 | Application.Terminate |
核心變數與函數宣告
private
MYDRIVE: Char; // 目前掃描到的磁碟機代號
MyCdrom: PChar; // 傳遞給 MCI 函數的磁碟機字串
tmpPopMenu1, tmpPopMenu2: TMenuItem; // 動態建立的選單項暫存
function OpenCDROM(Drive: PChar): Boolean;
function CloseCDROM(Drive: PChar): Boolean;
procedure MenuOpenCdrom(Sender: TObject);
procedure MenuCloseCdrom(Sender: TObject);
procedure PopMenuCDCtrlPopup(Sender: TObject); // 選單彈出前動態重建
關鍵邏輯:選單彈出前動態掃描與重建
procedure TForm1.PopMenuCDCtrlPopup(Sender: TObject);
var Drive: Char;
begin
// 1. 清空舊選單項
mOpenCDROM.Clear;
mCloseCDROM.Clear;
// 2. 掃描 A:~Z: 尋找光碟機
for Drive := 'A' to 'Z' do begin
case GetDriveType(PChar(Drive + ':\')) of
DRIVE_CDROM: begin
MYDRIVE := Drive;
// 建立「開啟」子選單項
tmpPopMenu1 := TMenuItem.Create(Self);
tmpPopMenu1.AutoHotkeys := maManual;
tmpPopMenu1.OnClick := MenuOpenCdrom;
tmpPopMenu1.Caption := UpperCase(MYDRIVE) + ':';
mOpenCDROM.Add(tmpPopMenu1);
// 建立「關閉」子選單項
tmpPopMenu2 := TMenuItem.Create(Self);
tmpPopMenu2.AutoHotkeys := maManual;
tmpPopMenu2.OnClick := MenuCloseCdrom;
tmpPopMenu2.Caption := UpperCase(MYDRIVE) + ':';
mCloseCDROM.Add(tmpPopMenu2);
end;
// 其他磁碟機類型略過...
end;
end;
// 3. 多光碟機時新增「所有光碟機」批次操作項
if mOpenCDROM.Count > 1 then begin
tmpPopMenu1 := TMenuItem.Create(Self);
tmpPopMenu1.Caption := '所有光碟機';
tmpPopMenu1.OnClick := MenuOpenCdrom;
mOpenCDROM.Add(tmpPopMenu1);
tmpPopMenu2 := TMenuItem.Create(Self);
tmpPopMenu2.Caption := '所有光碟機';
tmpPopMenu2.OnClick := MenuCloseCdrom;
mCloseCDROM.Add(tmpPopMenu2);
end;
end;
設計亮點解析
| 技術點 | 實作方式 | 優勢 |
| 動態選單重建 | Popup 事件中 Clear + 重掃描 | 即時反映光碟機插拔變化,無需重啟程式 |
| 共用事件處理器 | 所有動態子項指向同一 OnClick | 程式碼精簡,透過 Sender.MenuIndex 區分目標 |
| Owner 自動釋放 | TMenuItem.Create(Self) | 表單銷毀時自動釋放動態建立的選單項,無記憶體洩漏 |
| 批次操作邏輯 | 最後一項為「所有光碟機」,MenuIndex = Count-1 判斷 | 直觀易懂,無需額外標記欄位 |
系列文章導覽
- (一) 本文:專案架構、選單設計、動態掃描重建邏輯
- (二):
OpenCDROM/CloseCDROM MCI 核心函數、開機自動執行登錄操作
- (三):選單項具體事件處理、批次操作實作、托盤常駐改造方向
現代化改造建議
- 將 TForm 改為 TTrayIcon 單元,無視窗常駐托盤區
- 使用
DeviceIoControl + IOCTL_STORAGE_EJECT_MEDIA 取代 MCI,支援 USB 光碟機、虛擬光碟機
- 採用
WM_DEVICECHANGE 訊息監聽裝置到達/移除,主動重建選單而非被動等待點擊
- 開機自啟改寫
HKCU\Software\Microsoft\Windows\CurrentVersion\Run 避免 UAC 提升
這個專案展示了 Delphi「所見即所得」的 UI 設計與底層 API 呼叫的無縫整合能力,是學習 Windows 系統程式設計的優秀入門案例。
- 上一篇文章: Delphi 控制光碟機彈出/收回托盤核心函數與自動執行管理(二)
- 下一篇文章: Delphi 原始碼格式撰寫規範(三):組件簡稱對照表與修改歷史管理
Copyright ©
程式碼之家 All Rights Reserved