c++ c windows cd-burning

c++ - Windows CD Burning API



cd-burning (5)

Debería poder usar la interfaz ICDBurn del shell. De vuelta en el día de XP, MFC ni siquiera tenía clases para la grabación de CD. Veré si puedo encontrar algunos ejemplos para ti, pero ha pasado un tiempo desde que miré esto.

Necesitamos grabar programáticamente archivos a CD en una aplicación C / C ++ Windows XP / Vista que estamos desarrollando usando Borlands Turbo C ++.

¿Cuál es la forma más simple y mejor de hacer esto? Preferiríamos una API nativa de Windows (que no dependa de MFC) para no depender de ningún software / controlador de terceros si hay alguno disponible.




Usamos lo siguiente:

Almacene los archivos en el directorio devuelto por GetBurnPath, luego escriba usando Burn. GetCDRecordableInfo se utiliza para verificar cuándo el CD está listo.

#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; }


Para complementar la respuesta aceptada, agregamos esta función auxiliar para cambiar programáticamente el directorio quemado sobre la marcha, ya que este era un requisito nuestro.

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; }