工作中要求使用IMAPI写一个小的刻录测试程序,苦于资料较少,但最后大体理出一些内容,并初步测试通过,把一些心得和问题记录在此。希望交流一下。程序基于MSDN (April 2004)和微软工程师Paul DiLascia的一个例程,并作了一定修改,环境是XPsp2和VS.net2003(MFC)。
1.IDiscMaster::ProgressAdvise()的使用
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 声明一个类,从接口继承
class CDiscMasterProgressEvents : public CComQIPtr<IDiscMasterProgressEvents>
{
public:
HRESULT m_hr;
int m_nRefCount;
{
public:
HRESULT m_hr;
int m_nRefCount;
// 进度条控件
CProgressCtrl * m_pCtlProgress;
// 构造和析构
CDiscMasterProgressEvents(/*CWnd * pWnd*/);
CDiscMasterProgressEvents(/*CWnd * pWnd*/);
ULONG __stdcall AddRef(void);
ULONG __stdcall Release(void);
HRESULT __stdcall QueryInterface(REFIID riid, void **ppv);
ULONG __stdcall Release(void);
HRESULT __stdcall QueryInterface(REFIID riid, void **ppv);
// 以下为一些消息的回调函数
// 刻录结束后被IMAPI调用(Reports that the burn is fully complete.IDiscMaster::RecordDisc()结束时调用)
HRESULT __stdcall NotifyBurnComplete(HRESULT status);
// 刻录结束后被IMAPI调用(Reports that the burn is fully complete.IDiscMaster::RecordDisc()结束时调用)
HRESULT __stdcall NotifyBurnComplete(HRESULT status);
.............................
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//类实现代码
ULONG __stdcall CDiscMasterProgressEvents::AddRef(void)
{
return ++m_nRefCount;
}
{
return ++m_nRefCount;
}
ULONG __stdcall CDiscMasterProgressEvents::Release(void)
{
if (--m_nRefCount)
return m_nRefCount;
delete this;
return 0L;
}
{
if (--m_nRefCount)
return m_nRefCount;
delete this;
return 0L;
}
HRESULT __stdcall CDiscMasterProgressEvents::QueryInterface(REFIID riid, void **ppv)
{
if(riid == IID_IUnknown)
{
*ppv = (LPUNKNOWN)(IDiscMasterProgressEvents*)this;
m_nRefCount++;
return NOERROR;
}
else if(riid == IID_IDiscMasterProgressEvents)
{
*ppv = (IDiscMasterProgressEvents*)this;
m_nRefCount++;
return NOERROR;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
}
{
if(riid == IID_IUnknown)
{
*ppv = (LPUNKNOWN)(IDiscMasterProgressEvents*)this;
m_nRefCount++;
return NOERROR;
}
else if(riid == IID_IDiscMasterProgressEvents)
{
*ppv = (IDiscMasterProgressEvents*)this;
m_nRefCount++;
return NOERROR;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
}
// 刻录结束后被IMAPI调用
HRESULT __stdcall CDiscMasterProgressEvents::NotifyBurnComplete(HRESULT status)
{
if (status == S_OK)
{
AfxMessageBox("刻录完毕");
if (m_pCtlProgress)
{
m_pCtlProgress->SetPos(0);
}
HRESULT __stdcall CDiscMasterProgressEvents::NotifyBurnComplete(HRESULT status)
{
if (status == S_OK)
{
AfxMessageBox("刻录完毕");
if (m_pCtlProgress)
{
m_pCtlProgress->SetPos(0);
}
}
return status ;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 类的使用
..........
CDiscMasterProgressEvents * pEvent = new CDiscMasterProgressEvents;
pEvent->m_pCtlProgress = &(pDlg->m_progBurning);
UINT_PTR m_nCookie = 0;
pEvent->m_pCtlProgress = &(pDlg->m_progBurning);
UINT_PTR m_nCookie = 0;
// dm为CDIscMater(class CDiscMaster : public CComQIPtr<IDiscMaster>)
hr = dm.ProgressAdvise(pEvent, &m_nCookie); // ok
..........
hr = dm.RecodeDisc(0, 0);
2.
IJolietDiscMaster::AddData()前,所有IStream.Release()和子ISubStorage.Release();
如果没有释放,我遇到的问题是数据刻录到光盘中,但却看不到;根IStorage在AddData后Release()
3.文件名和文件夹名的问题
pStorage->CreateStream(
const WCHAR*
pwcsName
, ....); // 参数对应刻录后的文件名
pStorage->CreateStorage(
const WCHAR*
pwcsName
, .....); // 参数对应刻录后的子文件夹名
上面的两个参数都不能超过31个字符,不能使用某些特殊字符(!等),否则会造成创建失败;没有查到资料如何处理超过31字符的文件名,如果有解决问题的方法,希望能和大家交流。
4.光盘的Volume(没有测试)
通过IJolietDiscMaster::GetJolietProperties()得到;对应的一个IJolietDiscMaster::SetJolietProperties()
5.IDiscRecorder::GetPath(BSTR* pbstrPath)(未解决)
得到刻录机路径,MSDN说明:
Parameters
pbstrPath
[out] Path to the disc recorder. This can be a drive letter such as 'E:/', or a full path such as '/Device/CdRom0'.
测试程序中得到的是后者,还没有找到合理的方式来把两者挂钩,特别是多光驱情况下