DDE Hints and Guidelines
Keep the following in mind to avoid the most common problems when working with DDE, especially if you don't use the framework:
- If you want to put a string into a DDE data handle by using DDEDataOut::SetData or DdeCreateDataHandle, remember to pass its length plus one to make room for the zero terminator. You can also use DDEDataOut::SetString, which does it automatically.
- When you receive data from DDE, don't count on the data size you get from DDEDataIn::GetSize or DdeAccessData as being the exact size. The size these functions return might be larger than the actual data size . If you need to know the exact size, pass it as part of the transaction data.
- When using NetDDE, for some strange reason the client connection will temporarily succeed even if the remote server did not respond. If the server has not responded, this seemingly successful connection will soon be followed by an XTYP_DISCONNECT transaction. If you want to be sure your connection succeeded right after the call to DdeConnect, make a synchronous transaction and check the error code. My DDE framework does this automatically.
- When using NetDDE with Windows 95, remember to start the NETDDE.EXE support application, which is not started by default. The framework starts it automatically.
- If you need to do lengthy processing or start synchronous transactions from within your DDECallback, rather store the data received, post a message to some of your windows, return from the function, and let the Windows message handler process the data later.
- If you use DDE to do some polling requests, make sure no previous polling request is waiting to complete before starting a new request; otherwise wait until the next timer message, so that transactions are not started faster than they can complete. The framework provides two functions for testing if some transaction is waiting to complete: SynchBusy and AsynchBusy.
- Remember that calling a synchronous transaction causes a separate message loop to process Windows messages while the transaction is waiting to complete, so other parts of your code can execute. Make sure these parts don't start other synchronous transactions or you'll get a reentrancy error. (You can use the framework's SynchBusy function to test this situation.)
- If you start an advise link on an item, the server will notify you when the item changes. Usually you also need the current value of the item. You'll need to make a Request on that item first.
- Don't count on the DDECallback not being called after you have called DdeUninitialize.
- Use the Windows API function IsBadReadPtr to test the data pointer you get from DdeAccessData. It has happened that accessing data through that pointer (which was not NULL) caused a crash. The framework does this test and uses Windows ASSERTs.
- Prefer asynchronous transactions if possible; they seem more efficient and give less problems (like reentrancy). It is also safe to mix synchronous and asynchronous transactions.
- Don't try to create string handles longer than 255 characters. o