数据对象是所有Shell数据传输的要点。数据对象主要用作数据容器,用以存储要传输的数据。
然而,传输目标也可以与数据对象通信,以方便处理像优化的移动这样特定类型的Shell数据传输。本文提供对Shell数据对象如何工作、传输源如何创建数据对象、传输目标如何处理数据对象的一般讨论。关于如何使用数据对象传输各种不同类型Shell数据的详细讨论,见
Handling Shell Data Transfer Scenarios
。
1.数据对象如何工作
数据对象是由数据源创建,用以传输数据到传输目标的COM对象。数据对象通常携带多项数据,原因是:
-
虽然数据对象几乎可以传输任何类型的数据,但是传输源通常不知道传输目标可以接受什么类型的数据。比如说,数据可能是一个格式化的文本文档的一部分,然而传输目标可能能够处理复杂的格式信息,也可能只能接受ANSI文本。因此,数据对象通常含有多种不同格式的相同数据。这样传输目标就可以取出它所能处理格式的数据。
-
数据对象还可以携带不属于源数据的辅助数据项。这些数据项通常用于为数据传输操作提供额外信息。比如说,Shell使用辅助数据项指示文件是被复制还是被移动。
1.1 剪贴板格式
数据对象中的每个数据项都有一个相关的格式,通常称作剪贴板格式。Winuser.h中声明了多种对应通常使用的数据类型的标准剪贴板格式。剪贴板格式是个整数值,但通常用其形式为CF_XXX的等价名字来表示。比如说,ANSI文本的剪贴板格式是CF_TEXT。
应用程序可以通过定义私有格式来扩展可用的剪贴板格式。要定义私有格式,调用
RegisterClipboardFormat
,传入标识格式的字符串。函数返回一个表示剪贴板格式的无符号整数值,可以像标准剪贴板格式那样使用这个值。但使用这个格式之前,传输源和目标都必须注册这个格式。但用于传输Shell数据的剪贴板格式CF_HDROP是个例外(不需要注册),它也被定义为私有格式。关于可用剪贴板格式的描述,见
Shell Clipboard Formats
。
虽然有一些例外,但通常来说,对于所支持的每种剪贴板格式,数据对象只包含一个数据项。这种格式与数据项的一对一关系,使得格式值可以用于标识相关数据项。实际上,在讨论数据对象内容的时候,通常用数据的格式来指代数据本身。比如说,在讨论数据对象的ANSI文本数据项的时候,通常会说“取出CF_TEXT格式……”。
放置目标收到数据对象指针时,会枚举可用的格式以确定什么类型的数据可用,然后请求一种或者多种可用的格式,取出数据。从数据对象中取出数据的方式随着格式的不同而不同,相关详细讨论见本文的
How a Target Handles a Data Object
节。
对于简单的剪贴板数据传输,数据放置在全局存储对象中。对象的地址及其格式被放置在剪贴板中。剪贴板格式告诉放置目标可以从相关地址处取得什么类型的数据。虽然简单的剪贴板数据传输很容易实现,但是:
-
数据对象为数据传输提供了更灵活的方式
-
数据对象更适合传输大量数据
-
拖放操作必须使用数据对象来传输数据
基于上述理由,所有Shell数据传输都使用数据对象。数据对象不直接使用剪贴板格式,而是由一种通用的剪贴板格式,即
FORMATETC
结构体标识。
1.2 FORMATETC结构体
FORMATETC
结构体是剪贴板格式的扩展版本。为了能用于Shell数据传输,它具有下列特征:
-
数据项还是由
cfFormat
成员中的剪贴板格式值标识。
-
数据传输不仅仅限于全局存储对象。
tymed
成员用以指示包含在
STGMEDIUM
结构体中的数据所使用的传输机制,它的值是
TYMED_XXX
之一。
-
Shell使用
CFSTR_FILECONTENTS
格式及其
lIndex
成员来支持包含相同格式的多个数据项。关于如何使用这种格式的详细讨论,见
Using the CFSTR_FILECONTENTS Format to Extract Data from a File
。
-
dwAspect
成员通常被设置为
DVASPECT_CONTENT
。然而,ShlObj.h中定义了可用于Shell数据传输的三种值:
DVASPECT_COPY 用以指示格式代表数据的副本
DVASPECT_LINK 用以指示格式代表数据的快捷方式
DVASPECT_SHORTNAME 与CF_HDROP格式一起使用,要求缩短文件路径后的文件名到8.3格式。
-
Shell数据传输没有使用
ptd
成员,它通常被设置为NULL。
1.3 STGMEDIUM结构体
STGMEDIUM
结构体提供对被传输数据的访问。Shell数据支持三种传输机制:
-
全局存储对象
-
IStream
接口
-
IStorage
接口
STGMEDIUM
结构体的
tymed
成员值
TYMED_XXX
表示数据传输机制。结构体的第二个成员是一个指针,传输目标用它取出数据。指针可以是多种类型中的一种,这决定于
tymed
成员值。下表总结了用于Shell数据传输的三种
tymed
成员值以及它们相关的
STGMEDIUM
成员名字:
tymed 值 |
成员名 |
描述 |
---|---|---|
TYMED_HGLOBAL |
hGlobal |
指向全局存储对象的指针。这种指针类型通常用于传输少量数据。比如说,Shell使用全局存储对象传输像文件名或者URL这样较短的字符串。 |
TYMED_ISTREAM |
pstm |
指向 IStream 接口的指针。这种指针类型对于大多数Shell数据传输是最佳选择,因为与TYMED_HGLOBAL相比,它使用相对少的内存。而且ÿ |