程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 用IMAPI實現CD刻錄和設備查找

用IMAPI實現CD刻錄和設備查找

編輯:關於VC++

我讀了你在 January 2004 中有關獲取驅動器盤符以及用 GetDriveType 函數判定某個磁盤是否為 CD(DRIVE_CDROM)的專欄文章,但我如何才能知道 CD 驅動器是不是刻錄設備呢?此外,如何將文件寫入可擦寫 CD?Windows XP 允許你用 Windows 資源管理拖拽文件,並將其寫入CD。你能否告知有沒有什麼方法從我的程序中實現,而不需要用戶購買第三方軟件,如:Nero 或者 Roxio? 有沒有相關的 MFC 類可以實現這個功能?

MFC 沒有提供 CD 刻錄的類,但 Windows Xp 內置了寫入 CD 的支持。如果只是復制文件和目錄,可以用 shell''s ICDBurn 接口。如果要刻錄音頻或更近一步的實現對音頻的控制,那麼下面會介紹一個專用的 API。

用 ICDBurn 有三個步驟,HasRecordableDrive 掃描系統內可寫的CD驅動器,找到的話返回TRUE。GetRecorderDriveLetter 返回可寫驅動器的盤符。最後刻錄指令通知 Windows 從“集結區”向可寫 CD 拷貝數據。“集結區”是一個專用的文件夾,通常是“%userprofile%\Local Settings\Application Data\Microsoft\CD Burning”,但還是應該調用 SHGetFolderPath 和參數 CSIDL_CDBURN_AREA 獲得准確的目錄名。開發者會經常用到 SHGetFolderPath,因為用戶會經常手動或用 PowerTools/TweakUI 等工具改變刻錄的目錄。

筆者寫了一個很短的類 CCDBurn 來封裝 ICDBurn。這個結構用 CLSID_CDBurn 調用 CoCreateInstance,讀者可調試運行。

CCDBurn burner;
if (!burner.HasRecordableDrive()) {
  printf("Oops—No recordable drive!\n");
} else {
  CString dl =
    burner.GetRecorderDriveLetter();
  printf("Default Recorder drive letter =
    %s\n", (LPCTSTR)dl);
}

驅動器盤符是在驅動器記錄屬性中啟動CD記錄功能的那個驅動器。只有一個驅動器可以設置這種屬性。假定 HasRecordableDrive 返回TRUE,也就是電腦至少有一個可記錄的CD驅動器,你要做的就是把文件拷貝到集結區內,這就是刻錄。

由於筆者很嚴謹,我又加入了另一個步驟 GetBurnFolderPath,調用 SHGetSpecialFolderPath 得到一個 CString 形式的刻錄文件目錄:

CString path = burner.GetBurnFolderPath();

Figure 1 CD 驅動的刻錄屬性

如果你想刻錄音樂,或找到其它刻錄驅動器(可能有多個),或者獲得更詳細的信息:如制造或型號,或者驅動器是 CD-R 還是 CD-RW?為此,Windows XP 提供了 IMAPI 來實現這些特性,它是 Image Mastering API 的縮寫,不要和 MAPI——用於 e-mail 的 Messaging API 混淆。唉!要記住這些縮寫真是難啊。IMAPI 提供了 COM 接口來尋找可刻機驅動器和寫入數據,或者最新射頻探頭調諧到光光彩照人的塑膠唱盤上。有關 IMAPI 接口信息概要參見 Figure 2。

由於與 COM 的沖突會引起較大的問題,筆者寫了一個小的類庫,IMAPITools,解決了大多數問題。為了說明怎麼用這個類庫筆者還寫了一個程序 CDINFO。CDINFO 在控制台窗口中顯示CD記錄體的信息。

只要掌握了 IMAPI,CD,刻錄就不難。但 IMAPI 很龐大,在講完基礎後再簡要的說一下這個問題。

Figure 3 CDINFO

首先,CDINFO創建了一個對象顯示驅動器盤符和刻錄路徑。接著,創建 CDiscMaster 打開IMAPI session:

CDiscMaster dm; // create IDiscMaster
 if (!dm.Open()) {
   printf("Oops: ...");
   return;
 }

CDiscMaster 封裝了第一個主 IMAPI 接口 IDiscMaster。它調用 CoCreateInstance 創建 Microsoft MSDiscMasterObj 對象然後得到 IDiscMaster 接口。IDiscMaster 例舉出格式和記錄器,選擇活動記錄器等。

Figure 5 MSDiscMasterObj 接口

CD分為兩種:記錄音頻的 CD-Audio 和存儲文件的 CD-ROM。它們的格式分別為 Redbook 和 Joliet。RedBook 是 Philips 和 Sony 在80年代根據“redbook”標准制定的;Joliet 是微軟擴展 ISO-9660 制定的一種 CD-ROM 文件格式。微軟在 Win95 時代制定 Joliet 是為了擴展 ISO-9660 從而支持長文件名和多層目錄。

IDiscMaster::EnumDiscMasterFormats 可以例舉出刻錄器支持哪種格式,但是這種方法很耗費資源,我用一個簡單的方法實現了這個功能,CDiscMaster::GetSupportedFormats 在數組 IID 中返回格式:

const MAXNFORMATS = 2;
IID fmts[MAXNFORMATS];
int nFormats = dm.GetSupportedFormats(fmts,MAXNFORMATS);

fmts 數組中包含了支持的格式,IID_IRedbookDiscMaster 和 IID_IJoiletDiscMaster,而再也不用使用 IEnumDiscMasterFormats 了。有經驗的程序員可能會提出疑問:為什麼IMAPI的設計者選擇一個這麼復雜的API來獲得只有兩種的支持格式,一行簡單的代碼就可以提供足夠的帶寬來傳送信息。這只有設計者知道答案,也許他們希望有人會用VB寫一個音頻記錄器。不管怎樣,只要你使用了IMAPITools。你就會忘記 COM。

一旦打開一個 session,就可以實現查詢單個的刻錄驅動器。但IMAPI會再一次使用COM例舉刻錄器,而筆者又用一個類隱藏了這個結構。

CDiscRecorder dr;
CDiscRecorderIterator itr(dm); // dm=CDiscMaster
while (itr.Next(dr)) {
// do something
}

程序每次調用下一步,累加器就會抓取下一段記錄到 CDiscRecorder 中。CDiscRecorder 封裝了其它大的 IMAPI 接口,CDiscRecorder 代表了可記錄CD設備。CDiscRecorder 提供了打開記錄器的方法,詢問它的類型(CD-R or CD-RW)和路徑,得到指定設備的屬性,彈出 CD 等等。Figure 4 是 IDiscRecorder 接口的方法列表。CDINFO 演示了如何用 CDiscRecorder 獲得記錄器的所有信息。

要把數據寫入光盤,就要使用 IJolietDiscMaster或IRedbookDiscMaster,或者也可以用 IMAPITools:

dm.SetActiveDiscRecorder(dr); // select recorder
CJolietDiscMaster jdm(dm); // get joliet interface

jdm 保存了 IJolietDiscMaster 接口,可以調用任何 IJolietDiscMaster 方法。AddData 是寫入數據方法的一種;它需要一個 COM IStorage 指針。寫入音頻也是一樣的,除非是用 IRedbookDiscMaster 和 AddAudioTrackBlocks 添加未處理的音頻數據(44.1 KHz, 16-bit RAW, WAV 文件也相同)。創建多音軌可以用 Create/CloseAudioTrack。AddData 和 AddAudioTrackBlocks實際上不往光盤中寫數據,而是寫到集結區中。如果要真正的移動數據,還需要調用 RecordDisc:

BOOL bSimulate=FALSE;
BOOL bEjectAfterBurn=TRUE;
dm.RecordDisc(bSimulate, bEjectAfterBurn);
dm.Close();

bSimulate = TRUE 會調用 RecordDisc 模擬刻錄但實際上並未寫入。Windows 檢查全部預刻錄列表並刻錄,但實際上並沒有寫入。這可以讓開發者測試和調試軟件而並不需要花很多時間真正的刻錄光盤。

以上簡單介紹了一下 IMAPI,但這足夠你開始刻錄編程了。大多數人都會調用 IMAPI,除非要寫一個復雜的備份程序或音頻紀錄器。對於普通的拷貝文件,要用到的就是 ICDBurn。即使你要顯示出可記錄驅動器列表,用 IMAPI 也足夠了。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved