小弟想實現將硬盤某個文件夾下的文件刻錄到光盤上
我不想使用第三方的刻錄軟件
不知道XP系統是否有提供這樣的接口,哪位大蝦知道請給小弟一點提示:)給個思考的方向就可以了
謝過了
我不想使用第三方的刻錄軟件
不知道XP系統是否有提供這樣的接口,哪位大蝦知道請給小弟一點提示:)給個思考的方向就可以了
謝過了
醬壇子專注C++技術 在這里寫下自己的學習心得 感悟 和大家討論 共同進步(歡迎批評?。。。?/p> |
公告常用鏈接留言簿(19)我參與的團隊隨筆檔案(65)文章分類(16)文章檔案(16)相冊Blog List技術網站我的Blog搜索積分與排名
最新隨筆
最新評論
閱讀排行榜
評論排行榜 |
小弟想實現將硬盤某個文件夾下的文件刻錄到光盤上
我不想使用第三方的刻錄軟件 不知道XP系統是否有提供這樣的接口,哪位大蝦知道請給小弟一點提示:)給個思考的方向就可以了 謝過了 Feedback
<轉:在網上看見的別人寫的東西>
關于使用IMAPI的一些問題 工作中要求使用IMAPI寫一個小的刻錄測試程序,苦于資料較少,但最后大體理出一些內容,并初步測試通過,把一些心得和問題記錄在此。希望交流一下。程序基于MSDN (April 2004)和微軟工程師Paul DiLascia的一個例程,并作了一定修改,環境是XPsp2和VS.net2003(MFC)。 1.IDiscMaster::ProgressAdvise()的使用 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 聲明一個類,從接口繼承 class CDiscMasterProgressEvents : public CComQIPtr<IDiscMasterProgressEvents> { public: HRESULT m_hr; int m_nRefCount; // 進度條控件 CProgressCtrl * m_pCtlProgress; // 構造和析構 CDiscMasterProgressEvents(/*CWnd * pWnd*/); ULONG __stdcall AddRef(void); ULONG __stdcall Release(void); HRESULT __stdcall QueryInterface(REFIID riid, void **ppv); // 以下為一些消息的回調函數 // 刻錄結束后被IMAPI調用(Reports that the burn is fully complete.IDiscMaster::RecordDisc()結束時調用) HRESULT __stdcall NotifyBurnComplete(HRESULT status); ............................. }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //類實現代碼 ULONG __stdcall CDiscMasterProgressEvents::AddRef(void) { return ++m_nRefCount; } ULONG __stdcall CDiscMasterProgressEvents::Release(void) { if (--m_nRefCount) return m_nRefCount; delete this; return 0L; } HRESULT __stdcall CDiscMasterProgressEvents::QueryInterface(REFIID riid, void **ppv) { if(riid == IID_IUnknown) { *ppv = (LPUNKNOWN)(IDiscMasterProgressEvents*)this; m_nRefCount++; return NOERROR; } else if(riid == IID_IDiscMasterProgressEvents) { *ppv = (IDiscMasterProgressEvents*)this; m_nRefCount++; return NOERROR; } else { *ppv = NULL; return E_NOINTERFACE; } } // 刻錄結束后被IMAPI調用 HRESULT __stdcall CDiscMasterProgressEvents::NotifyBurnComplete(HRESULT status) { if (status == S_OK) { AfxMessageBox("刻錄完畢"); if (m_pCtlProgress) { m_pCtlProgress->SetPos(0); } } return status ; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 類的使用 .......... CDiscMasterProgressEvents * pEvent = new CDiscMasterProgressEvents; pEvent->m_pCtlProgress = &(pDlg->m_progBurning); UINT_PTR m_nCookie = 0; // dm為CDIscMater(class CDiscMaster : public CComQIPtr<IDiscMaster>) hr = dm.ProgressAdvise(pEvent, &m_nCookie); // ok .......... hr = dm.RecodeDisc(0, 0); 2. IJolietDiscMaster::AddData()前,所有IStream.Release()和子ISubStorage.Release(); 如果沒有釋放,我遇到的問題是數據刻錄到光盤中,但卻看不到;根IStorage在AddData后Release() 3.文件名和文件夾名的問題 pStorage->CreateStream(const WCHAR* pwcsName, ....); // 參數對應刻錄后的文件名 pStorage->CreateStorage(const WCHAR* pwcsName, .....); // 參數對應刻錄后的子文件夾名 上面的兩個參數都不能超過31個字符,不能使用某些特殊字符(!等),否則會造成創建失??;沒有查到資料如何處理超過31字符的文件名,如果有解決問題的方法,希望能和大家交流。 4.光盤的Volume(沒有測試) 通過IJolietDiscMaster::GetJolietProperties()得到;對應的一個IJolietDiscMaster::SetJolietProperties() 5.IDiscRecorder::GetPath(BSTR* pbstrPath)(未解決) 得到刻錄機路徑,MSDN說明: Parameters pbstrPath [out] Path to the disc recorder. This can be a drive letter such as 'E:\', or a full path such as '\Device\CdRom0'. 測試程序中得到的是后者,還沒有找到合理的方式來把兩者掛鉤,特別是多光驅情況下 回復 更多評論
http://download.microsoft.com/download/1/6/4/164c2a20-aeb0-460f-907d-985d83e86bd4/CQA0404.exe
用IMAPI實現CD刻錄和設備查找 MFC沒有提供CD刻錄的類,但WindowsXp內置了寫入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(); 如果要寫入音樂,或找到其他刻錄驅動器,或者獲得更詳細的信息:如驅動器是否是可寫的。對此,windows xp提供了IMAPI,它是Image Mastering API的縮寫,不要和 MAPI——用于e-mail的Messaging API 混淆。IMAPI提供了COM接口可以尋找可刻錄驅動器和寫入數據或者指向你最近用過的光驅。 由于與COM的沖突會引起較大的問題,筆者寫了一個小的類庫,IMAPITools,解決了大多數問題。為了說明怎么用這個類庫筆者還寫了一個程序CDINFO。CDINFO在控制臺窗口中顯示CD記錄體的信息。 只要掌握了IMAPI,CD刻錄就不難。但IMAPI很龐大,在講完基礎后再簡要的說一下這個問題。 首先,CDINFO創建了一個對象顯示驅動器盤符和刻錄路徑。接著,創建CDiscMaster 打開IMAPI session: CDiscMaster dm; // create IDiscMaster if (!dm.Open()) { printf("Oops: ..."); return; CDiscMaster 封裝了第一個主IMAPI 接口IDiscMaster。它調用CoCreateInstance創建 Microsoft MSDiscMasterObj 對象然后得到IDiscMaster 接口。IDiscMaster 例舉出格式和記錄器,選擇活動記錄器等。 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等等。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也足夠了。 回復 更多評論
|