COM 学习(一)复合文件
2008-03-25 16:47 Jaypei 阅读(1068) 评论(0) 编辑 收藏 举报复合文档测试
WIN API 函数 |
功能说明 |
StgCreateDocfile() | 建立一个复合文件,得到根存储对象 |
StgOpenStorage() | 打开一个复合文件,得到根存储对象 |
StgIsStorageFile() | 判断一个文件是否是复合文件 |
|
|
IStorage 函数 |
功能说明 |
CreateStorage() | 在当前存储中建立新存储,得到子存储对象 |
CreateStream() | 在当前存储中建立新流,得到流对象 |
OpenStorage() | 打开子存储,得到子存储对象 |
OpenStream() | 打开流,得到流对象 |
CopyTo() | 复制存储下的所有对象到目标存储中,该函数可以实现“整理文件,释放碎片空间”的功能 |
MoveElementTo() | 移动对象到目标存储中 |
DestoryElement() | 删除对象 |
RenameElement() | 重命名对象 |
EnumElements() | 枚举当前存储中所有的对象 |
SetElementTimes() | 修改对象的时间 |
SetClass() | 在当前存储中建立一个特殊的流对象,用来保存CLSID(注5) |
Stat() | 取得当前存储中的系统信息 |
Release() | 关闭存储对象 |
IStream 函数 |
功能说明 |
Read() | 从流中读取数据 |
Write() | 向流中写入数据 |
Seek() | 定位读写位置 |
SetSize() | 设置流尺寸。如果预先知道大小,那么先调用这个函数,可以提高性能 |
CopyTo() | 复制流数据到另一个流对象中 |
Stat() | 取得当前流中的系统信息 |
Clone() | 克隆一个流对象,方便程序中的不同模块操作同一个流对象 |
Release() | 关闭流对象 |
WIN API 补充函数 | 功能说明 |
WriteClassStg() | 写CLSID到存储中,同IStorage::SetClass() |
ReadClassStg() | 读出WriteClassStg()写入的CLSID,相当于简化调用IStorage::Stat() |
WriteClassStm() | 写CLSID到流的开始位置 |
ReadClassStm() | 读出WriteClassStm()写入的CLSID |
WriteFmtUserTypeStg() | 写入用户指定的剪贴板格式和名称到存储中 |
ReadFmtUserTypeStg() | 读出WriteFmtUserTypeStg()写入的信息。方便应用程序快速判断是否是它需要的格式数据。 |
CreateStreamOnHGlobal() | 内存句柄 HGLOBAL 转换为流对象 |
GetHGlobalFromStream() | 取得CreateStreamOnHGlobal()调用中使用的内存句柄 |
#define _WIN32_WINNT 0x0500
#include <ole2.h>
#include <assert.h>
void SampleCreateDoc()
{
::CoInitialize(NULL); // COM 初始化,如果是MFC程序,可以使用AfxOleInit()替代
HRESULT hr; // 函数执行返回值
IStorage *pStg = NULL; // 根存储接口指针
IStorage *pSub = NULL; // 子存储接口指针
IStream *pStm = NULL; // 流接口指针
// 建立复合文件
hr = ::StgCreateDocfile(
L"c:\\a.stg", // 文件名称
STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, // 打开方式
0, // 保留参数
&pStg); // 取得根存储接口指针
assert( SUCCEEDED(hr) ); // 为了突出重点,简化程序结构,所以使用了断言。在实际的程序中则要使用条件判断和异常处理
// 建立子存储
hr = pStg->CreateStorage(
L"SubStg", // 子存储名称
STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,
0,0,
&pSub); // 取得子存储接口指针
assert( SUCCEEDED(hr) );
hr = pSub->CreateStream( // 建立流
L"Stm", // 流名称
STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,
0,0,
&pStm); // 取得流接口指针
assert( SUCCEEDED(hr) );
hr = pStm->Write( // 向流中写入数据
"Hello", // 数据地址
5, // 字节长度(注意,没有写入字符串结尾的\0)
NULL); // 不需要得到实际写入的字节长度
assert( SUCCEEDED(hr) );
if( pStm ) pStm->Release();// 释放流指针
if( pSub ) pSub->Release();// 释放子存储指针
if( pStg ) pStg->Release();// 释放根存储指针
::CoUninitialize(); // COM 释放,如果使用 AfxOleInit(),则不调用该函数
}
#include <ole2.h>
#include <assert.h>
void SampleCreateDoc()
{
::CoInitialize(NULL); // COM 初始化,如果是MFC程序,可以使用AfxOleInit()替代
HRESULT hr; // 函数执行返回值
IStorage *pStg = NULL; // 根存储接口指针
IStorage *pSub = NULL; // 子存储接口指针
IStream *pStm = NULL; // 流接口指针
// 建立复合文件
hr = ::StgCreateDocfile(
L"c:\\a.stg", // 文件名称
STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, // 打开方式
0, // 保留参数
&pStg); // 取得根存储接口指针
assert( SUCCEEDED(hr) ); // 为了突出重点,简化程序结构,所以使用了断言。在实际的程序中则要使用条件判断和异常处理
// 建立子存储
hr = pStg->CreateStorage(
L"SubStg", // 子存储名称
STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,
0,0,
&pSub); // 取得子存储接口指针
assert( SUCCEEDED(hr) );
hr = pSub->CreateStream( // 建立流
L"Stm", // 流名称
STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,
0,0,
&pStm); // 取得流接口指针
assert( SUCCEEDED(hr) );
hr = pStm->Write( // 向流中写入数据
"Hello", // 数据地址
5, // 字节长度(注意,没有写入字符串结尾的\0)
NULL); // 不需要得到实际写入的字节长度
assert( SUCCEEDED(hr) );
if( pStm ) pStm->Release();// 释放流指针
if( pSub ) pSub->Release();// 释放子存储指针
if( pStg ) pStg->Release();// 释放根存储指针
::CoUninitialize(); // COM 释放,如果使用 AfxOleInit(),则不调用该函数
}
#include <atlconv.h> // ANSI、MBCS、UNICODE 转换
#include <atlbase.h>
#include <atlconv.h>
#include <assert.h>
void SampleEnum()
{
::CoInitialize(NULL); // COM 初始化,如果是MFC程序,可以使用AfxOleInit()替代
LPCTSTR lpFileName = L"c:\\a.stg";
HRESULT hr;
IStorage *pStg = 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;
while( NOERROR == pEnum->Next( 1, &statstg, NULL) )
{
// statstg.type 保存着对象类型 STGTY_STREAM 或 STGTY_STORAGE
// statstg.pwcsName 保存着对象名称
// 。。。 还有时间,长度等很多信息。请查看 MSDN
::CoTaskMemFree( statstg.pwcsName ); // 释放名称所使用的内存(注6)
}
if( pEnum ) pEnum->Release();
if( pStg ) pStg->Release();
::CoUninitialize(); // COM 释放,如果使用 AfxOleInit(),则不调用该函数
}
#include <atlbase.h>
#include <atlconv.h>
#include <assert.h>
void SampleEnum()
{
::CoInitialize(NULL); // COM 初始化,如果是MFC程序,可以使用AfxOleInit()替代
LPCTSTR lpFileName = L"c:\\a.stg";
HRESULT hr;
IStorage *pStg = 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;
while( NOERROR == pEnum->Next( 1, &statstg, NULL) )
{
// statstg.type 保存着对象类型 STGTY_STREAM 或 STGTY_STORAGE
// statstg.pwcsName 保存着对象名称
// 。。。 还有时间,长度等很多信息。请查看 MSDN
::CoTaskMemFree( statstg.pwcsName ); // 释放名称所使用的内存(注6)
}
if( pEnum ) pEnum->Release();
if( pStg ) pStg->Release();
::CoUninitialize(); // COM 释放,如果使用 AfxOleInit(),则不调用该函数
}