22.4.1 Initiating a Conversation

To initiate a DDE conversation, the client sends a WM_DDE_INITIATE message. Usually, the client broadcasts this message by calling the SendMessage function, with –1 as the first parameter. If the application already has the window handle of the server application, however, it can send the message directly to that window. The client prepares atoms for the application and topic names by calling the GlobalAddAtom function. The client may request conversations with any potential server application and for any potential topic by supplying NULL (wildcard) atoms for, respectively, the application and topic.

The following example illustrates how the client initiates a conversation, where both the application and topic are specified:

atomApplication = *szApplication == 0 ?
    NULL : GlobalAddAtom((LPSTR)szApplication);
atomTopic = *szTopic == 0 ?
    NULL : GlobalAddAtom((LPSTR)szTopic);

fInInitiate = TRUE;
SendMessage(-1,
    WM_DDE_INITIATE,
    hwndClientDDE,
    MAKELONG(atomApplication, atomTopic));
fInInitiate = FALSE;
if (atomApplication != NULL)
    GlobalDeleteAtom(atomApplication);
if (atomTopic != NULL)
    GlobalDeleteAtom(atomTopic);

Note that if your application uses NULL atoms, you need not use the GlobalAddAtom and GlobalDeleteAtom functions. In this example, the client application creates two global atoms containing the name of the server and the name of the topic, respectively.

The client application sends a WM_DDE_INITIATE message with these two atoms in the lParam parameter of the message. The special window handle –1 in the call to the SendMessage function directs Windows to send this message to all other active applications. SendMessage does not return to the client application until all applications that receive the message have, in turn, returned control to Windows. This means that all WM_DDE_ACK messages sent in reply by the server applications are guaranteed to have been processed by the client by the time the SendMessage call has returned.

After SendMessage returns, the client application deletes the global atoms.

Server applications respond according to the following logic:

To acknowledge one or more topics, the server must create atoms for each conversation (requiring duplicate application-name atoms if there are multiple topics) and send a WM_DDE_ACK message for each conversation, as follows:

if ((atomApplication = GlobalAddAtom("Server")) != 0) {
    if ((atomTopic = GlobalAddAtom(szTopic)) != 0) {
        SendMessage(hwndClientDDE,
            WM_DDE_ACK,
            hwndServerDDE,
            MAKELONG(atomApplication, atomTopic));
        GlobalDeleteAtom(atomApplication);
    }
    GlobalDeleteAtom(atomTopic);
}

if ((atomApplication == 0) || (atomTopic == 0)) {
     .
     . /* error handling */
     .

}

When a server responds with a WM_DDE_ACK message, the client application should save the handle of the server window. The client application receives this handle as the wParam parameter of the WM_DDE_ACK message. The client application then sends all subsequent DDE messages to the server window identified by this handle.

If your client application uses NULL atoms for the application or topic, you should expect that it will receive acknowledgments from more than one server application. As stated in Section 22.2.1, “Client, Server, and Conversation,” creating a unique, hidden window for each DDE conversation ensures that a pair of client and server windows is never involved in more than one conversation. To follow this practice, however, the client application must terminate conversations with all but one of the server applications that respond to the same WM_DDE_INITIATE message from the client.