COM 组件设计与应用(一) 学习笔记
打今起开始学习VC知识库里杨老师的 COM 组件设计与应用 文章,将学习心得整理与此,防止我这老年痴呆会慢慢的忘记,
好嘞,今天就开始第一篇 http://www.vckbase.com/document/viewdoc/?id=1483 COM 组件设计与应用(一)起源复合文件
一. 文件的存储
1. 非结构化文件 打开记事本程序,输入了一篇文章后,保存。——这样的文件叫“非结构化文件”;
2. 标准结构化文件 打开电子表格程序,输入一个班的学生姓名和考试成绩,保存。——这样的文件叫“标准结构化文件”;
3. 自定义结构化文件 在我们写的程序中,需要把特定的数据按照一定的结构和顺序写到文件中保存。这样的文件叫“自定义结构化文件”如 .bmp
4. 复合结构文件 俗称“文件中的文件系统”,ActiveX、OLE、COM的起源,

二. 复合文件的特点
1. 复合文件的内部是使用指针构造的一棵树进行管理的。编写程序的时候要注意,由于使用的是单向指针,因此当做定位操作的时候,向后定位比向前定位要快;
2. 复合文件中的“流对象”,是真正保存数据的空间。它的存储单位为512字节。也就是说,即使你在流中只保存了一个字节的数据,它也要占据512字节的文件空间。啊~~~,这也太浪费了呀?不浪费!因为文件保存在磁盘上,即使一个字节也还要占用一个“簇”的空间那;
3. 不同的进程,或同一个进程的不同线程可以同时访问一个复合文件的不同部分而互不干扰;
4. 大家都有这样的体会,当需要往一个文件中插入一个字节的话,需要对整个文件进行操作,非常烦琐并且效率低下。而复合文件则提供了非常方便的“增量访问”能力;
5. 当频繁地删除文件,复制文件后,磁盘空间会变的很零碎,需要使用磁盘整理工具进行重新整合。和磁盘管理非常相似,复合文件也会产生这个问题,在适当的时候也需要整理,但比较简单,只要调用一个函数就可以完成了。
VC6.0 附带了一个工具软件“复合文件浏览器”,文件名是“vc目录\Common\Tools\DFView.exe”。
杨老师的作业我只完成了第一个: 写个小应用程序,从 MSWORD 的 doc 文件中,提取出附加信息(作者)
代码如下:
CString filter_str;
filter_str= "word files (*.doc)|*.doc||";
CFileDialog mSaveDlg(TRUE,NULL,NULL,NULL,filter_str,NULL);//初始化
mSaveDlg.DoModal();//显示
CString sFilePathNamem = mSaveDlg.GetPathName();
// TODO: 在此添加控件通知处理程序代码
LPCTSTR lpFileName = sFilePathNamem;
HRESULT hr;
IStorage *pStg = NULL;
IStream *pIStream = NULL;
USES_CONVERSION; // (注6)
LPCOLESTR lpwFileName = T2COLE( lpFileName ); // 转换T类型为宽字符
hr = ::StgIsStorageFile( lpwFileName ); // 是复合文件吗?
if( FAILED(hr) ) return;
hr = ::StgOpenStorage( // 打开复合文件
lpwFileName, // 文件名称
NULL,
STGM_READ | STGM_SHARE_DENY_WRITE,
0,
0,
&pStg); // 得到根存储接口指针
IEnumSTATSTG *pEnum=NULL; // 枚举器
hr = pStg->EnumElements( 0, NULL, 0, &pEnum );
ASSERT( SUCCEEDED(hr) );
STATSTG statstg;
char sTemp[20]; memset(sTemp,0,20);
strcpy(sTemp,"|SummaryInformation"); sTemp[0] = 5;
while( NOERROR == pEnum->Next( 1, &statstg, NULL) )
{
if (!strcmp(OLE2A(statstg.pwcsName),sTemp))
{
hr = pStg->OpenStream(statstg.pwcsName,NULL, STGM_SHARE_EXCLUSIVE ,0,&pIStream);
LARGE_INTEGER laint;
laint.HighPart = 0x00;
laint.LowPart = 0xE0; // 复合结构 流数据的 空间地址,而非数据地址
hr = pIStream->Seek(laint,STREAM_SEEK_SET,NULL);
BYTE bBuffer[200];
memset(bBuffer,0,200);
hr = pIStream->Read(bBuffer,200,NULL);
CString csTemp;
csTemp = bBuffer;
GetDlgItem(IDC_STATIC_Name)->SetWindowText(csTemp);
break;
}
}
if( pEnum ) pEnum->Release();
if( pStg ) pStg->Release();
该Demo一读取出word 07的话崩溃
如果是指Word97-Word2003之间的二进制格式的doc文件的话,那它们都是复合文档,且里面有一个名为"WordDocument"的流;
如果是Word2007的新格式docx文件,那它本身是一个zip包(将它扩展名改为.zip就可以用解压缩工具打开),里面的文件都是xml格式的文件可以直接读出来看;
但是 为什么微软这么做呢? 不知 费解
有时间的话,琢磨琢磨把第二个作业也完成了。
好嘞,今天就开始第一篇 http://www.vckbase.com/document/viewdoc/?id=1483 COM 组件设计与应用(一)起源复合文件
一. 文件的存储
1. 非结构化文件 打开记事本程序,输入了一篇文章后,保存。——这样的文件叫“非结构化文件”;
2. 标准结构化文件 打开电子表格程序,输入一个班的学生姓名和考试成绩,保存。——这样的文件叫“标准结构化文件”;
3. 自定义结构化文件 在我们写的程序中,需要把特定的数据按照一定的结构和顺序写到文件中保存。这样的文件叫“自定义结构化文件”如 .bmp
4. 复合结构文件 俗称“文件中的文件系统”,ActiveX、OLE、COM的起源,
图一、左侧表示一个磁盘下的文件组织方式,右侧表示一个复合文件内部的数据组织方式。
二. 复合文件的特点
1. 复合文件的内部是使用指针构造的一棵树进行管理的。编写程序的时候要注意,由于使用的是单向指针,因此当做定位操作的时候,向后定位比向前定位要快;
2. 复合文件中的“流对象”,是真正保存数据的空间。它的存储单位为512字节。也就是说,即使你在流中只保存了一个字节的数据,它也要占据512字节的文件空间。啊~~~,这也太浪费了呀?不浪费!因为文件保存在磁盘上,即使一个字节也还要占用一个“簇”的空间那;
3. 不同的进程,或同一个进程的不同线程可以同时访问一个复合文件的不同部分而互不干扰;
4. 大家都有这样的体会,当需要往一个文件中插入一个字节的话,需要对整个文件进行操作,非常烦琐并且效率低下。而复合文件则提供了非常方便的“增量访问”能力;
5. 当频繁地删除文件,复制文件后,磁盘空间会变的很零碎,需要使用磁盘整理工具进行重新整合。和磁盘管理非常相似,复合文件也会产生这个问题,在适当的时候也需要整理,但比较简单,只要调用一个函数就可以完成了。
VC6.0 附带了一个工具软件“复合文件浏览器”,文件名是“vc目录\Common\Tools\DFView.exe”。
杨老师的作业我只完成了第一个: 写个小应用程序,从 MSWORD 的 doc 文件中,提取出附加信息(作者)
代码如下:
CString filter_str;
filter_str= "word files (*.doc)|*.doc||";
CFileDialog mSaveDlg(TRUE,NULL,NULL,NULL,filter_str,NULL);//初始化
mSaveDlg.DoModal();//显示
CString sFilePathNamem = mSaveDlg.GetPathName();
// TODO: 在此添加控件通知处理程序代码
LPCTSTR lpFileName = sFilePathNamem;
HRESULT hr;
IStorage *pStg = NULL;
IStream *pIStream = NULL;
USES_CONVERSION; // (注6)
LPCOLESTR lpwFileName = T2COLE( lpFileName ); // 转换T类型为宽字符
hr = ::StgIsStorageFile( lpwFileName ); // 是复合文件吗?
if( FAILED(hr) ) return;
hr = ::StgOpenStorage( // 打开复合文件
lpwFileName, // 文件名称
NULL,
STGM_READ | STGM_SHARE_DENY_WRITE,
0,
0,
&pStg); // 得到根存储接口指针
IEnumSTATSTG *pEnum=NULL; // 枚举器
hr = pStg->EnumElements( 0, NULL, 0, &pEnum );
ASSERT( SUCCEEDED(hr) );
STATSTG statstg;
char sTemp[20]; memset(sTemp,0,20);
strcpy(sTemp,"|SummaryInformation"); sTemp[0] = 5;
while( NOERROR == pEnum->Next( 1, &statstg, NULL) )
{
if (!strcmp(OLE2A(statstg.pwcsName),sTemp))
{
hr = pStg->OpenStream(statstg.pwcsName,NULL, STGM_SHARE_EXCLUSIVE ,0,&pIStream);
LARGE_INTEGER laint;
laint.HighPart = 0x00;
laint.LowPart = 0xE0; // 复合结构 流数据的 空间地址,而非数据地址
hr = pIStream->Seek(laint,STREAM_SEEK_SET,NULL);
BYTE bBuffer[200];
memset(bBuffer,0,200);
hr = pIStream->Read(bBuffer,200,NULL);
CString csTemp;
csTemp = bBuffer;
GetDlgItem(IDC_STATIC_Name)->SetWindowText(csTemp);
break;
}
}
if( pEnum ) pEnum->Release();
if( pStg ) pStg->Release();
该Demo一读取出word 07的话崩溃
如果是指Word97-Word2003之间的二进制格式的doc文件的话,那它们都是复合文档,且里面有一个名为"WordDocument"的流;
如果是Word2007的新格式docx文件,那它本身是一个zip包(将它扩展名改为.zip就可以用解压缩工具打开),里面的文件都是xml格式的文件可以直接读出来看;
但是 为什么微软这么做呢? 不知 费解
有时间的话,琢磨琢磨把第二个作业也完成了。