我们需要以编程方式将文件刻录到使用Borland Turbo C ++开发的C \ C ++ Windows XP / Vista应用程序中的CD上。
什么是最简单和最好的方法来做到这一点? 我们更喜欢本地的Windows API(不依靠MFC),以便不依赖任何第三方软件/驱动程序(如果有的话)。
我们使用了以下内容:
将文件存储在由GetBurnPath返回的目录中,然后使用刻录进行写入。 GetCDRecordableInfo用于检查CD何时准备就绪。
#include <stdio.h> #include <imapi.h> #include <windows.h> struct MEDIAINFO { BYTE nSessions; BYTE nLastTrack; ULONG nStartAddress; ULONG nNextWritable; ULONG nFreeBlocks; }; //============================================================================== // Description: CD burning on Windows XP //============================================================================== #define CSIDL_CDBURN_AREA 0x003b SHSTDAPI_(BOOL) SHGetSpecialFolderPathA(HWND hwnd, LPSTR pszPath, int csidl, BOOL fCreate); SHSTDAPI_(BOOL) SHGetSpecialFolderPathW(HWND hwnd, LPWSTR pszPath, int csidl, BOOL fCreate); #ifdef UNICODE #define SHGetSpecialFolderPath SHGetSpecialFolderPathW #else #define SHGetSpecialFolderPath SHGetSpecialFolderPathA #endif //============================================================================== // Interface IDiscMaster const IID IID_IDiscMaster = {0x520CCA62,0x51A5,0x11D3,{0x91,0x44,0x00,0x10,0x4B,0xA1,0x1C,0x5E}}; const CLSID CLSID_MSDiscMasterObj = {0x520CCA63,0x51A5,0x11D3,{0x91,0x44,0x00,0x10,0x4B,0xA1,0x1C,0x5E}}; typedef interface ICDBurn ICDBurn; // Interface ICDBurn const IID IID_ICDBurn = {0x3d73a659,0xe5d0,0x4d42,{0xaf,0xc0,0x51,0x21,0xba,0x42,0x5c,0x8d}}; const CLSID CLSID_CDBurn = {0xfbeb8a05,0xbeee,0x4442,{0x80,0x4e,0x40,0x9d,0x6c,0x45,0x15,0xe9}}; MIDL_INTERFACE("3d73a659-e5d0-4d42-afc0-5121ba425c8d") ICDBurn : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetRecorderDriveLetter( /* [size_is][out] */ LPWSTR pszDrive, /* [in] */ UINT cch) = 0; virtual HRESULT STDMETHODCALLTYPE Burn( /* [in] */ HWND hwnd) = 0; virtual HRESULT STDMETHODCALLTYPE HasRecordableDrive( /* [out] */ BOOL *pfHasRecorder) = 0; }; //============================================================================== // Description: Get burn pathname // Parameters: pathname - must be at least MAX_PATH in size // Returns: Non-zero for an error // Notes: CoInitialize(0) must be called once in application //============================================================================== int GetBurnPath(char *path) { ICDBurn* pICDBurn; int ret = 0; if (SUCCEEDED(CoCreateInstance(CLSID_CDBurn, NULL,CLSCTX_INPROC_SERVER,IID_ICDBurn,(LPVOID*)&pICDBurn))) { BOOL flag; if (pICDBurn->HasRecordableDrive(&flag) == S_OK) { if (SHGetSpecialFolderPath(0, path, CSIDL_CDBURN_AREA, 0)) { strcat(path, "\\"); } else { ret = 1; } } else { ret = 2; } pICDBurn->Release(); } else { ret = 3; } return ret; } //============================================================================== // Description: Get CD pathname // Parameters: pathname - must be at least 5 bytes in size // Returns: Non-zero for an error // Notes: CoInitialize(0) must be called once in application //============================================================================== int GetCDPath(char *path) { ICDBurn* pICDBurn; int ret = 0; if (SUCCEEDED(CoCreateInstance(CLSID_CDBurn, NULL,CLSCTX_INPROC_SERVER,IID_ICDBurn,(LPVOID*)&pICDBurn))) { BOOL flag; WCHAR drive[5]; if (pICDBurn->GetRecorderDriveLetter(drive, 4) == S_OK) { sprintf(path, "%S", drive); } else { ret = 1; } pICDBurn->Release(); } else { ret = 3; } return ret; } //============================================================================== // Description: Burn CD // Parameters: None // Returns: Non-zero for an error // Notes: CoInitialize(0) must be called once in application //============================================================================== int Burn(void) { ICDBurn* pICDBurn; int ret = 0; if (SUCCEEDED(CoCreateInstance(CLSID_CDBurn, NULL,CLSCTX_INPROC_SERVER,IID_ICDBurn,(LPVOID*)&pICDBurn))) { if (pICDBurn->Burn(NULL) != S_OK) { ret = 1; } pICDBurn->Release(); } else { ret = 2; } return ret; } //============================================================================== bool GetCDRecordableInfo(long *FreeSpaceSize) { bool Result = false; IDiscMaster *idm = NULL; IDiscRecorder *idr = NULL; IEnumDiscRecorders *pEnumDiscRecorders = NULL; ULONG cnt; long type; long mtype; long mflags; MEDIAINFO mi; try { CoCreateInstance(CLSID_MSDiscMasterObj, 0, CLSCTX_ALL, IID_IDiscMaster, (void**)&idm); idm->Open(); idm->EnumDiscRecorders(&pEnumDiscRecorders); pEnumDiscRecorders->Next(1, &idr, &cnt); pEnumDiscRecorders->Release(); idr->OpenExclusive(); idr->GetRecorderType(&type); idr->QueryMediaType(&mtype, &mflags); idr->QueryMediaInfo(&mi.nSessions, &mi.nLastTrack, &mi.nStartAddress, &mi.nNextWritable, &mi.nFreeBlocks); idr->Release(); idm->Close(); idm->Release(); Result = true; } catch (...) { Result = false; } if (Result == true) { Result = false; if (mtype == 0) { // No Media inserted Result = false; } else { if ((mflags & 0x04) == 0x04) { // Writable Media Result = true; } else { Result = false; } if (Result == true) { *FreeSpaceSize = (mi.nFreeBlocks * 2048); } else { *FreeSpaceSize = 0; } } } return Result; }
为了补充接受的答案,我们添加了这个辅助函数,以编程方式更改燃烧目录,因为这是我们的要求。
typedef HMODULE (WINAPI * SHSETFOLDERPATHA)( int , HANDLE , DWORD , LPCTSTR ); int SetBurnPath( char * cpPath ) { SHSETFOLDERPATHA pSHSetFolderPath; HANDLE hShell = LoadLibraryA( "shell32.dll" ); if( hShell == NULL ) return -2; DWORD dwOrdinal = 0x00000000 + 231; pSHSetFolderPath = (SHSETFOLDERPATHA)GetProcAddress( hShell, (LPCSTR)dwOrdinal ); if( pSHSetFolderPath == NULL ) return -3; if( pSHSetFolderPath( CSIDL_CDBURN_AREA, NULL, 0, cpPath ) == S_OK ) return 0; return -1; }
你应该可以使用shell的ICDBurn接口。 回到XP日,MFC甚至没有任何CD刻录类。 我会看看能不能找到一些例子,但是我看了这一段时间已经有一段时间了。
这是MSDN站点中的IMAPI的信息http://msdn.microsoft.com/en-us/library/aa939967.aspx