Question

Nous devons graver par programme des fichiers sur un CD dans une application C \ C ++ Windows XP / Vista que nous développons avec Borlands Turbo C ++.

Quel est le moyen le plus simple et le meilleur de procéder? Nous préférerions une API Windows native (qui ne repose pas sur MFC) afin de ne pas compter sur des logiciels / pilotes tiers, le cas échéant.

Était-ce utile?

La solution

Nous avons utilisé les éléments suivants:

Stockez les fichiers dans le répertoire renvoyé par GetBurnPath, puis écrivez à l'aide de Burn. GetCDRecordableInfo permet de vérifier que 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;
}

Autres conseils

Pour compléter la réponse acceptée, nous avons ajouté cette fonction d’aide permettant de modifier le répertoire de gravure à la volée à la volée, car c’était une exigence de notre part.

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

Il s'agit des informations relatives à IMAPI dans le site MSDN http: // msdn. microsoft.com/en-us/library/aa939967.aspx

Vous devriez pouvoir utiliser l'interface ICDBurn du shell. À l'époque des XP, MFC n'avait même pas de classe pour la gravure de CD. Je verrai si je peux trouver quelques exemples pour vous, mais cela fait longtemps que je n’ai pas regardé cela.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top