程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> Delphi 對象鏈接與嵌入(1)

Delphi 對象鏈接與嵌入(1)

編輯:Delphi

對象鏈接和嵌入(Object Linking and Embeding)是一組服務功能,它提供了一種用源於不同應用程序的信息創建復合文檔的強有力方法。 對象可以是幾乎所有的信息類型,如文字、位圖、矢量圖形,甚至於聲音注解和錄像剪輯等。

  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類的私有數據成員。 聲明如下:













  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved