2008-09-17 9 views
13

Chúng ta cần lập trình ghi tập tin vào CD trong ứng dụng C/C++ Windows XP/Vista mà chúng tôi đang phát triển bằng cách sử dụng Borlands Turbo C++.Windows CD Burning API

Cách đơn giản nhất và tốt nhất để làm điều này là gì? Chúng tôi muốn một API cửa sổ nguyên gốc (không dựa trên MFC) để không dựa vào bất kỳ phần mềm/trình điều khiển của bên thứ ba nào nếu có sẵn.

Trả lời

15

Chúng tôi sử dụng như sau:

file Lưu trữ trong thư mục được trả về bởi GetBurnPath, sau đó viết sử dụng Burn. GetCDRecordableInfo được sử dụng để kiểm tra xem đĩa CD đã sẵn sàng chưa.

#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

Cảm ơn, điều đó hoàn hảo. – QAZ

+0

Nó cũng hoạt động mà không có đặc quyền quản trị viên, cảm ơn bạn – elarmando

-1

Bạn sẽ có thể sử dụng giao diện ICDBurn của trình bao. Quay lại trong XP ngày MFC thậm chí không có bất kỳ lớp học để ghi đĩa cd. Tôi sẽ xem nếu tôi có thể tìm thấy một số ví dụ cho bạn, nhưng nó đã được một lúc kể từ khi tôi nhìn vào điều này.

4

Để bổ sung cho câu trả lời được chấp nhận, chúng tôi đã thêm chức năng helper này để programatically thay đổi thư mục bỏng một cách nhanh chóng như thế này là một yêu cầu của chúng ta.

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