本文将就在Windows XP/Windows 2003下如何使用ImapiService来实现CD/DVD刻录功能。
前提条件:
操作系统必须为Windows XP及Windows 2003以上。因为,在这两种平台下才提供ImapiService服务,缺省的,在Windows XP下,该服务是被设置为自动启动的,而在Windows 2003下,该服务为禁用的,也就需要手工来将其打开。这里就不写如何开启服务了。
开发平台,VS.NET 2003/VS.NET 2005并需要额外下载Windows Platform SDK,因为,VS.NET里的PlatformSDK是没有带入Imapi的支持的。安装了Windows PlatformSDK后,你便可以在C:\Program Files\Microsoft SDKs\Windows\v1.0下找到你所需要的imapi.h及imapierror.h文件,这时,你就可以在你的程序中引用它了。由于Imapi使用的是COM接口,所以你无须添加lib文件。
OK,准备结束。让我开始做这个刻录软件吧。
首先,我们需实例化IDiscMaster。CLSID_MSDiscMasterObj是它的CLSID。 这里我们使用了ATL的智能指针模板。
CComQIPtr<IDiscMaster> dm;
HRESULT m_hr = CoCreateInstance(CLSID_MSDiscMasterObj, &dm, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER);
如果宏SUCCEEDED( m_hr )返回为TRUE的话,表明IDiscMaster初始化成功。这样,我们可以继续下面的操作。
初始化成功后,我们就可以调用Open方法来打开DiscMaster,记住,以后的任何一个步骤的前提条件都是要调用这个方法,否则会返回一个IMAPI_E_NOTOPENED错误。
在真正开始刻录之前,Imapi要求我们首先得告诉它使用哪个刻录机及什么样的格式来进行刻录,讲到这个格式,我们先弄明白,Windows所支持的格式有哪些。其实,这个格式大概的划分起来就两种,一种是众所周知的如CD的音频格式,另一种是我们经常使用的数据CD格式ISO9660及它的扩展Joliet。这里我们将需要使用到下面四种接口:
IDiscRecorder
IEnumDiscRecorders
IJolietDiscMaster
IRedbookDiscMaster
其中, IDiscRecorder是用来操作刻录机的COM接口。IEnumDiscRecorders是用来遍历所有的Recorder的接口,我们可以使用下面的方法来遍历所有的刻录机。
HRESULT hr;
CComQIPtr<IEnumDiscRecorders> enumRecorders;
CComQIPtr<IDiscRecorder> Recorders;
hr = dm->EnumDiscRecorders( &enumRecorders );
if( SUCCEEDED( hr ) ){
UINT nRet = 0;
while( SUCCEEDED( hr= enumRecorder->Next(1, &recorder.p, &nRet)) && nRet==1 ){
///You can set the ActiveDiscRecorder and Active format here.
dm->SetActiveDiscRecorder( recorder );
///说明将按数据CD的格式来刻录。
dm->SetActiveDiscMasterFormat( IID_IJolietDiscMaster, &recorder );
}
}
然后使用IJolietDiscMaster来将DiscMaster特例化,当我也可用IRedbookDiscMaster来将特例化。
CComQIPtr<IJolietDiscMaster> jdm(dm);
做完这些后,Imapi刻录机的状态就基本上准备完成了。接下的是我们要准备如何将想要的数据刻录到CD里。那在这里就有必要搞明白一个接口:
IStorage;
IStorage是微软提供的用于结构化存储的接口,在该接口中有子存储及子对象之分,分别可以使用方法CreateStorage及CreateStream来创建。而其中所创建的子Storage的话,则会当作目录被刻入到CD中,而Stream就会被当作文件写入到CD中。下面的程序将指定目录下的文件来组织成一个IStorage对象。
ULONGLONG PerformFileStream( const char *pFileName, IStream *stream ){
CFile file;
char *pBuffer = NULL;
bool isOpened = false;
UINT BufferSize = 40960;
ULONGLONG m_ReadedSize = 0L;
try{
if( file.Open( pFileName, CFile::modeRead ) ){
is