關於動態數據交換

Windows 提供數種方法,可在應用程式之間傳輸數據。 其中一種方法是使用動態數據交換 (DDE) 通訊協定。 DDE 通訊協定是一組訊息和指導方針。 它會在共用資料的應用程式之間傳送訊息,並使用共用記憶體在應用程式之間交換資料。 應用程式可以使用 DDE 通訊協議進行一次性數據傳輸,以及持續交換,其中應用程式會在有新數據可用時將更新傳送至彼此。

Windows 也支援動態數據交換管理連結庫 (DDEML)。 DDEML 是動態連結庫 (DLL),應用程式可用來共享數據。 DDEML 提供函式和訊息,可簡化將 DDE 功能新增至應用程式的工作。 應用程式會使用 DDEML 函式來管理 DDE 交談,而不是直接傳送、張貼及處理 DDE 訊息。 (DDE 交談是用戶端與伺服器應用程式之間的互動。

DDEML 也提供一個功能來管理 DDE 應用程式共用的字串和數據。 DDE 應用程式不會使用 Atom 和指標來共用記憶體物件,而是建立和交換字串句柄,以識別字串,以及識別記憶體對象的數據句柄。 DDEML 也可讓伺服器應用程式註冊它支援的服務名稱。 這些名稱會廣播至系統中的其他應用程式,其可以使用名稱來連線到伺服器。 此外,DDEML 會強制 DDE 通訊協定以一致的方式實作 DDE 通訊協定,以確保 DDE 應用程式之間的相容性。

使用訊息型 DDE 通訊協定的現有應用程式與使用 DDEML 的應用程式完全相容。 也就是說,使用訊息型 DDE 的應用程式可以建立交談,並使用 DDEML 的應用程式執行交易。 由於 DDEML 的許多優點,新的應用程式應該使用它,而不是 DDE 訊息。 若要使用 DDEML 的 API 元素,您必須在來源檔案中包含 DDEML 頭檔、連結至 DDEML 連結庫,並確定 DDEML 動態連結庫位於系統的搜尋路徑中。

本節將討論下列主題。

動態資料交換通訊協定

因為 Windows 有訊息架構,因此傳遞訊息是自動在應用程式之間傳送資訊的最適當方法。 不過,訊息只包含傳遞數據的兩個參數 (wParamlParam)。 因此,當應用程式之間傳遞一些以上的資訊時,這些參數必須間接參考其他數據片段。 DDE 通訊協定會定義應用程式應該 如何使用 wParamlParam 參數,透過全域 Atom 和共用記憶體句柄傳遞較大的數據片段。 DDE 通訊協定有配置和刪除全域 Atom 和共用記憶體物件的特定規則。

全域 Atom 是字元字串的參考。 在 DDE 通訊協定中,Atom 會識別交換數據的應用程式、所交換數據的性質,以及數據項本身。 如需 Atom 的詳細資訊,請參閱 關於 Atoms

用於 Windows Dynamic Data Exchange

DDE 最適合不需要進行中用戶互動的數據交換。 應用程式通常會提供方法,讓使用者建立應用程式交換數據之間的連結。 不過,一旦建立該連結,應用程式就會交換數據,而不需要進一步的用戶參與。

DDE 可用來實作廣泛的應用程式功能,例如:

  • 連結到實時數據,例如股市更新、科學儀器或過程控制。
  • 建立複合檔,例如包含圖形應用程式所產生的圖表的文字處理檔。 使用 DDE 時,圖表會在源數據變更時變更,而檔的其餘部分則保持不變。
  • 在應用程式之間執行數據查詢,例如電子錶格,查詢逾期帳戶的資料庫。

用戶觀點的動態數據交換

下列範例說明兩個 DDE 應用程式如何合作,如用戶的觀點所見。

電子表格使用者想要使用 Microsoft Excel 來追蹤紐約證券交易所特定股票的價格。 使用者有一個名為 Quote 的應用程式,接著可以存取 NYSE 數據。 Excel 與 Quote 之間的 DDE 交談會如下所示:

  • 用戶會藉由提供應用程式的名稱(Quote)來起始交談,該名稱會提供數據和感興趣的特定主題(NYSE)。 產生的 DDE 交談是用來要求特定股票的報價。
  • Excel 會將應用程式和主題名稱廣播至目前在系統中執行的所有 DDE 應用程式。 報價會回應,建立與 Excel 關於 NYSE 主題的對話。
  • 然後,用戶可以在儲存格中建立電子表格公式,要求每當特定股票報價變更時,就會自動更新電子錶格。 例如,使用者只要指定下列 Excel 公式,即可在 ZAXX 股票的銷售價格發生變更時要求自動更新: ='Quote'|'NYSE'!ZAXX
  • 用戶可以隨時終止 ZAXX 股票報價的自動更新。 另外建立的其他數據連結(如其他股票報價)仍會在相同的紐約證交所對話下保持活躍。
  • 使用者也可以終止 NYSE 主題上 Excel 與 Quote 之間的整個對話,如此一來,就該主題無法建立任何特定數據連結,而不需要起始新的交談。

動態數據交換概念

下列各節說明瞭解動態數據交換的重要概念和術語。

用戶端、伺服器和交談

參與 DDE 的兩個應用程式據說會參與 DDE 對話。 起始交談的應用程式是 DDE 用戶端應用程式;回應用戶端的應用程式是 DDE 伺服器應用程式。 應用程式可以同時進行數個交談,做為某些中的用戶端,以及做為其他伺服器。

DDE 交談會在兩個視窗之間進行,每個參與的應用程式各一個。 視窗可能是應用程式的主要視窗;與特定文件相關聯的視窗,如同在多文檔介面 (MDI) 應用程式中;或隱藏的視窗,其唯一目的是處理 DDE 訊息。

由於 DDE 交談是由交談中視窗的句柄配對所識別,因此不應該讓視窗與另一個視窗進行一個以上的交談。 用戶端應用程式或伺服器應用程式都必須為每個與特定伺服器或用戶端應用程式的交談提供不同的視窗。

應用程式可以藉由為每個交談建立隱藏的窗口,確保一對用戶端和伺服器視窗永遠不會涉及多個交談。 此視窗的唯一目的是處理 DDE 訊息。

應用程式、主題和項目名稱

DDE 通訊協定會識別客戶端與伺服器之間傳遞的數據單位,其中包含應用程式、主題和專案名稱的三層階層。

每個 DDE 交談都是由應用程式名稱和主題唯一定義。 在 DDE 交談的開頭,用戶端和伺服器會決定應用程式名稱和主題。 應用程式名稱通常是伺服器應用程式的名稱。 例如,當 Excel 做為交談中的伺服器時,應用程式名稱為 Excel。

DDE 主題是數據的一般分類,其中多個數據項可能會在交談期間「討論」(交換)。 對於在檔案型檔上運作的應用程式,主題通常是檔名。 對於其他應用程式,本主題是應用程式特定的名稱。

因為客戶端和伺服器視窗會一起處理一起識別 DDE 交談,所以定義交談的應用程式名稱和主題無法在交談過程中變更。

DDE 資料項是與應用程式之間交換之交談主題相關的資訊。 數據項的值可以從伺服器傳遞至用戶端,或從客戶端傳遞至伺服器。 數據可以使用任何標準剪貼簿格式或已註冊的剪貼簿格式傳遞。 名為 Link 的特殊已註冊格式會識別 DDE 交談中的專案。 如需剪貼簿格式的詳細資訊,請參閱 剪貼簿

系統主題

應用程式應該隨時都支援系統主題。 本主題提供另一個應用程式可能感興趣的信息內容。

數據項值必須以 剪貼簿格式CF_TEXT 呈現。 系統主題的專案值個別元素必須以製表元分隔。 下表建議系統主題的一些專案。

項目 說明
格式 應用程式可以轉譯之剪貼簿格式的製表符分隔清單。 一般而言, CF_ 格式會列出已移除名稱的 “CF_” 部分 (例如, CF_TEXT 列為 “TEXT” )。
Help 簡短說明如何使用 DDE 伺服器的文字。
ReturnMessage 支援最近使用 WM_DDE_ACK 訊息的詳細數據。 當需要超過八位應用程式特定傳回數據時,此專案很有用。
狀態 指示應用程式目前的狀態。 當伺服器收到此系統主題專案的WM_DDE_REQUEST訊息時,應該視需要張貼包含忙碌或就緒字串的WM_DDE_DATA訊息來回應。
SysItems 應用程式支援的系統主題專案清單。
TopicItemList 類似於 SysItems 專案,不同之處在於,除了系統主題之外,應該支援 TopicItemList。 這可讓您流覽任何主題下支援的專案。 如果無法列舉專案,此項目應該只包含 「TopicItemList」。。
主題 應用程式目前支援的主題清單;此清單可能會因時刻而異。

 

一旦 DDE 交談開始,用戶端就可以與伺服器建立一或多個永久數據連結。 數據連結是通訊機制,每當指定的數據項值變更時,伺服器就會通知用戶端。 數據連結是永久的,在此通知程序繼續,直到數據連結或 DDE 交談本身終止為止。

永久 DDE 資料連結有兩種:暖和熱。 在暖數據連結中,伺服器會通知用戶端數據項的值已變更,但伺服器在用戶端要求數據之前,不會將數據值傳送至用戶端。 在經常性數據連結中,伺服器會立即將變更的數據值傳送至用戶端。

支援暖或經常性數據連結的應用程式通常會在其 [編輯] 功能表中提供 [複製貼上連結] 命令,讓用戶能夠建立應用程式之間的連結。

Atom 和共用記憶體物件

DDE 訊息的某些自變數是全域原子或共用記憶體物件。 使用這些自變數的應用程式必須遵循關於何時配置和刪除這些自變數的明確規則。 在所有情況下,訊息傳送者都必須刪除預期接收者因錯誤狀況而無法接收的任何 Atom 或共用記憶體物件,例如 PostMessage 函式失敗

DDE 使用共用記憶體物件進行三個用途:

  • 若要傳送要交換的數據項值。 這是WM_DDE_DATA和WM_DDE_POKE訊息中 hData 參數所參考的專案。
  • 在訊息中攜帶選項。 這是 hOptions 參數在WM_DDE_ADVISE訊息中參考的專案。
  • 若要攜帶命令執行字串。 這是WM_DDE_EXECUTE訊息中 hCommands 參數所參考的專案,以及其對應的WM_DDE_ACK訊息。

接收 DDE 共用記憶體物件的應用程式必須將其視為唯讀。 應用程式不得使用物件做為可自由交換數據的相互讀寫區域。

與 DDE Atom 一樣,應用程式應該釋放共用記憶體物件,以有效地管理記憶體。 應用程式也應該鎖定和解除鎖定記憶體物件。

動態數據交換訊息概觀

由於 DDE 是以訊息為基礎的通訊協定,因此不會採用任何函式或連結庫。 所有 DDE 交易都是透過在用戶端與伺服器視窗之間傳遞特定定義的 DDE 訊息來執行。

有九個 DDE 訊息;這些訊息的符號常數定義於 DDE 標頭檔中。 此標頭檔案也會定義各種 DDE 訊息的特定結構。

下表摘要說明 DDE 訊息。

訊息 描述
WM_DDE_ACK 認可接收或未接收訊息。
WM_DDE_ADVISE 要求伺服器應用程式在資料項變更時提供更新或通知。 這會建立永久數據連結。
WM_DDE_DATA 將資料項值傳送至用戶端應用程式。
WM_DDE_EXECUTE 將字串傳送至伺服器應用程式,預期會將字串當作一系列命令來處理。
WM_DDE_INITIATE 起始客戶端與伺服器應用程式之間的交談。
WM_DDE_POKE 將資料項值傳送至伺服器應用程式。
WM_DDE_REQUEST 要求伺服器應用程式提供資料項的值。
WM_DDE_TERMINATE 終止交談。
WM_DDE_UNADVISE 終止永久數據連結。

 

應用程式會呼叫 SendMessage 來發出WM_DDE_INITIATE訊息或WM_DDE_ACK訊息,以回應WM_DDE_INITIATE。 所有其他訊息都會由 PostMessage傳送。 這些呼叫的第一個參數是接收視窗的句柄;第二個參數包含要傳送的訊息;第三個參數會識別傳送視窗;和第四個參數包含訊息特定的自變數。

動態數據交換訊息流程

典型的 DDE 交談包含下列事件:

  1. 用戶端應用程式會起始交談,而伺服器應用程式會回應。

  2. 應用程式會以下列任何或所有方法交換資料:

      • 伺服器應用程式會在用戶端的要求下將數據傳送至用戶端。
      • 用戶端應用程式會將未經請求的數據傳送至伺服器應用程式。
      • 每當資料項變更時,用戶端應用程式會要求伺服器應用程式通知用戶端(暖數據連結)。
      • 用戶端應用程式會要求伺服器應用程式在資料變更時傳送數據(經常性數據連結)。
      • 伺服器應用程式會在用戶端的要求下執行命令。
  3. 用戶端或伺服器應用程式都會終止交談。

處理來自用戶端或伺服器要求的應用程式窗口,必須嚴格按照收到要求的順序來處理這些要求。

用戶端可以建立與多部伺服器的交談;伺服器可以與多個客戶端進行交談。 處理來自多個來源的訊息時,用戶端或伺服器必須同步處理交談的訊息,但不需要同步處理所有訊息。 換句話說,它可以視需要從一個交談轉移到另一個交談。

如果應用程式因為正在等候 DDE 回應而無法處理傳入要求,它必須藉由將 DDEACK 結構的 fBusy 成員張貼為 1 的WM_DDE_ACK訊息來防止死結。 如果基於任何原因,應用程式也無法在合理的時間內處理傳入要求,則應用程式也可以傳送忙碌 的WM_DDE_ACK 訊息。

應用程式應該能夠處理用戶端或伺服器在特定時間內回應訊息的失敗。 由於超時時間間隔可能會因應用程式的性質和使用者的系統設定而有所不同(包括是否連線到網路),因此應用程式應該提供一種方式讓使用者指定間隔。

參數封裝函式

許多 DDE 訊息的 lParam 參數包含兩個數據片段。 例如,WM_DDE_DATA訊息的 lParam 包含數據句柄和 Atom。 應用程式必須使用 PackDDElParam 函式將句柄和 Atom 封裝成 lParam 參數,以及 UnpackDDElParam 函式來移除值。 DDE 應用程式必須針對在 DDE 交談期間張貼的所有訊息使用 PackDDElParamUnpackDDElParam

應用程式也可以使用 ReuseDDElParam FreeDDElParam 函式。 ReuseDDElParam 可讓 DDE 應用程式重複使用已 封裝的 lParam 參數,協助減少應用程式在交談期間必須執行的記憶體重新配置數目。 應用程式可以使用 FreeDDElParam 釋放與 DDE 交談期間所接收之數據句柄相關聯的記憶體。

動態數據交換和模擬

若要允許伺服器模擬用戶端,用戶端會呼叫 DdeSetQualityOfService 函式。 SECURITY_IMPERSONATION_LEVEL 結構可用來控制伺服器可能執行的模擬層級。

DDE 伺服器可以藉由呼叫 ImpersonateDdeClientWindow 函式來模擬 DDE 用戶端。 DDEML 伺服器應該使用 DdeImpersonateClient 函 式。