DELPHI基础教程
第八章 对象链接与嵌入(一)
Windows 附件组中的书写器是应用 OLE 的实例,使用单击“对象 | 插入”菜单项, 书写器弹出插入对话框,对话框中列出了多个 OLE 服务器程序,如公式编辑工具,绘图工具,报表生成工具。用户双击鼠标左键,可激活一个 OLE 服务器。在 OLE 服务器中可编辑 OLE 对象,当用户返回到书写器中时,在书写器文档中将出现 OLE 对象。 Delphi 支持 OLE 技术, Delphi1.0 可以创建 OLE 应用程序, Delphi2.0 可创建 OLE 自动化服务器和控制器程序。本章通过例程介绍对象链接与嵌入的基本概念, Delphi 创建 OLE 对象的方法, OLE 自动化的概念以及如何开发 OLE 自动化服务器和控制器。 8.1 OLE 简介 8.1.1 OLE1.0 和 OLE2.0 迄今为止,有两种版本的 OLE : OLE1.0 和 OLE2.0 。当用户在 OLE1.0 服务器中激活 OLE 对象,服务器程序在前台打开自己的窗体,并获得焦点。 OLE 窗体失去焦点,存在于单独的窗体之中。 OLE2.0 服务器采用“本地” (in place) 激活方式。本地激活意味着服务器菜单与应用程序菜单要进行融合,服务器的状态条更换应用程序状态条,服务器的工具条更换应用程序工具条。 OLE 对象在应用程序窗体中进行编辑,但所有过程均由服务器处理。 创建 OLE 对象的服务器决定了 OLE 的激活方式。如果一个 OLE1.0 的对象在 OLE2.0 编译的应用程序中打开,它将采用 OLE1.0 的方式。 8.1.2 链接与嵌入 链接对象的数据保存在 OLE 服务器创建的文件中,嵌入对象的数据保存在 OLE 应用程序中。 链接对象必须以文件形式保存,只有对 OLE 服务器已经创建好的 OLE 对象, 才能进行 OLE 链接,链接的 OLE 对象文件可被 OLE 应用程序或其它程序进行修改, OLE 服务器和其它 OLE 应用程序也可以访问和修改 OLE 对象。对象数据保存在某一处,但可以被多个应用程序访问。 Delphi 应用程序可以得到 OLE 对象文件中的最新数据。当 OLE 对象数据被应用程序修改时,这些变化将在所有包含该对象的其它应用程序中体现。 嵌入对象保存在 OLE 应用程序中,其它应用程序不能访问该对象。只有在 OLE 应用程序中激活 OLE 对象才能对其进行编辑。嵌入的 OLE 对象不需要保存在文件中,所有数据都在应用程序中,这就确保了 OLE 数据不会被偶然地删除或修改。不足之处是应用程序的规模因为保存了 OLE 数据而增大了 。 如果用户想保存对嵌入对象的修改,可以把OLE数据存入文件中,本章第3 节将详细讨论这个问题。 表 8.1 使用链接或嵌入的原则。 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 何时使用链接 何时使用嵌入 ─────────────────────────────── 想要对源对象进行修改及将 对源对象进行修改,并将这 这些修改反映到其他与源对 些修改反映在一个特定的应 象链接的应用程序或文本中 用程序或文本中 源对象可能被多个 OLE 应 源对象不可能被一个 OLE 应 用程序应用程序频繁修改 用程序频繁修改 源对象的文件不会被频繁移 源对象的文件可能被频繁移 动,且不会被删除 动,且不会被删除 对象很大,一般通过网络或 对象很小,或对象很大却无法 电子邮件进行分配 通过网络或电子邮件进行分配 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.1.3 设计状态 OLE 对象的创建 在 Delphi 中,可分别在设计状态或运行状态创建 OLE 对象,表 8.2 说明了两种状态创建对象的差别。 表 8.2 设计、运行状态 OLE 对象的创建 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 设计状态 OLE 对象的创建 运行状态 OLE 对象的创建 ────────────────────────────────────── 对象保存在运行文件中,增加了所需 对象保存在一个文件中或只在运行时 编译的程序的规模 才有,减小了编译程序的规模 开发者需在设计时访问 OLE 服务器 开发者不需要在设计时访问 OLE 服务器 运行时 OLE 对象已经创建,减小了 运行时 OLE 对象已经创建,增加了运行 运行时间 时间 OLE 对象在设计运行时间可行性编辑 OLE 对象只能在运行时编辑 应用程序的 OLE 对象数目在设计时已 应用程序可以在运行时创建新的 OLE 对 经确立 象 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 在设计状态, OLE 服务器不能被本地激活,只能在自己的窗体内激活。但在运行状态, 只要 OLE 服务器支持本地激活,就可以使用这种方式。 8.1.4 OLE 类、文件、项目 OLE 类决定创建 OLE 对象的服务器。有些应用程序需要创建多种类型的 OLE 对象,例如应用程序同时链接或嵌入公式、图片等。 OLE 类也决定 OLE 对象所包含的数据类型,链接或嵌入对象均要定义 OLE 类。 OLE 文件是包含 OLE 对象数据的源文件。链接对象必须使用对象文件,因为链接对象在文件中保存。如果应用程序从已存在的源文件中创建嵌入对象,也要使用 OLE 文件。例如,如果链接到 QuattiPro 笔记本的 OLE 对象 TUTOR.WBI 存储在 D:\DFFICE\QPW 目录下,则 OLE 文件就是 D:\DFFICE\QPW\TUTOR.WBI 。值得注意的是 OLE 文件只能为链接对象所定义,而对于嵌入对象,只需定义 OLE 类。 OLE 项目是代表链接或嵌入数据的 OLE 文件中的一部分。当应用程序希望 OLE 对象包含比 OLE 文件小的数据块时,则必须使用 OLE 项目。 例如,在 QuattiPro 笔记本中, OLE 对象链接了 GasCosts 的 B4 到 B5 范围的网格, OLE 项目是 $GasCosts;$B$4.$B$5 。 8.2 设计状态 OLE 对象的创建 Dephi 可以在设计状态和运行状态中创建 OLE 对象。本节介绍设计状态 OLE 对象的创建。 8.2.1 TOLEContainer 部件 要创建 OLE 对象,需在窗体中加入 OLE 包容器部件。 应用程序部件包含链接或嵌入的对象。用该部件可显示在 OLE 服务器编辑的数据。部件的 ObjClass,ObjDoc,ObjItem 属性分别定义 OLE 类、文件、项目。要定义 OLE 对象是否本地激活,使用 InPlaceActive 属性。如果 OLE 对象可以本地激活, OLE 服务器菜单将与 OLE 应用程序的菜单进行融合, GroupIndex 属性的值将决定菜单融合情况。 8.2.2 OLE 对象创建的步骤: 1. 在窗体中增加 OLE 包容器部件; 2. 在 Object inspector 中单击 ObjClass 或 ObjDoc 属性的省略按钮,将出现插入对象对话框; 3. 如果要插入的 OLE 对象已存储在文件中,选择“ Creat From File ”,而后定义该对象的文件名和路径名。如果是链接对象,则选择链接检查框。 如果是嵌入对象,选择“ Creat new ”,并在对象类型列表框中选择 OLE 对象; 4. 选择 OK 按钮; 如果是创建新对象, OLE 服务器将激活,则可对 OLE 对象进行编辑,完成编辑后关闭 OLE 服务器。典型的例子是单击服务器中的“ File ”或“ File|Update ”菜单。 5. 此时 ObjClass 属性中包含了相应的值,如果 OLE 对象从已存在的文件中创建或插入一 个链接对象, ObjDoc 属性包含了 OLE 文件。 在设计对象状态时也可以粘贴 OLE 对象,其步骤如下: 1. 激活服务器应用程序,选择 OLE 包容器部件; 2. 在服务器中,将数据或对象拷贝到剪切板; 3. 进入 Delphi 集成开发环境,选择 OLE 包容器部件; 4. 在 Object inspector 窗体中选择 ObjItem 属性的省略 ( … ) 按钮; 5. 在列表中选择 OLE 对象; 6. 选择“ Paste" 创建一个嵌入对象或选择 "Pastelink" 创建链接对象; 7. 选择 OK 。 OLE 包容器部件在此时初始化。如果粘贴一个嵌入对象, ObjClass 属性将包含适当的值。如果粘贴一链接对象, ObjClass,ObjDoc,ObjItem 属性将全部定义。 OLE 应用程序部件包含代表 OLE 对象的图片。 如果 OLE 服务器程序支持 OLE 对象的拖放功能,则在设计状态从服务器中拖动对象至应用程序,应用程序将创建链接对象,具体步骤: 1. 激活服务器,并 Delphi 集成开放环境中选择要链接的对象; 2. 按隹鼠标左键拖动 OLE 对象至设计状态的窗体; 3. 松开鼠键释放 OLE 对象。 窗体将创建 OLE 应用程序并进行初始化。 8.3 OLE 应用程序的开发 Delphi 可以在设计状态和运行状态创建 OLE 对象,上一节介绍的是在设计状态如何创建 OLE 对象,这一节将通过例程介绍如何在运行状态创建 OLE 对象、粘贴对象、拖动对象,以及 OLE 对象的文件操作。我们开发的 OLE.dpr 是一个 OLE 应用程序的实例 8.3.1 OLE 应用程序界面开发 OLE.dpr 采用了多文档界面,父窗体有菜单,工具条,状态条,子窗体有一个 OLE 包容器部件,下面分别加以介绍。 8.3.1.1 OLE 应用程序的菜单 OLE 应用程序的菜单与其它应用程序的主菜单大体一致,如果应用程序中有支持本地激活的 OLE 2.0 对象,则要进行菜单融合。查阅 OLE 服务器的资料可知道服务器是否支持本地激活。 OLE 应用程序菜单的 GroupIndex 属性决定融合菜单的位置,即融合菜单是更换主菜单,还是插入至应用程序的主菜单中。 OLE 服务器,将融合三组菜单 :Edit,View,Help ,每组菜单分配了唯一的组索引值。在 OLE 应用程序中任何索引值为 1,3,5 的菜单组在菜单融合时被 OLE 服务器中具有相应索引值的菜 单更换。在本例程中,编辑菜单项在菜单融合时被服务器的 "Edit" 替换。如图 8.3 。 要想保存应用程序中的菜单,分配有异于 1,3,5 的索引值。 表 8.3 融合后的菜单 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 菜单 索引值 功能描述 来源 (OLE 激活时 ) ──────────────────────────────── 文件 0 使用文件和退出程序 OLE 应用程序 Edit 1 编辑 OLE 对象 OLE 服务器 对象 2 操作未激活的 OLE 对象 OLE 应用程序 View 3 修改 OLE 对象的观测方式 OLE 服务器 窗体 4 操纵窗体 OLE 应用程序 Help 5 访问服务器在线帮助 OLE 服务器 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.3.1.2 OLE 工具条和状态条 当 OLE 对象被本地激活时, OLE 服务器将试图用自己的工具条和状态条替换 OLE 应用程序的。如果应用程序想要本地激活, 就应该在应用程序中编写相应的代码让服务器使用工具条和状态条。要做到这点,必须: ● 设置工具条和状态条 ● 在应用程序中加入状态条 通过修改面板部件的属性创建工具条和状态条。 当 OLE 对象被本地激活时,面板或其他对齐控制将与 OLE 服务器程序进行协调。 这意味 OLE 服务器可以替换 OLE 应用程序窗体中任何对齐控制,但锁定的控制不能被替换。例如, 如果面板的 align 属性是 alTop,alleft,alBottom,alIngh 时,控制未锁定, OLE 服务器可以替换。要使应用程序的工具条、状态条不被替换,可将 locked 属性设置成真值。 当 OLE 对象被激活, OLE 服务器在状态条中显示有关信息时, OLE 应用程序部件的 OnStatusLineEvent 事件发生,一个文本字符会将从 OLE 服务器传至该事件句柄。 OnStatusLineEvent 事件句柄的 MSG 参数接受文本字符。 以下代码用以状态条接收 OLE 服务器的信息: procedure TOLEObjectForm.OleContainerStatusLineEvent(Sender: TObject; Msg: String); begin OLEFrameForm.StatusBarPanel.Caption := Msg end; 8.3.2 插入 OLE 对象 运行状态时进行对象链接与插入也要用到插入对话框, Delphi 中没有插入对话框部件,但可调用 InsertOLEObjectDlg 函数来显示对话框。 8.3.2.1 InsertOLEObjectDlg 函数声明如下: function InsertOleObjectDlg(Form: TForm; HelpContext: THelpContext; var PInitInfo: Pointer): Boolean; 其中参数 Form 是拥有插入对话框的窗体,一般将拥有 OLE 包容器部件的窗体名字传给 Form. 参数 Helplontext 为插入对象对话框定义在线帮助,如果应用程序没有在线帮助, HelpContext 的值为零,对话框中将不出现帮助按钮。 参数 PInitInfo 是一个无类型指针,该指针指向一个包含初始化 OLE 部件信息的内部数据结构。 InsertOLEObjectDlg 修改这个指针以指向一个有效的数据结构,该结构包含了对话框列表中被选择的 OLE 对象初始化信息。当该指针被使用后,应调用 ReleaseOLEInitInfo 过程释放初始化信息所占用的内存。 当用户选择 OK 按钮关闭插入对象对话框, InsertOLEObjectDlg 返回真值,并把 PInitInfo 指向包含 OLE 对象的初始化信息的数据结构。 8.3.2.2 初始化 OLE 包容器部件 为了使 OLE 包容器部件包含 OLE 对象,必须对部件进行初始化。 初始化主要是定义部件的 OLE 类。如果定义了 OLE 文件和 OLE 项目,初始化完成后, OLE 应用程序部件将包含 OLE 对象。 调用 InsertOLEObjetDlg 函数可在其参数 PInitInfo 获得关于 OLE 对象初始化的信息时,把它传递给 OLE 包容器部件的 PInitInfo 属性, OLE 包容部件的 ObjClass,ObjDoc,ObjItem 属性将被自动定义。 初始化完成后, OLE 对象被击活。 OLE 服务器将获得控制,用户可通过 OLE 服务器对 OLE 对象进行编辑。当程序冻结 OLE 对象, OLE 包容器部件将包含一幅图像或位图代表 OLE 对象。定义 OLE 包容器部件的 AutoActive 属性可重新激活 OLE 对象,缺省情况下,双击 OLE 包容器部件可击活 OLE 对象。 例程中初始 OLE 对象的代码如下: procedure TOLEObjectForm.InitializeOLEObject(Info: Pointer); begin OLEContainer.PInitInfo := Info; ReleaseOLEInitInfo(Info) end; 该过程先将初始化指针传给 OLE 包容器部件的 PInitInfo 属性,而后释放其内存空间。 当用户单击例程中的“编辑 | 插入”菜单项,将弹出插入对象对话框,选择对象类型后, OLE 对象被激活,该过程的代码如下: procedure TOLEObjectForm.InsertObject1Click(Sender: TObject); var Info: Pointer; begin if InsertOLEObjectDlg(OLEFrameForm, 0, Info) then InitializeOLEObject(Info); end; 8.3.3 冻结 OLE 对象 如果 OLE 对象是 OLE 1.0 服务器创建,对象将在 OLE 服务器中被击活,焦点和控制移到 OLE 服务器中。要冻结一个由 OLE 1.0 创建的对象选择 "File | Exit" 菜单项。 如果 OLE 2.0 服务器支持本地激活,激活 OLE 对象后 OLE 服务器将进行菜单融合,并转换工具条和状态条。要冻结对象,只需在应用程序窗体中异于 OLE 包容器部件的任何地方单击鼠 标键即可。 另一种冻结对象的方法是把 OLE 包容器部件的 Active 属性设置成假值。在例程中,“对象 | 冻结”菜单项实现冻结功能。代码如下: procedure TOLEObjectForm.Deactivate1Click(Sender: TObject); begin OLEContainer.Active := False end; 8.3.4 粘贴 OLE 对象 一些 OLE 服务器允许用户把 OLE 对象复制到剪贴板,如果一个 OLE 对象复制到剪贴板上, OLE 应用程序可通过初始化 OLE 包容器部件来粘贴 OLE 对象。 8.3.4.1 粘贴对话框 把 OLE 对象粘贴到 OLE 包容器部件,要使用粘贴对话框, Delphi 中没有粘贴对话框部件,但可用 PasteSpecialDlg 函数显示粘贴对话框。 PasteSpecialDlg 函数声明如下: function PasteSpecialDlg(Form :TForm;Const First:arrang; HelpConcert: THelpCOntext;var Forrmat : Word; var Hardle : THanlle var PInitInfo : Point ) : Boolean; PasteSpecialDlg 参数定义如下: 参数 Form 是拥有粘贴对话框的窗体,应把包含 OLE 包容器部件的窗体名字传递给 Form 。 参数 Format 是注册对象格式的数组,每组格式是 BOLEFormat 类型的数组成员。例如应用程序可注册两种对象格式。为嵌入对象注册 FEmbedClipFmt ,为链接对象注册 FlinkClipFmt 。 BOLEFormat 声明如下: BOLEFormat : Record fmtID : Word; fmtName : array[0..31] of char; fmtResultName : array[0..31] of char; fmtMediun : BOleMedium; fmIsLInkble : Bool; end; fmtID 是对象的剪贴板格式 ID 号, fmtID 可以是标准的剪贴板格式: CF_TEXT,CF_BIFMAP 。使用 OLE 对象时, 需注册新的剪贴板格式来处理 OLE 对象。 Windows 的 API 中 的 RegisterClipbordFormat 函数注册格式。 fmtName 表示是对象的名字,用以定义出现在粘贴对话框中列表框 内的对象名称。在例程中,把“% S ”匹配给 fmtName , OLE 服务器自动地把格式化的名字代替“% S ”参数。例如,如果 OLE 服务器是画笔,在程序运行时“ Paintbrush Picture Object ”将代替“% S ”。 fmtResultName ,定义出现在粘贴对话框中结果检查框内的名字。在例程中, 把“% S ”传给了 fmtResultName 。 OLE 服务器自动地把格式结果名称代替“% S ”参数。例如,如果 OLE 服务器是画笔,程序运行时“ Paintbrush Picture ”将代替“% S ”。 fmtMedium 是 BOLEMedium 类型,是 Windows 决定对象格式的数据类型。例如, OLE 联 接对象的格式是 BOLE_MED_STREAM 。 OLE 嵌入对象的格式是 BOLE_MED_STORAGE 。 BOLEMedium 函数可计算出需要的 BOLEMedium 类型。 fmtIsLinkale 决定对象格式是否可联连。联连对象的 fmtIsLinkable 为真值。嵌入对象的 fmtIsLinkable 为假值。 参数 HelpContext 为粘贴对话框定义在线帮助。如果应用程序没有在线帮助, HelpContext 的值为零,对话框中将不出现帮助按钮。 参数 Form 用以定义剪粘板上的格式,是由 PasteSpecialDlg 函数进行修改。因为使用粘贴对话框时,应用程序并不知道剪贴板的格式。因而用 Format 来处理剪贴板的数据。在本章例程中。 PasteSpecialDlg 函数把 format 变量修改成 FEmbedClipFmt 或 FLinkClipFmt 格式,这两种格式是在主窗体的 OnCreate 事件中定义的。如果剪贴板上的数据不是 OLE 对象, Format 将被修改成其它类型的格式,如 CF_TEXT 等。 参数 Landle 定义剪贴板上的数据句柄。由 PasteSpecialDlg 函数进行修改。 当剪贴板的数据类型不是 OLE 对象时,需用 Handle 参数访问剪贴板数据。 Handle 是句柄类型。 参数 PInitInfo 是一个指向 OLE 对象初始化结构的指针。前面在讲述初始化 OLE 应用程序部件时也用到了这种指针。 PasteSpecialDlg 函数将修改 PInitInfo 指针以使其指向一个有效的数据结构。该结构包括了粘贴对话框中被选中的 OLE 对象的初始化信息。 下面介绍粘贴对话框中的部件。 ● 将剪贴板上的数据插入 OLE 应用程序,以实现对象嵌入,须选择 "Paste" ; ● 在 OLE 服务器资源文件与 OLE 应用程序之间建立联连,以实现对象联连,须选择 : "Paste Line ; ● 要将闻连与嵌入的对象显示成图标,选择 "Display As Icon" 。若这个检查框被选中,改变图标 ("Chang Icon") 按钮将显示通过这个按钮可改变 OLE 对象的缺省图标或标签。 ● 如果数据不是注册的格式, "Paste","Paste link" 选择键将变灰。 用户无法从剪贴板上粘贴数据。在本章例程中,剪贴板上的数据只能是 FEmbedClipFmt( 嵌入对象 ) 和 FlinkClipFmt( 链接对象 ) 。 ● 用户在列表框中选择数据类型。有时数据被解释成多种类型。例如在包含 OLE 服务器功能的字处理器中把文本复制到剪贴板中。应用程序可以以文本和 OLE 对象两种方式粘贴对象。列表框中出现的选择项由 OLE 服务器决定。 用户在粘贴对话框中选择 OK 按钮, PasteSpecialDlg 返回真值,关于 OLE 应用程序的初始化信息贮存在 PInitInfo 所指向的结构中。 8.3.4.2 在剪贴板中使用 OLE 对象 要把 OLE 对象粘贴到 OLE 应用程序中,必须用 Windows 的 RegisterClipboardFormat 函数为链连对象、嵌入对象注册两种新的剪贴板格式。这些格式将在 BOLEFormat 记录的 fmtIdt 域中被用到。 本章例程中, 程序在 OnCreate 事件中注册 OLE 对象的剪贴板格式,以下代码是主窗体的 OnCreate 事件: procedure TOLEFrameForm.FormCreate(Sender: TObject); begin FEmbedClipFmt := RegisterClipboardFormat('Embedded Object'); FLinkClipFmt := RegisterClipboardFormat('Link Source'); Fmts[0].fmtId := FEmbedClipFmt; Fmts[0].fmtMedium := BOLEMediumCalc(FEmbedClipFmt); Fmts[0].fmtIsLinkable := False; StrPCopy(Fmts[0].fmtName, '%s'); StrPCopy(Fmts[0].fmtResultName, '%s'); Fmts[1].fmtId := FLinkClipFmt; Fmts[1].fmtMedium := BOLEMediumCalc(FLinkClipFmt); Fmts[1].fmtIsLinkable := True; StrPCopy(Fmts[1].fmtName, '%s'); StrPCopy(Fmts[1].fmtResultName, '%s'); RegisterFormAsOleDropTarget(Self, Fmts) end; 程序传给 RegistClipBroardFormat 函数一个描述格式的参数,它返回一个 Word 类型的值。该值能唯一的辨识新注册的格式。 FEmbdeClipFmt,FlinkClipFmt 是 TOLEFormat 类的私有数据成员。 声明如下: TYPE TOLEForaneForm = Class(TForm) … private FEmbedClipFmt: Word; FLinkClipFmt: Word; function CreateChild: TOLEObjectForm; public Fmts: array[0..1] of BOleFormat; end; 在注册剪贴板格式后, 还必须定义 OLE 格式才能进行对象粘贴。 每种格式定义在 BOLEFormat 记录中。 程序中可能注册标准剪贴板格式并用这种格式进行粘贴。例如:注册文本作为粘贴格式,将 BOLEFormat 记录为 fmtId 域定义为 CF_TEXT , fmt Medium 域定义为 BOLE_MED_HGLOBOL 。 BOLEMediumCalc 函数可以根据定义的剪贴板格式计算出 fmtMedium 值。在本章例程中,程序注册了两种格式,一种是链接 OLE 对象的格式,另一种是嵌入 OLE 对象的格式。 BOLEFormat 类型定义在 BOLEDefs 单元中, BOLEMediumCalc 函数定义在 ToCtrl 单元。因此主窗中的 interface 部分应加入这两个单元。 interface use … ,BOLEDefs,ToCtrl, 在粘贴 OLE 对象前,应用程序必须知道在剪贴板中是否有 OLE 对象。 PasteSpecialEnabled 函数可判断粘贴对话框是否有效。如果剪贴板上有 Fmts 定义的任何一种格式, PasteSpecialEnable 将返回真值, 粘贴对话框才能成功地调用。反之调用粘贴对话框将不发生任何事件。 以下代码实现“编辑 | 粘贴”菜单项的功能: procedure TOLEObjectForm.PasteSpecial1Click(Sender: TObject); var ClipFmt: Word; DataHand: THandle; Info: Pointer; begin if PasteSpecialEnabled(Self, OLEFrameForm.Fmts) then if PasteSpecialDlg(Self, OLEFrameForm.Fmts, 0, ClipFmt, DataHand, Info) then InitializeOLEObject(Info) end; 只有在粘贴对话框有效时“编辑 | 粘贴”菜单才有效,以下代码实现此功能: procedure TOLEObjectForm.Edit1Click(Sender: TObject); begin PasteSpecial1.Enabled := PasteSpecialEnabled(Self, OLEFrameForm.Fmts) end; 8.3.5 释放 OLE 对象 从 OLE 服务器拖动 OLE 对象并将其放在 OLE 应用程序是一种方便的对象链接与嵌入的方法。通过拖放操作,用户不需要使用插入对话框或粘贴对话框来定义 OLE 对象。而只需用鼠标键从 OLE 服务器中“抓”住 OLE 对象,拖至 OLE 应用程序,松开鼠标键,从而实现 OLE 对象的插入。 8.3.5.1 注册 OLE 释放目标窗体 为了接收一个释放的 OLE 对象,必须有一个窗体在 Windows 中注册成 OLE 释放目标,用 RegisterFormASOLEDropTarget 函数可实现此功能。 RegisterFormASOLEDropTarger(Form : TFrom;Const Fmts: array of BOlefrom). 其中 Form 是 OLE 对象的释放目标窗体,在本章例程中,将子窗体传递给 Form 参数。 Fmts 是对象格式的数组。它是 BOLEFormat 类型的数组。 所有要释放的数据必须用 Fmts 数组中相应 BOLEFormat 元素注册。 在本章例程中,注册的 Fmts 数组与主窗体 OnCreate 事件 声明的数组相同, 即:联接对象格式和嵌入对象格式。如果想接收更多类型的释放数据,就必须在 Fmts 数组中加入其它元素。例如应用程序要接收释放的文本, Fmts 需加第三个元素, 其 fmtId 域为 CF_TEXT,BOLEMedium 域为 BOLE_MED_HGLOBL. 拖放过程中不需要用 BOLEFormat 的 fmtName,fmtResultName 域,如果程序只进行拖放操作而不进行对象粘贴,可以不初始化两个域。 在主窗体的 OnCreate 事件中可调用 RegisterFormAsOLEDropTorget 。 procedure TOLEFrameForm,FormCreate(Sender : TObject); begin … Register FormASOleDropTarget(Self,Fmts) end; |