【问题标题】:Windows CD Burning APIWindows CD 刻录 API
【发布时间】:2010-09-10 03:01:12
【问题描述】:

我们需要在使用 Borlands Turbo C++ 开发的 C\C++ Windows XP/Vista 应用程序中以编程方式将文件刻录到 CD。

最简单、最好的方法是什么?我们更喜欢原生 Windows API(不依赖于 MFC),以便不依赖任何第三方软件/驱动程序(如果可用)。

【问题讨论】:

    标签: c++ c windows cd-burning


    【解决方案1】:

    您应该能够使用 shell 的 ICDBurn 接口。早在 XP 时代,MFC 甚至没有任何用于 cd 刻录的课程。我会看看能不能为你找到一些例子,但我已经有一段时间没有看到这个了。

    【讨论】:

      【解决方案2】:

      我们使用了以下内容:

      将文件存储在 GetBurnPath 返回的目录中,然后使用 Burn 进行写入。 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;
      }
      

      【讨论】:

      • 我似乎无法理解如何使用它。能否举例说明如何使用?
      【解决方案3】:

      这是 MSDN 站点 http://msdn.microsoft.com/en-us/library/aa939967.aspx 中 IMAPI 的信息

      【讨论】:

        【解决方案4】:

        为了补充已接受的答案,我们添加了此帮助函数,以便以编程方式即时更改刻录目录,因为这是我们的要求。

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

        【讨论】:

          猜你喜欢
          • 2011-05-29
          • 2011-04-07
          • 1970-01-01
          • 2014-06-16
          • 2010-10-26
          • 2011-06-02
          • 2011-05-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多