The WM_DDE_DATA Message

Following the WM_DDE_ADVISE messages, WndProc will receive WM_DDE_DATA messages from the server containing updated population data. The low word of lParam is a memory handle to a global block containing a WM_DDE_DATA structure, and the high word of lParam is the atom identifying the data item.

SHOWPOP checks if the cfFormat field of the DDEDATA structure is CF_TEXT. (Of course, we know that DDEPOP uses CF_TEXT exclusively, but this is just for the sake of completeness.) It then obtains the text string associated with the item atom by calling GlobalGetAtomName. This text string is the two-letter state abbreviation.

Using a for loop, SHOWPOP scans through the states looking for a match. If it finds one, it copies the population data from the DDEDATA structure into the szPopulation array, converts it to a long integer using the C function atol (”ASCII to long“), stores it in the pop structure, and invalidates the window.

All that remains now is cleaning up. If the client requested an acknowledgment of the WM_DDE_DATA message, WndProc posts one. If no acknowledgment was requested (or if the PostMessage call fails), then the item atom is deleted. If the PostMessage call fails, or if there was no match on the state (indicating a negative acknowledgment), or if the fRelease flag in the DDEDATA structure is set to TRUE, then SHOWPOP frees the memory block.

I originally wrote SHOWPOP so that it posted WM_DDE_ADVISE messages with the fAckReq field of the DDEADVISE structure set to FALSE. This indicates to the server that the WM_DDE_DATA messages should be posted with the fAckReq field of the DDEDATA structure set to FALSE, which in turn indicates to the client that it should not post WM- DDE_ACK messages to the server acknowledging the WM_DDE_DATA messages. This worked fine for normal updates. However, if I changed the system time in Windows while SHOWPOP was running, then DDEPOP posted 52 WM_DDE_DATA messages to SHOWPOP without waiting for acknowledgment. This caused SHOWPOP's message queue to overflow, and it lost many of the updated populations.

The lesson is clear: If a client wishes to be advised of many data items that can change all at once, then it must set the fAckReq field of the DDEADVISE structure to TRUE. This is the only safe approach.