2008-09-17 8 views
13

Nous devons graver par programmation des fichiers sur CD dans une application Windows XP/Vista C \ C++ que nous développons en utilisant Borlands Turbo C++.Windows CD Burning API

Quelle est la manière la plus simple et la plus efficace de le faire? Nous préférerions une API Windows native (qui ne repose pas sur MFC) afin de ne pas dépendre d'un logiciel/pilote tiers s'il en existe un.

Répondre

15

Nous avons utilisé les suivants:

Stocker des fichiers dans le répertoire retourné par GetBurnPath, puis écrire en utilisant Graver. GetCDRecordableInfo est utilisé pour vérifier quand le CD est prêt.

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

Merci, c'est parfait. – QAZ

+0

Il fonctionne également sans privilèges d'administrateur, merci – elarmando

-1

Vous devriez pouvoir utiliser l'interface ICDBurn du shell. De retour dans la journée XP MFC n'a même pas de classes pour la gravure de CD. Je vais voir si je peux trouver des exemples pour vous, mais cela fait un moment que j'ai regardé ça.

4

Pour compléter la réponse acceptée, nous avons ajouté cette fonction d'assistance pour modifier programatically le répertoire de brûlure à la volée car cela était une exigence de la nôtre.

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