用IMAPI完成CD刻錄與設(shè)備搜索
發(fā)表時(shí)間:2024-02-08 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]代碼下載:http://download.microsoft.com/download/1/6/4/164c2a20-aeb0-460f-907d-985d83e86bd4/CQA0404.exe MFC沒(méi)有提供CD刻錄的類,但WindowsXp內(nèi)置了寫入CD的支持。如果只是復(fù)制文件...
代碼下載:
http://download.microsoft.com/download/1/6/4/164c2a20-aeb0-460f-907d-985d83e86bd4/CQA0404.exe
MFC沒(méi)有提供CD刻錄的類,但WindowsXp內(nèi)置了寫入CD的支持。如果只是復(fù)制文件和目錄,可以用shell's ICDBurn接口。如果要刻錄音頻或更近一步的實(shí)現(xiàn)對(duì)音頻的控制,那么下面會(huì)介紹一個(gè)專用的API。
ICDBurn有三個(gè)方法,HasRecordableDrive掃描系統(tǒng)內(nèi)可寫的CD驅(qū)動(dòng)器,找到的話返回TRUE。GetRecorderDriveLetter返回可寫驅(qū)動(dòng)器的盤符。最后刻錄指令通知Windows從“集結(jié)區(qū)”向可寫CD拷貝數(shù)據(jù)!凹Y(jié)區(qū)”是一個(gè)專用的文件夾,通常是"%userprofile%\Local Settings\Application Data\Microsoft\CD Burning", 但還是應(yīng)該調(diào)用SHGetFolderPath和參數(shù)CSIDL_CDBURN_AREA獲得準(zhǔn)確的目錄名。開(kāi)發(fā)者會(huì)經(jīng)常用到SHGetFolderPath,因?yàn)橛脩魰?huì)經(jīng)常手動(dòng)或用PowerTools/TweakUI等工具改變刻錄的目錄。
筆者寫了一個(gè)很短的類CCDBurn來(lái)封裝ICDBurn.這個(gè)結(jié)構(gòu)用CLSID_CDBurn調(diào)用CoCreateInstance,讀者可調(diào)試運(yùn)行。
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);
}
驅(qū)動(dòng)器盤符是在驅(qū)動(dòng)器記錄屬性中啟動(dòng)CD記錄功能的那個(gè)驅(qū)動(dòng)器。只有一個(gè)驅(qū)動(dòng)器可以設(shè)置這種屬性。假定HasRecordableDrive 返回TRUE,也就是電腦至少有一個(gè)可記錄的CD驅(qū)動(dòng)器,你要做的就是把文件拷貝到集結(jié)區(qū)內(nèi),這就是刻錄。
由于筆者很嚴(yán)謹(jǐn),我又加入了另一個(gè)步驟GetBurnFolderPath,調(diào)用SHGetSpecialFolderPath 得到一個(gè)CString形式的刻錄文件目錄:
CString path = burner.GetBurnFolderPath();
如果要寫入音樂(lè),或找到其他刻錄驅(qū)動(dòng)器,或者獲得更詳細(xì)的信息:如驅(qū)動(dòng)器是否是可寫的。對(duì)此,windows xp提供了IMAPI,它是Image Mastering API的縮寫,不要和 MAPI——用于e-mail的Messaging API 混淆。IMAPI提供了COM接口可以尋找可刻錄驅(qū)動(dòng)器和寫入數(shù)據(jù)或者指向你最近用過(guò)的光驅(qū)。
由于與COM的沖突會(huì)引起較大的問(wèn)題,筆者寫了一個(gè)小的類庫(kù),IMAPITools,解決了大多數(shù)問(wèn)題。為了說(shuō)明怎么用這個(gè)類庫(kù)筆者還寫了一個(gè)程序CDINFO。CDINFO在控制臺(tái)窗口中顯示CD記錄體的信息。
只要掌握了IMAPI,CD刻錄就不難。但I(xiàn)MAPI很龐大,在講完基礎(chǔ)后再簡(jiǎn)要的說(shuō)一下這個(gè)問(wèn)題。
首先,CDINFO創(chuàng)建了一個(gè)對(duì)象顯示驅(qū)動(dòng)器盤符和刻錄路徑。接著,創(chuàng)建CDiscMaster 打開(kāi)IMAPI session:
CDiscMaster dm; // create IDiscMaster
if (!dm.Open()) {
printf("Oops: ...");
return;
CDiscMaster 封裝了第一個(gè)主IMAPI 接口IDiscMaster。它調(diào)用CoCreateInstance創(chuàng)建 Microsoft MSDiscMasterObj 對(duì)象然后得到IDiscMaster 接口。IDiscMaster 例舉出格式和記錄器,選擇活動(dòng)記錄器等。
CD分為兩種:記錄音頻的CD-Audio和存儲(chǔ)文件的CD-ROM。它們的格式分別為Redbook和Joliet。RedBook是Philips和Sony在80年代根據(jù)“redbook" 標(biāo)準(zhǔn)制定的;Joliet是微軟擴(kuò)展ISO-9660制定的一種CD-ROM文件格式。微軟在win95時(shí)代制定Joliet是為了擴(kuò)展ISO-9660從而支持長(zhǎng)文件名和多層目錄。
IDiscMaster::EnumDiscMasterFormats可以例舉出刻錄器支持哪種格式,但是這種方法很耗費(fèi)資源,我用一個(gè)簡(jiǎn)單的方法實(shí)現(xiàn)了這個(gè)功能,CDiscMaster::GetSupportedFormats在數(shù)組IID中返回格式:
const MAXNFORMATS = 2;
IID fmts[MAXNFORMATS];
int nFormats = dm.GetSupportedFormats(fmts,MAXNFORMATS);
fmts數(shù)組中包含了支持的格式,IID_IRedbookDiscMaster和IID_IJoiletDiscMaster,而再也不用使用IEnumDiscMasterFormats了。有經(jīng)驗(yàn)的程序員可能會(huì)提出疑問(wèn):為什么IMAPI的設(shè)計(jì)者選擇一個(gè)這么復(fù)雜的API來(lái)獲得只有兩種的支持格式,一行簡(jiǎn)單的代碼就可以提供足夠的帶寬來(lái)傳送信息。這只有設(shè)計(jì)者知道答案,也許他們希望有人會(huì)用VB寫一個(gè)音頻記錄器。不管怎樣,只要你使用了IMAPITools,你就會(huì)忘記COM。
一旦打開(kāi)一個(gè)session,就可以實(shí)現(xiàn)查詢單個(gè)的刻錄驅(qū)動(dòng)器。但I(xiàn)MAPI會(huì)再一次使用COM例舉刻錄器,而筆者又用一個(gè)類隱藏了這個(gè)結(jié)構(gòu)。
CDiscRecorder dr;
CDiscRecorderIterator itr(dm); // dm=CDiscMaster
while (itr.Next(dr)) {
// do something
}
程序每次調(diào)用下一步,累加器就會(huì)抓取下一段記錄到CDiscRecorder中。CDiscRecorder封裝了其他大的IMAPI接口,CDiscRecorder代表了可記錄CD設(shè)備。CDiscRecorder提供了打開(kāi)記錄器的方法,詢問(wèn)它的類型(CD-R or CD-RW)和路徑,得到設(shè)備屬性,彈出CD等等。CDINFO演示了如何用CDiscRecorder獲得記錄器的所有信息。
要把數(shù)據(jù)寫入光盤,就要使用IJolietDiscMaster或IRedbookDiscMaster,或者也可以用IMAPITools:
dm.SetActiveDiscRecorder(dr); // select recorder
CJolietDiscMaster jdm(dm); // get joliet interface
jdm保存了IJolietDiscMaster接口,可以調(diào)用任何IJolietDiscMaster方法。AddData是寫入數(shù)據(jù)方法的一種;它需要一個(gè)COM IStorage指針。寫入音頻也是一樣的,除非是用IRedbookDiscMaster和AddAudioTrackBlocks 添加未處理的音頻數(shù)據(jù)(44.1 KHz, 16-bit RAW, WAV 文件也相同)。創(chuàng)建多音軌可以用Create/CloseAudioTrack。AddData 和AddAudioTrackBlocks實(shí)際上不往光盤中寫數(shù)據(jù),而是寫到集結(jié)區(qū)中。如果要真正的移動(dòng)數(shù)據(jù),還需要調(diào)用RecordDisc:
BOOL bSimulate=FALSE;
BOOL bEjectAfterBurn=TRUE;
dm.RecordDisc(bSimulate, bEjectAfterBurn);
dm.Close();
bSimulate=TRUE會(huì)調(diào)用RecordDisc模擬刻錄但實(shí)際上并未寫入。Windows檢查全部預(yù)刻錄列表并刻錄,但實(shí)際上并沒(méi)有寫入。這可以讓開(kāi)發(fā)者測(cè)試和調(diào)試軟件而并不需要花很多時(shí)間真正的刻錄光盤。
以上簡(jiǎn)單介紹了一下IMAPI,但這足夠你開(kāi)始刻錄編程了。大多數(shù)人都會(huì)調(diào)用IMAPI,除非要寫一個(gè)復(fù)雜的備份程序或音頻紀(jì)錄器。對(duì)于普通的拷貝文件,要用到的就是ICDBurn。即使你要顯示出可記錄驅(qū)動(dòng)器列表,用IMAPI也足夠了。