首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

VC 實現光驅彈出/送入狀態自動監測

     編輯:關於VC++

Windows 系統透過 WM_DEVICECHANGE 廣播訊息通知應用程式硬體裝置狀態變更。本文詳細解析如何攔截該訊息,結合 DBT_DEVICEARRIVAL 與 DBT_DEVICEREMOVECOMPLETE 事件,實現光驅狀態的即時偵測與友善提示。

核心原理

當光驅托盤彈出或送入時,系統會發送 WM_DEVICECHANGE,其 wParam 參數指示事件類型,lParam 指向 PDEV_BROADCAST_HDR 結構,包含裝置類型與邏輯磁碟機遮罩。透過解析遮罩即可定位具體磁碟機代號(如 E:、F:)。

關鍵函數實現

1. 遮罩解析磁碟機代號

char chFirstDriveFromMask(ULONG unitmask) {
    char i;
    for (i = 0; i < 26; ++i) {
        if (unitmask & 0x1) break; // 找到變化位
        unitmask >>= 1;
    }
    return (i + 'A'); // 轉為 'A'~'Z'
}

2. 對話框訊息處理核心

BOOL WINAPI DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
    static UINT uMsgQueryCancelAutoPlay = RegisterWindowMessage(_T("QueryCancelAutoPlay"));

    switch (uMsg) {
    case WM_DEVICECHANGE: {
        char szMsg[80];
        switch (wParam) {
        case DBT_DEVICEARRIVAL: // 裝置插入/可用
            if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) {
                PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
                if (lpdbv->dbcv_flags & DBTF_MEDIA) { // 有媒體(光碟)
                    wsprintf(szMsg, _T("驅動器 %c: 已經可用\n"),
                             chFirstDriveFromMask(lpdbv->dbcv_unitmask));
                    MessageBox(hwnd, szMsg, _T("光驅自動監測"), MB_OK | MB_ICONINFORMATION);
                }
            }
            break;
        case DBT_DEVICEREMOVECOMPLETE: // 裝置移除完成
            if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) {
                PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
                if (lpdbv->dbcv_flags & DBTF_MEDIA) {
                    wsprintf(szMsg, _T("驅動器 %c: 已經彈出\n"),
                             chFirstDriveFromMask(lpdbv->dbcv_unitmask));
                    MessageBox(hwnd, szMsg, _T("光驅自動監測"), MB_OK | MB_ICONINFORMATION);
                }
            }
            break;
        }
        break;
    }
    case uMsgQueryCancelAutoPlay: // 防衝突:暫停自動播放
        if (MessageBox(hwnd, _T("你想禁止 AutoPlay 功能嗎?"), NULL,
                       MB_YESNO | MB_ICONQUESTION) == IDYES) {
            SetDlgMsgResult(hwnd, uMsg, 1);
            return 1;
        }
        break;
    }
    return FALSE;
}

3. 程式進入點

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) {
    DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);
    return 0;
}

關鍵技術點總結

  • 裝置類型判斷:僅處理 DBT_DEVTYP_VOLUME(邏輯磁碟區)
  • 媒體標誌檢查:DBTF_MEDIA 確認光碟實際存在
  • 自動播放協調:處理 QueryCancelAutoPlay 避免與系統自動播放衝突
  • Unicode/ANSI 兼容:使用 _T() 巨集支援雙字元集建置

本方案適用於 Windows 2000/XP 及以上版本,為光碟燒錄軟體、多媒體播放器等需感知光驅狀態的應用提供了輕量級解決方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved