動的データ交換について

Windows には、アプリケーション間でデータを転送するためのいくつかの方法が用意されています。 1 つの方法は、Dynamic Data Exchange (DDE) プロトコルを使用することです。 DDE プロトコルは、一連のメッセージとガイドラインです。 データを共有し、共有メモリを使用してアプリケーション間でデータを交換するアプリケーション間でメッセージを送信します。 アプリケーションでは、DDE プロトコルを使用して、1 回限りのデータ転送や、新しいデータが使用可能になったときにアプリケーションが相互に更新を送信する継続的な交換を行うことができます。

Windows では、動的データ交換管理ライブラリ (DDEML) もサポートされています。 DDEML は、アプリケーションがデータの共有に使用できるダイナミック リンク ライブラリ (DLL) です。 DDEML には、DDE 機能をアプリケーションに追加するタスクを簡略化する関数とメッセージが用意されています。 アプリケーションでは、DDE メッセージを直接送信、投稿、および処理する代わりに、DDEML 関数を使用して DDE 会話を管理します。 (DDE 会話は、クライアント アプリケーションとサーバー アプリケーション間の相互作用です)。

DDEML には、DDE アプリケーションが共有する文字列とデータを管理するための機能も用意されています。 DDE アプリケーションでは、共有メモリ オブジェクトへのアトムとポインターを使用する代わりに、文字列を識別する文字列ハンドルと、メモリ オブジェクトを識別するデータ ハンドルを作成して交換します。 DDEML を使用すると、サーバー アプリケーションがサポートするサービス名を登録することもできます。 名前はシステム内の他のアプリケーションにブロードキャストされ、名前を使用してサーバーに接続できます。 さらに、DDEML は、DDE プロトコルを一貫した方法で強制的に実装することで、DDE アプリケーション間の互換性を確保します。

メッセージ ベースの DDE プロトコルを使用する既存のアプリケーションは、DDEML を使用するアプリケーションと完全に互換性があります。 つまり、メッセージ ベースの DDE を使用するアプリケーションは、会話を確立し、DDEML を使用するアプリケーションとのトランザクションを実行できます。 DDEML には多くの利点があるため、新しいアプリケーションでは DDE メッセージではなく、DDEML を使用する必要があります。 DDEML の API 要素を使用するには、DDEML ヘッダー ファイルをソース ファイルに含め、DDEML ライブラリとリンクし、DDEML ダイナミック リンク ライブラリがシステムの検索パスにあることを確認する必要があります。

このセクションでは、次のトピックについて説明します。

動的データ交換プロトコル

Windows にはメッセージ ベースのアーキテクチャがあるため、アプリケーション間で情報を自動的に転送するための最も適切な方法は、メッセージの受け渡しです。 ただし、メッセージには、データを渡すためのパラメーター (wParamlParam) が 2 つだけ含まれています。 その結果、アプリケーション間で数語以上の情報が渡される場合、これらのパラメーターは他のデータを間接的に参照する必要があります。 DDE プロトコルでは、アプリケーションで wParam パラメーターと lParam パラメーターを使用して、グローバル アトムと共有メモリ ハンドルを使用してより大きなデータを渡す方法を正確に定義します。 DDE プロトコルには、グローバル アトムと共有メモリ オブジェクトの割り当てと削除に関する特定の規則があります。

グローバル アトムは、文字列への参照です。 DDE プロトコルでは、アトムは、データを交換するアプリケーション、交換されるデータの性質、およびデータ項目自体を識別します。 アトムの詳細については、「アトムについて」を参照してください。

Windows 動的データ交換の使用

DDE は、継続的なユーザー操作を必要としないデータ交換に最適です。 通常、アプリケーションは、ユーザーがデータを交換するアプリケーション間のリンクを確立するためのメソッドを提供します。 ただし、そのリンクが確立されると、アプリケーションはユーザーの関与なしにデータを交換します。

DDE を使用して、さまざまなアプリケーション機能を実装できます。次に例を示します。

  • 株価情報、科学機器、プロセス制御などのリアルタイム データへのリンク。
  • グラフィックス アプリケーションによって生成されたグラフを含むワープロ ドキュメントなど、複合ドキュメントを作成する。 DDE を使用すると、ソース データが変更されるとグラフが変更されますが、ドキュメントの残りの部分は変わりません。
  • 期限を過ぎたアカウントをデータベースに照会するスプレッドシートなど、アプリケーション間でデータ クエリを実行する。

ユーザーの観点からの動的データ交換

次の例は、ユーザーの観点から見ると、2 つの DDE アプリケーションがどのように連携できるかを示しています。

スプレッドシート ユーザーは、Microsoft Excel を使用して、ニューヨーク証券取引所の特定の株式の価格を追跡したいと考えています。 ユーザーには Quote というアプリケーションがあり、そのアプリケーションは NY Standard Edition データにアクセスできます。 Excel と Quote の間の DDE 会話は次のように行われます。

  • ユーザーは、データと関心のある特定のトピック (NY Standard Edition) を提供するアプリケーションの名前 (Quote) を指定して、会話を開始します。 結果の DDE 会話は、特定の株式の見積もりを要求するために使用されます。
  • Excel は、システムで現在実行されているすべての DDE アプリケーションにアプリケーション名とトピック名をブロードキャストします。 引用符が応答し、NY Standard Edition トピックに関する Excel との会話が確立されます。
  • その後、ユーザーは、特定の株価情報が変更されるたびにスプレッドシートを自動的に更新することを要求するスプレッドシート数式をセルに作成できます。 たとえば、ユーザーは、次の Excel 数式を指定して ZAXX 在庫の販売価格に変更が発生するたびに自動更新を要求できます: ='Quote'|'NY Standard Edition'!ZAXX
  • ユーザーは、ZAXX 在庫見積の自動更新をいつでも終了できます。 個別に確立された他のデータ リンク (他の株式の相場情報など) は、引き続き同じ NYSE 会話の下でアクティブなままになります。
  • ユーザーは、NY Standard Edition トピックの Excel と Quote の間の会話全体を終了して、新しい会話を開始せずにそのトピックの特定のデータ リンクを確立できないようにすることもできます。

動的データ交換の概念

次のセクションでは、動的なデータ交換を理解するための重要な概念と用語について説明します。

クライアント、サーバー、会話

DDE に参加している 2 つのアプリケーションが DDE 会話に参加していると言われます。 会話を開始するアプリケーションは DDE クライアント アプリケーションです。クライアントに応答するアプリケーションが DDE サーバー アプリケーションです。 アプリケーションは、一部ではクライアントとして機能し、他のアプリケーションではサーバーとして機能し、同時に複数の会話を行うことができます。

DDE 会話は、参加しているアプリケーションごとに 1 つずつ、2 つのウィンドウの間で行われます。 ウィンドウは、アプリケーションのメイン ウィンドウ、複数ドキュメント インターフェイス (MDI) アプリケーションのように特定のドキュメントに関連付けられたウィンドウ、または DDE メッセージの処理のみを目的とする非表示 (非表示) ウィンドウです。

DDE 会話は、会話に参加しているウィンドウへのハンドルのペアによって識別されるため、別のウィンドウとの複数の会話にウィンドウを関与させる必要はありません。 クライアント アプリケーションまたはサーバー アプリケーションは、特定のサーバーまたはクライアント アプリケーションとの会話ごとに異なるウィンドウを提供する必要があります。

アプリケーションは、会話ごとに非表示ウィンドウを作成することで、クライアントウィンドウとサーバーウィンドウのペアが複数の会話に関与しないようにすることができます。 このウィンドウの唯一の目的は、DDE メッセージを処理することです。

アプリケーション名、トピック名、および項目名

DDE プロトコルは、アプリケーション、トピック、および項目名の 3 レベル階層を持つクライアントとサーバーの間で渡されるデータの単位を識別します。

各 DDE 会話は、アプリケーション名とトピックによって一意に定義されます。 DDE 会話の開始時に、クライアントとサーバーがアプリケーション名とトピックを決定します。 通常、アプリケーション名はサーバー アプリケーションの名前です。 たとえば、Excel が会話のサーバーとして機能する場合、アプリケーション名は Excel です。

DDE トピックは、会話中に複数のデータ項目を "ディスカッション" (交換) できるデータの一般的な分類です。 ファイル ベースのドキュメントを操作するアプリケーションの場合、通常、このトピックはファイル名です。 他のアプリケーションの場合、トピックはアプリケーション固有の名前です。

クライアント ウィンドウとサーバー ウィンドウが一緒に処理して DDE 会話を識別するため、会話を定義するアプリケーション名とトピックは、会話の実行中に変更できません。

DDE データ項目は、アプリケーション間で交換される会話トピックに関連する情報です。 データ項目の値は、サーバーからクライアントに、またはクライアントからサーバーに渡すことができます。 データは、標準のクリップボード形式と共に、または登録済みのクリップボード形式で渡すことができます。 Link という名前の特殊な登録済み形式は、DDE 会話内の項目を識別します。 クリップボード形式の詳細については、「クリップボード」を参照してください。

システム トピック

アプリケーションは常にシステム トピックをサポートする必要があります。 このトピックでは、他のアプリケーションにとって一般的に関心のある情報のコンテキストを示します。

データ項目の値は、 CF_TEXT クリップボード形式でレンダリングする必要があります。 システム トピックの項目値の個々の要素は、タブ文字で区切る必要があります。 次の表は、システム トピックのいくつかの項目を示しています。

アイテム 説明
形式 アプリケーションでレンダリングできるクリップボード形式のタブ区切りリスト。 通常、 CF_ 形式は、名前の "CF_" 部分が削除された状態で一覧表示されます (たとえば、 CF_TEXT は "TEXT" と表示されます)。
ヘルプ​​ DDE サーバーの使用方法を簡単に説明するテキスト。
ReturnMessage 最近使用 した WM_DDE_ACK メッセージの詳細をサポートします。 この項目は、8 ビットを超えるアプリケーション固有のリターン データが必要な場合に便利です。
Status アプリケーションの現在の状態を示します。 サーバーは、このシステム トピック項目の WM_DDE_REQUEST メッセージを受信すると、必要に応じて、 WM_DDE_DATA メッセージにビジーまたは準備完了を含む文字列を投稿して応答する必要があります。
SysItems アプリケーションがサポートするシステム トピック項目の一覧。
TopicItemList SysItems 項目と同様ですが、システム トピック以外のトピックごとに TopicItemList をサポートする必要があります。 これにより、任意のトピックでサポートされている項目を参照できます。 項目を列挙できない場合、この項目には "TopicItemList" のみを含める必要があります。
トピック アプリケーションが現在サポートしているトピックの一覧。このリストは、瞬間によって異なる場合があります。

 

DDE 会話が開始されると、クライアントはサーバーとの永続的なデータ リンクを 1 つ以上確立できます。 データ リンクは、指定されたデータ項目の値が変更されるたびにサーバーがクライアントに通知する通信メカニズムです。 データ リンクは、データ リンクまたは DDE 会話自体が終了するまで、この通知プロセスが継続するという意味で永続的です。

永続的な DDE データ リンクには、ウォームとホットの 2 種類があります。 ウォーム データ リンクでは、サーバーはデータ項目の値が変更されたことをクライアントに通知しますが、クライアントが要求するまで、サーバーはデータ値をクライアントに送信しません。 ホット データ リンクでは、サーバーはすぐに変更されたデータ値をクライアントに送信します。

ウォーム データ リンクまたはホット データ リンクをサポートするアプリケーションでは、通常、[編集] メニューの [リンクのコピー または 貼り付け] コマンドを使用して、ユーザーがアプリケーション間のリンクを確立できるようにします。

Atoms オブジェクトと共有メモリ オブジェクト

DDE メッセージの特定の引数は、グローバル アトムまたは共有メモリ オブジェクトです。 これらの引数を使用するアプリケーションでは、割り当てと削除のタイミングに関する明示的な規則に従う必要があります。 いずれの場合も、メッセージ送信者は、 PostMessage 関数の失敗などのエラー状態のために、目的の受信者が受信しないアトムまたは共有メモリ オブジェクトを削除する必要があります。

DDE では、次の 3 つの目的で共有メモリ オブジェクトが使用されます。

  • 交換するデータ項目の値を保持します。 これは、 WM_DDE_DATA および WM_DDE_POKEメッセージhData パラメーターによって参照される項目です。
  • メッセージにオプションを含める。 これは、 WM_DDE_ADVISE メッセージ内の hOptions パラメーターによって参照される項目です。
  • コマンド実行文字列を実行する。 これは、 WM_DDE_EXECUTE メッセージとそれに対応する WM_DDE_ACK メッセージ内の hCommands パラメーターによって参照される項目です。

DDE 共有メモリ オブジェクトを受け取るアプリケーションは、それを読み取り専用として扱う必要があります。 アプリケーションは、データを自由に交換するための相互読み取り/書き込み領域としてオブジェクトを使用してはなりません。

DDE アトムと同様に、アプリケーションは、メモリを効果的に管理するために共有メモリ オブジェクトを解放する必要があります。 アプリケーションでは、メモリ オブジェクトのロックとロック解除も行う必要があります。

動的データ交換メッセージの概要

DDE はメッセージ ベースのプロトコルであるため、関数やライブラリを使用しません。 すべての DDE トランザクションは、クライアント ウィンドウとサーバー ウィンドウの間で特定の定義済み DDE メッセージを渡すことによって実行されます。

DDE メッセージは 9 つあります。これらのメッセージのシンボリック定数は 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_INITIATE メッセージまたは WM_DDE_ACK メッセージを発行します。 他のすべてのメッセージは PostMessage によって送信されます。 これらの呼び出しの最初のパラメーターは、受信ウィンドウへのハンドルです。2 番目のパラメーターには、送信するメッセージが含まれています。3 番目のパラメーターは、送信ウィンドウを識別します。4 番目のパラメーターには、メッセージ固有の引数が含まれています。

動的データ交換メッセージ フロー

一般的な DDE 会話は、次のイベントで構成されます。

  1. クライアント アプリケーションが会話を開始し、サーバー アプリケーションが応答します。

  2. アプリケーションは、次のいずれかの方法またはすべての方法でデータを交換します。

      • サーバー アプリケーションは、クライアントの要求時にクライアントにデータを送信します。
      • クライアント アプリケーションは、未承諾のデータをサーバー アプリケーションに送信します。
      • クライアント アプリケーションは、データ項目が変更されるたびにクライアントに通知するようにサーバー アプリケーションに要求します (ウォーム データ リンク)。
      • クライアント アプリケーションは、データが変更されるたびにデータを送信するようにサーバー アプリケーションに要求します (ホット データ リンク)。
      • サーバー アプリケーションは、クライアントの要求でコマンドを実行します。
  3. クライアントアプリケーションまたはサーバーアプリケーションが会話を終了します。

クライアントまたはサーバーからの要求を処理するアプリケーション ウィンドウでは、受信した順序で厳密に処理する必要があります。

クライアントは、複数のサーバーとの会話を確立できます。サーバーは、複数のクライアントとの会話を行うことができます。 複数のソースからのメッセージを処理する場合、クライアントまたはサーバーはメッセージ交換のメッセージを同期的に処理する必要がありますが、すべてのメッセージを同期的に処理する必要はありません。 つまり、必要に応じて会話間を移動できます。

アプリケーションが DDE 応答を待機しているために受信要求を処理できない場合は、 DDEACK 構造体の fBusy メンバーを 1 に設定して WM_DDE_ACK メッセージをポストしてデッドロックを防ぐ必要があります。 アプリケーションは、何らかの理由で、妥当な時間内に受信要求を処理できない場合に、ビジー状態の WM_DDE_ACK メッセージを送信することもできます。

アプリケーションは、特定の時間内にメッセージに応答するクライアントまたはサーバーのエラーを処理できる必要があります。 タイムアウト間隔は、アプリケーションの性質とユーザーのシステムの構成 (ネットワークに接続されているかどうかなど) によって異なる場合があるため、アプリケーションはユーザーが間隔を指定する方法を提供する必要があります。

パラメーターパッキング関数

多くの DDE メッセージの lParam パラメーターには、2 つのデータが含まれています。 たとえば、 WM_DDE_DATA メッセージの lParam には、データ ハンドルとアトムが含まれます。 アプリケーションでは、 PackDDElParam 関数を使用してハンドルとアトムを lParam パラメーターにパックし、 UnpackDDElParam 関数を使用して値を削除する必要があります。 DDE アプリケーションでは、DDE 会話中に投稿されたすべてのメッセージに PackDDElParamUnpackDDElParam を使用する必要があります。

アプリケーションでは、 ReuseDDElParam 関数と FreeDDElParam 関数を使用することもできます。 ReuseDDElParam を使用すると、DDE アプリケーションでパックされた lParam パラメーターを再利用できるため、アプリケーションが会話中に実行する必要があるメモリ再割り当ての数を減らすことができます。 アプリケーションでは、 FreeDDElParam を使用して、DDE 会話中に受信したデータ ハンドルに関連付けられているメモリを解放できます。

動的データ交換と偽装

サーバーがクライアントを偽装できるようにするために、クライアントは DdeSetQualityOfService 関数を呼び出します。 Standard EditionCURITY_IMPERSONATION_LEVEL 構造体は、サーバーが実行できる偽装のレベルを制御するために使用されます。

DDE サーバーは、 ImpersonateDdeClientWindow 関数を呼び出すことによって DDE クライアントを偽装できます。 DDEML サーバーでは、 DdeImpersonateClient 関数を使用する必要があります。