サーバーの作成DDEMLを使用してDDEサーバーを作成することは、メッセージベースのDDEと比べてかなりの利点があります。クライアントが複数存在する場合は、送られてきたメッセージがどのクライアントのものかを判断する必要があります。サーバーは自身に接続してきたクライアントを管理する必要はありません。サーバーが返したデータは、常に適切なクライアントへと送られます。クライアントからのWM_DDE_INITIATEを処理するということになります。アプリケーションがこの動作を行うようになるには、DdeNameServiceを呼び出します。afCmd);idInstは、インスタンス識別子を指定します。hsz1は、サーバーのサービス名を指定します。hsz2は、予約されているためNULLを指定します。受け入れないようにする場合にDNS_UNREGISTERを指定します。DdeNameServiceを呼び出せば、クライアントからの通知がDdeInitializeに指定したコールバック関数が送られることになります。クライアントがDdeClientTransaction(XTYP_REQUEST指定)や、WM_DDE_REQUESTをポストした場合は、XTYP_REQUESTという通知が送られることになるでしょう。サポートする場合は適切なデータをコールバック関数の戻り値として返すことになります。今回のプログラムは、チェックボックスを表示しており、そのチェックボックスの状態をクライアントが取得したり設定したりできます。CF_TEXT;}WM_CREATEでは、DdeInitializeとDdeNameServiceを呼び出しています。不要な通知を受け取りたくない場合は、その通知を示す定数を指定することができます。CBF_SKIP_REGISTRATIONSを指定すればこれを受け取らないようにできます。CBF_SKIP_DISCONNECTSを指定すればこれを受け取らないようにできます。これらの文字列ハンドルもWM_CREATEで作成しておきます。コールバック関数に送られる通知を1つずつ見ていきます。(HDDEDATA)TRUE;XTYP_CONNECTは、クライアントがDdeConnectを呼び出した場合や、WM_DDE_INITIATEを送信した場合に送られます。hsz1にはクライアントが指定したトピック名が格納されており、これがサーバーがサポートする名前と一致するかを調べます。一致しない場合はDDE対話ができないことを示すFALSEを返し、一致する場合は対話可能を示すTRUEを返します。GetData();XTYP_REQUESTは、DdeClientTransaction(XTYP_REQUEST指定)を呼び出した場合や、WM_DDE_REQUESTをポストした場合に呼ばれます。hsz1にはクライアントが指定したトピック名が格納されており、hsz2にはデータを識別するアイテム名が格納されています。適切である場合はDdeCreateDataHandleで作成したハンドルを返すようにします。GetDataの実装は次のようになっています。0);}チェックボックスの現在の状態を確認し、チェックが付いている場合はtrue、チェックが付いていない場合はfalseを返すようにします。DdeCreateDataHandleの第2引数には作成するデータを指定し、第3引数にはデータのサイズを指定します。第5引数はデータを識別するアイテム名であり、第6引数はデータのフォーマットを指定します。今回のデータはテキスト形式であるため、CF_TEXTを指定しています。(HDDEDATA)DDE_FACK;}XTYP_POKEは、DdeClientTransaction(XTYP_POKE指定)を呼び出した場合や、WM_DDE_POKEをポストした場合に呼ばれます。hsz1とhsz2は、XTYP_REQUESTと同じようにトピック名とアイテム名が格納されています。DDE_FNOTPROCESSEDを返すようにします。サポートする場合はDdeAccessDataでデータを取得し、hsz2で識別されるアイテムにデータを設定してDDE_FACKを返します。SetDataの内部は次のようになっています。TRUE;}BM_SETCHECKは、チェックボックスの状態を変更する際に使用できます。falseの場合はチェックを外すBST_UNCHECKEDを指定します。(HDDEDATA)TRUE;XTYP_ADVSTARTは、DdeClientTransaction(XTYP_ADVSTART指定)を呼び出した場合や、WM_DDE_ADVISEをポストした場合に呼ばれます。hsz1とhsz2は、XTYP_POKEと同じようにトピック名とアイテム名が格納されています。クライアントへ通知することを意味します。ユーザーがクリックした場合は次のコードが実行されます。このような際にはDdePostAdviseを呼び出すようにします。すると、コールバック関数にXTYP_ADVREQが通知されます。GetData();hsz1とhsz2については、XTYP_ADVSTARTと同様です。戻り値は通知したいデータになるため、GetDataの戻り値をそのまま指定できます。今回のサーバーに対応するクライアントの例を示します。マウスの右ボタンが押された場合はチェックを付けるようにします。サーバー上でチェックの状態が変化した場合はそれを検出します。TEXT("DDE対話の確立に失敗しました。TEXT("データの変更が通知されました。(HDDEDATA)FALSE;}WM_CREATEではDdeConnectを呼び出して、サーバーとDDE対話を確立しようとしています。このときに指定するサービス名とトピック名は、今回のサーバーで定義していたものと同一になります。DdeClientTransactionにXTYP_ADVSTARTを指定しているのは、サーバーとのデータリンクを確立するためです。XTYPF_ACKREQを指定すれば変更されたデータそのものが通知されるホットリンクになります。ホットリンクの場合はDdeGetDataで変更後のデータを取得できます。マウスの左ボタンが押された場合は、DdeClientTransactionにXTYP_REQUESTを指定しています。この場合は戻り値としてデータのハンドルが返るため、それをDdeGetDataに指定します。マウスの右ボタンが押された場合は、DdeClientTransactionにXTYP_POKEを指定しています。この場合は、第1引数に渡したいデータを指定し、第2引数にデータのサイズを指定します。trueを指定していることから、サーバーのチェックボックスにチェックが付くことになります。