Character Strings and Atoms

I've discussed how a DDE client and server identify data using three character strings_ the application, topic, and item. But in the actual messages between the client and server, these character strings do not appear: ”Atoms“ are used instead.

Atoms are WORD values that refer to character strings in a case-insensitive manner. You can use atoms within your own program for working with character strings, in which case the atom table (the table that references the atom values with the strings) is stored in your program's default data segment.

You define an atom as follows:

ATOM aAtom ;

You can add a string to the atom table using the function:

aAtom = AddAtom (lpString) ;

If the character string does not already exist in the atom table, this function adds it and returns a unique value identifying the string. Each atom has a ”reference count,“ which is the number of times AddAtom has been called for the same string. The reference count is initially set to 1. If the character string already exists in the atom table (that is, if this is the second or subsequent time that AddAtom has been called for the same string), the function returns the number identifying the character string and increments the reference count.

The function:

DeleteAtom (aAtom) ;

decrements the reference count. When the count is 0, the atom and character string are removed from the atom table.

The function:

aAtom = FindAtom (lpString) ;

will return the atom associated with the character string (or 0 if the string is not in the atom table). This function does not affect the reference count of the atom.

The function:

nBytes = GetAtomName (aAtom, lpBuffer, nBufferSize) ;

returns the character string for an atom. The last parameter indicates the size of the buffer pointed to by the second parameter. The function returns the number of bytes copied to the buffer and does not affect the reference count.

These four functions (there are several others of lesser importance) allow you to work with atoms within your own program. However, because the atom table is stored in your program's default data segment, the atoms are unique to your program. To use atoms with DDE, you must use another set of four functions, similar to the functions described above:

aAtom = GlobalAddAtom (lpString) ;

GlobalDeleteAtom (aAtom) ;

aAtom = GlobalFindAtom (lpString) ;

nBytes = GlobalGetAtomName (aAtom, lpBuffer, nBufferSize) ;

The atom table for these atoms is stored in a shared data segment in a dynamic link library within Windows and hence is common to all Windows programs. One program can use GlobalAddAtom to add a string to the atom table and pass the atom to another program. This other program can use GlobalGetAtomName to obtain the character string associated with the atom. This is how Windows programs identify the DDE application, topic, and item.

The rules regarding the use of atoms with DDE are described in the documentation of the DDE messages in Chapter 15 of the Microsoft Windows Programmer's Reference. These rules are extremely important: It is not good if an atom that is still required by one program is deleted from the atom table by another program. Neither is it good if atoms that are no longer required are not deleted from the atom table. For this reason, you must be careful about how your program handles atoms.

Atoms are used for the DDE application, topic, and item strings. The data structures that are transferred from one Windows program to another must be allocated using GlobalAlloc with the GMEM_DDESHARE option. This allows the global memory block to be shared among multiple Windows programs. The DDE rules that govern which program is responsible for allocating and freeing these global memory blocks are also quite strict.