交易管理 (Data Exchange)
建立與伺服器的交談之後,用戶端可以傳送交易,以從伺服器取得數據和服務。
下列主題描述用戶端可用來與伺服器互動的交易類型。
要求交易
用戶端應用程式可以使用 XTYP_REQUEST 交易,向伺服器應用程式要求數據項。 用戶端會呼叫 DdeClientTransaction 函式,將XTYP_REQUEST指定為交易類型,並指定應用程式所需的數據項。
動態數據交換管理連結庫 (DDEML) 會將XTYP_REQUEST交易傳遞至伺服器,並指定用戶端所要求的主題名稱、專案名稱和數據格式。 如果伺服器支援要求的主題、專案和格式,伺服器應該會傳回可識別專案目前值的數據句柄。 DDEML 會將這個句柄傳遞至用戶端,做為 DdeClientTransaction 的傳回值。 如果伺服器不支援所要求的主題、專案或格式,伺服器應該會傳回 NULL 。
DdeClientTransaction 使用 lpdwResult 參數,將交易狀態旗標傳回用戶端。 如果伺服器未處理 XTYP_REQUEST 交易, DdeClientTransaction 會 傳回 NULL,而 lpdwResult 會指向DDE_FNOTPROCESSED或DDE_FBUSY旗標。 如果傳回DDE_FNOTPROCESSED旗標,則客戶端無法判斷伺服器未處理交易的原因。
如果伺服器不支援XTYP_REQUEST交易,它應該在 DdeInitialize 函式中指定CBF_FAIL_REQUESTS篩選旗標。 此旗標可防止 DDEML 將交易傳送至伺服器。
Poke Transaction
用戶端可以使用 DdeClientTransaction 將XTYP_POKE交易傳送至伺服器的回呼函式,將未經請求的數據傳送至伺服器。
用戶端應用程式會先建立緩衝區,其中包含要傳送至伺服器的數據,然後將指標傳遞至緩衝區做為參數至 DdeClientTransaction。 或者,用戶端可以使用 DdeCreateDataHandle 函式來取得可識別數據的數據句柄,然後將句柄傳遞至 DdeClientTransaction。 在任一情況下,用戶端也會在呼叫 DdeClientTransaction 時指定主題名稱、專案名稱和數據格式。
DDEML 會將 XTYP_POKE 交易傳遞至伺服器,並指定用戶端要求的主題名稱、專案名稱和數據格式。 若要接受數據項和格式,伺服器應該會傳回DDE_FACK。 若要拒絕數據,伺服器應該會傳回DDE_FNOTPROCESSED。 如果伺服器太忙碌而無法接受數據,伺服器應該會傳回DDE_FBUSY。
當 DdeClientTransaction 傳回時,用戶端可以使用 lpdwResult 參數來存取交易狀態旗標。 如果旗標是DDE_FBUSY,客戶端應該稍後再次傳送交易。
如果伺服器不支援XTYP_POKE交易,它應該在 DdeInitialize 中指定CBF_FAIL_POKES篩選旗標。 此旗標可防止 DDEML 將此交易傳送至伺服器。
建議交易
用戶端應用程式可以使用 DDEML 來建立伺服器應用程式中專案的一或多個連結。 建立這類連結時,伺服器會將連結專案的相關定期更新傳送給用戶端(通常是每當與伺服器應用程式相關聯的專案值變更時)。 連結會建立兩個應用程式之間的建議迴圈,這些應用程式會保留到客戶端結束為止。
有兩種建議迴圈:「熱」和「暖」。在經常性建議迴圈中,伺服器會立即傳送可識別已變更值的數據句柄。 在暖建議迴圈中,伺服器會通知客戶端專案的值已變更,但在用戶端要求之前,不會傳送數據句柄。
用戶端可以在對 DdeClientTransaction 的呼叫中指定XTYP_ADVSTART交易類型,以要求與伺服器進行熱建議迴圈。 若要要求暖建議迴圈,客戶端必須結合XTYPF_NODATA旗標與 XTYP_ADVSTART 交易類型。 在任一事件中,DDEML 會將 XTYP_ADVSTART 交易傳遞至伺服器的動態數據交換 (DDE) 回呼函式。 伺服器的 DDE 回呼函式應該檢查 伴隨XTYP_ADVSTART 交易的參數(包括要求的格式、主題名稱和專案名稱),然後傳回 TRUE 以允許建議迴圈或 FALSE 拒絕它。
建立建議迴圈之後,每當與要求的專案名稱相關聯的專案值變更時,伺服器應用程式應該呼叫 DdePostAdvise 函式。 此呼叫會導致 XTYP_ADVREQ 交易傳送至伺服器自己的 DDE 回呼函式。 伺服器的 DDE 回呼函式應該會傳回可識別數據項新值的數據句柄。 然後,DDEML 會藉由將XTYP_ADVDATA交易傳送至用戶端的 DDE 回呼函式,通知用戶端指定的專案已變更。
如果用戶端要求經常性建議迴圈,DDEML 會在XTYP_ADVDATA交易期間,將數據句柄傳遞至已變更的專案給用戶端。 否則,用戶端可以傳送 XTYP_REQUEST 交易,以取得數據句柄。
伺服器可以比客戶端處理新數據更快傳送更新。 更新速度可能是客戶端必須對數據執行冗長處理作業的問題。 在此情況下,用戶端在要求建議迴圈時,應該指定XTYPF_ACKREQ旗標。 此旗標會讓伺服器等待用戶端確認它已接收並處理過數據項,然後伺服器才會傳送下一個數據項。 建議使用 XTYPF_ACKREQ 旗標建立的迴圈較強固,但偶爾可能會遺漏更新。 只要用戶端跟上伺服器,在未建立XTYPF_ACKREQ旗標的情況下建立的建議迴圈就不錯過更新。
用戶端可以在呼叫 DdeClientTransaction 時指定XTYP_ADVSTOP交易類型,以結束建議迴圈。
如果伺服器不支持建議迴圈,它應該在 DdeInitialize 函式中指定CBF_FAIL_ADVISES篩選旗標。 此旗標可防止 DDEML 將XTYP_ADVSTART和XTYP_ADVSTOP交易傳送至伺服器。
執行交易
用戶端可以使用 XTYP_EXECUTE 交易,讓伺服器執行命令或一系列命令。
若要執行伺服器命令,用戶端會先建立緩衝區,其中包含要執行之伺服器的命令字串,然後在呼叫 DdeClientTransaction 時傳遞緩衝區指標或識別緩衝區的數據句柄。 其他必要參數包括交談句柄、項目名稱字串句柄、格式規格,以及 XTYP_EXECUTE 交易類型。 建立用來傳遞執行數據之數據處理句柄的應用程式必須針對 DdeCreateDataHandle 函式的 hszItem 參數指定 NULL,而 uFmt 參數則為零。
DDEML 會將 XTYP_EXECUTE 交易傳遞至伺服器的 DDE 回呼函式,並指定識別命令字串的格式名稱、交談句柄、主題名稱和數據句柄。 如果伺服器支援 命令,它應該使用 DdeAccessData 函式來取得命令字串的指標、執行命令,然後傳回DDE_FACK。 如果伺服器不支援 命令或無法完成交易,則應該傳回DDE_FNOTPROCESSED。 如果伺服器太忙碌而無法完成交易,伺服器應該會傳回DDE_FBUSY。
一般而言,伺服器的回呼函式應該先處理 XTYP_EXECUTE 交易,再傳回下列例外狀況:
- 當與 XTYP_EXECUTE 交易一起傳遞的命令要求伺服器終止時,伺服器不應該終止,直到其回呼函式從處理XTYP_EXECUTE傳回為止。
- 如果伺服器必須執行作業,例如處理可能導致 DDEML 遞歸問題的對話框或 DDE 交易,伺服器應該傳回CBR_BLOCK傳回碼來封鎖執行交易、執行作業,然後繼續處理執行交易。
當 DdeClientTransaction 傳回時,用戶端可以使用 lpdwResult 參數來存取交易狀態旗標。 如果旗標是DDE_FBUSY,客戶端應該稍後再次傳送交易。
如果伺服器不支援XTYP_EXECUTE交易,它應該在 DdeInitialize 函式中指定CBF_FAIL_EXECUTES篩選旗標。 這樣做可防止 DDEML 將交易傳送至伺服器。
同步和異步交易
用戶端可以傳送同步或異步交易。 在同步交易中,用戶端會指定逾時值,指出等候伺服器處理交易的時間上限。 在伺服器處理交易、交易失敗或逾時值到期之前,DdeClientTransaction 不會傳回。 用戶端會在呼叫 DdeClientTransaction 時指定逾時值。
在同步交易期間,用戶端會在等候交易處理時輸入強制回應迴圈。 用戶端仍然可以處理使用者輸入,但無法在 DdeClientTransaction 傳回之前傳送另一個同步交易。
用戶端藉由在 DdeClientTransaction 中指定TIMEOUT_ASYNC旗標來傳送異步交易。 函式會在交易開始之後傳回,並將交易標識碼傳遞至用戶端。 當伺服器完成處理異步交易時,DDEML 會將XTYP_XACT_COMPLETE交易傳送給用戶端。 在XTYP_XACT_COMPLETE交易期間,DDEML 傳遞給用戶端的其中一個參數是交易標識符。 藉由比較此交易標識碼與 DdeClientTransaction 所傳回的標識碼,用戶端會識別伺服器已完成處理的異步交易。
用戶端可以使用 DdeSetUserHandle 函式作為處理異步交易的協助。 此函式可讓用戶端將應用程式定義值與交談句柄和交易標識碼產生關聯。 用戶端可以在XTYP_XACT_COMPLETE交易期間使用 DdeQueryConvInfo 函式來取得應用程式定義的值。 由於此函式,應用程式不需要維護使用中交易標識碼的清單。
當用戶端使用同步交易順利完成數據要求時,DDEML 無法判斷用戶端何時使用收到的數據完成。 用戶端應用程式必須將接收的數據句柄傳遞至 DdeFreeDataHandle 函式,通知 DDEML 不再使用句柄。 同步交易傳回的數據句柄實際上由客戶端擁有。
如果伺服器未及時處理異步交易,用戶端可以呼叫 DdeAbandonTransaction 函式來放棄交易。 DDEML 會釋放與交易相關聯的所有資源,並在伺服器完成處理交易時捨棄交易的結果。 同步交易期間的逾時會有效地取消交易。
異步交易方法提供給必須傳送大量 DDE 交易的應用程式,同時執行大量的處理,例如執行計算。 異步方法在必須暫時停止處理 DDE 交易的應用程式中也很有用,因此它們可以在不中斷的情況下完成其他工作。 在大部分的其他情況下,應用程式應該使用同步方法。
同步交易更容易維護,而且比異步交易更快。 不過,一次只能執行一個同步交易,而許多異步交易可以同時執行。 使用同步交易時,慢速伺服器可能會導致用戶端在等候回應時保持閑置。 此外,同步交易也會讓用戶端進入模式迴圈,以略過應用程式本身訊息迴圈中的訊息篩選。
如果用戶端已安裝攔截程式來篩選訊息(也就是說,在 SetWindowsHookEx 函式呼叫中指定WH_MSGFILTER攔截類型),同步交易將不會造成系統略過攔截程式。 當用戶端等候同步交易結束時發生輸入事件時,攔截程式會收到MSGF_DDEMGR攔截程式。 使用同步交易強制回應迴圈的主要危險在於對話框所建立的強制回應迴圈可能會干擾其作業。 DLL 正在使用 DDEML 時,應該一律使用異步交易。
交易控制
無論交談句柄為何,應用程式都可以暫停與特定交談句柄或所有交易相關聯的交易至其 DDE 回呼函式。 當應用程式收到需要長時間處理的交易時,這項功能很有用。 在這種情況下,應用程式可以傳回CBR_BLOCK傳回碼,以暫停與交易交談句柄相關聯的未來交易,讓應用程式可以自由處理其他交談。
處理完成時,應用程式會呼叫 DdeEnableCallback 函式,以繼續與暫停交談相關聯的交易。 呼叫 DdeEnableCallback 會導致 DDEML 重新傳送導致應用程式暫停交談的交易。 因此,應用程式應該以這樣的方式儲存交易的結果,以便取得並傳回結果,而不需重新處理交易。
應用程式可以在呼叫 DdeEnableCallback 時指定句柄和EC_DISABLE旗標,以暫停與特定交談句柄相關聯的所有交易。 藉由指定 NULL 句柄,應用程式可以暫停所有交談的所有交易。
當交談暫停時,DDEML 會將交談的交易儲存在交易佇列中。 當應用程式重新啟用交談時,DDEML 會從佇列中移除已儲存的交易,並將每個交易傳遞至適當的回呼函式。 交易佇列的容量很大,但應用程式應儘快重新啟用暫停的交談,以避免遺失交易。
應用程式可以藉由在 DdeEnableCallback 中指定EC_ENABLEALL旗標,以繼續一般事務處理。 若要更受控制地繼續事務處理,應用程式可以指定EC_ENABLEONE旗標。 此旗標會從交易佇列中移除一個交易,並將其傳遞至適當的回呼函式;處理該交易之後,任何交談會再次停用。
如果在對 DdeEnableCallback 的呼叫中指定了EC_ENABLEONE旗標和交談句柄,則只會在處理交易之後封鎖該交談。 如果指定 NULL 交談句柄,所有交談都會在任何交談中處理交易之後封鎖。
交易分類
DDEML 有四種交易類別。 每個類別都是由以 XCLASS_ 前置詞開頭的常數來識別。 類別定義於 DDEML 頭檔中。 類別值會與交易類型值結合,並傳遞至接收應用程式的 DDE 回呼函式。
交易的 類別會決定回呼函式在處理交易時應該傳回的傳回值。 下列傳回值和交易類型會與四個交易類別中的每一個相關聯。
類別 | 傳回值 | 交易 |
---|---|---|
XCLASS_BOOL | TRUE 或 FALSE | XTYP_ADVSTART XTYP_CONNECT |
XCLASS_DATA | 數據句柄、CBR_BLOCK傳回碼或 NULL | XTYP_ADVREQ XTYP_REQUEST XTYP_WILDCONNECT |
XCLASS_FLAGS | 交易旗標:DDE_FACK、DDE_FBUSY或DDE_FNOTPROCESSED | XTYP_ADVDATA XTYP_EXECUTE XTYP_POKE |
XCLASS_NOTIFICATION | 無 | XTYP_ADVSTOP XTYP_CONNECT_CONFIRM XTYP_DISCONNECT XTYP_ERROR XTYP_REGISTER XTYP_UNREGISTER XTYP_XACT_COMPLETE |
交易類型
每個 DDE 交易類型都有一個接收者和相關聯的活動,導致 DDEML 產生每個類型。
交易類型 | 接收者 | 原因 |
---|---|---|
XTYP_ADVDATA | 用戶端 | 伺服器藉 由傳回數據句柄來回應XTYP_ADVREQ 交易。 |
XTYP_ADVREQ | 伺服器 | 稱為 DdePostAdvise 函式的伺服器 ,指出建議迴圈中的數據項值已變更。 |
XTYP_ADVSTART | 伺服器 | 用戶端在呼叫 DdeClientTransaction 函式時指定了XTYP_ADVSTART交易類型。 |
XTYP_ADVSTOP | 伺服器 | 用戶端在呼叫 DdeClientTransaction 時指定了XTYP_ADVSTOP交易類型。 |
XTYP_CONNECT | 伺服器 | 名為 Dde 連線 函式的用戶端,並指定伺服器所支援的服務名稱和主題名稱。 |
XTYP_CONNECT_CONFIRM | 伺服器 | 伺服器傳回 TRUE 以回應XTYP_CONNECT或XTYP_WILDCONNECT交易。 |
XTYP_DISCONNECT | 用戶端/伺服器 | 交談中稱為 DdeDisconnect 函式的夥伴,導致這兩個夥伴都會收到此交易。 |
XTYP_ERROR | 用戶端/伺服器 | 發生嚴重錯誤。 DDEML 可能沒有足夠的資源可以繼續。 |
XTYP_EXECUTE | 伺服器 | 用戶端在呼叫 DdeClientTransaction 時指定了XTYP_EXECUTE交易類型。 |
XTYP_MONITOR | DDE 監視應用程式 | 系統發生 DDE 事件。 如需 DDE 監視應用程式的詳細資訊,請參閱 監視應用程式。 |
XTYP_POKE | 伺服器 | 用戶端在呼叫 DdeClientTransaction 時指定了XTYP_POKE交易類型。 |
XTYP_REGISTER | 用戶端/伺服器 | 伺服器應用程式使用 DdeNameService 函式來註冊服務名稱。 |
XTYP_REQUEST | 伺服器 | 用戶端在呼叫 DdeClientTransaction 時指定了XTYP_REQUEST交易類型。 |
XTYP_UNREGISTER | 用戶端/伺服器 | 伺服器應用程式使用 DdeNameService 取消註冊服務名稱。 |
XTYP_WILDCONNECT | 伺服器 | 稱為 Dde 連線 或 Dde 連線 List 函式的用戶端,針對服務名稱、主題名稱或兩者指定 NULL。 |
XTYP_XACT_COMPLETE | 用戶端 | 當用戶端在呼叫 DdeClientTransaction 時指定TIMEOUT_ASYNC旗標時傳送的異步交易已經結束。 |