DDE客户端的处理
客户对服务器发出的WM_DDE_DATA消息的响应主要完成对服务器提供数据项内容的提取。首先调用UnpackDDElParam()将消息参数lParam中包含的DDEDATA格式化内存块句柄和数据项原子标识值提取出来。在检验了数据格式的有效后,将共享内存块中的数据项内容读取出来:
UINT uLo, uHi; // lParam消息的低、高字 UnpackDDElParam(WM_DDE_DATA,lParam,&uLo,&uHi);//对lParam进行解包 HANDLE hDDEData = (HANDLE)uLo; // 取出DDEDATA句柄 ATOM atomItem = (ATOM)uHi; // 取出数据项原子标识值 DDEDATA* lpDDEData = (DDEDATA*)GlobalLock(hDDEData); // 锁定内存块 if (lpDDEData->cfFormat == CF_TEXT) { // 检验数据格式 // 报告服务器返回的数据项信息 CString sMessage = "服务器返回的数据项内容为:" + CString(lpDDEData->Value); AfxMessageBox(sMessage); } GlobalUnlock(hDDEData); // 内存解锁 |
与请求传送消息相比,客户也可以在没有请求的情况下通过向服务器传送WM_DDE_POKE消息实现对服务器的数据项传输,使用的消息参数lParam的高字为数据项原子标识值,低字为全局共享内存块的DDEPOKE结构句柄。从下面给出的向服务器窗口发送WM_DDE_POKE消息的代码段不难看出其与服务器使用WM_DDE_DATA消息发送数据的过程是非常类似的:
CString sDataItem = "Data from Client!"; // 发送的数据项内容 // 分配DDEPOKE格式化的全局共享内存块 HGLOBAL hDDEPoke = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (LONG)sizeof(DDEPOKE) + sDataItem.GetLength() + 2); DDEPOKE* lpDDEPoke = (DDEPOKE*)GlobalLock(hDDEPoke); // 锁定内存块地址 lpDDEPoke->cfFormat = CF_TEXT; // 设置格式字段 ::strcpy((LPSTR)lpDDEPoke->Value, sDataItem); // 填充数据项内容 ::strcat((LPSTR)lpDDEPoke->Value, "\r\n"); // 添加终结字符 GlobalUnlock(hDDEPoke); // 解锁内存块 ATOM atomItem = GlobalAddAtom("Item B"); // 获取数据项原子标识值 HWND hwndClient = GetSafeHwnd(); // 获取当前窗口的安全句柄 // 组合消息参数lParam LONG lDataPack = PackDDElParam(WM_DDE_POKE, (UINT)hDDEPoke, atomItem); // 向服务器窗口发送WM_DDE_POKE消息 ::PostMessage(m_hwndServer, WM_DDE_POKE, (WPARAM)hwndClient, (LPARAM)lDataPack); |
DDE服务器对数据的接收处理
服务器在响应WM_DDE_POKE消息后必须决定其是否能够接收客户发送来的格式数据。但不管服务器是否能够处理该数据都必须向客户发送一个WM_DDE_ACK消息作为应答,通过消息参数lParam的低字区分服务器是否成功接收数据:
UINT uLo, uHi; // lParam消息的低、高字 UnpackDDElParam(WM_DDE_DATA, lParam, &uLo, &uHi); // 对lParam进行解包 HANDLE hDDEPoke = (HANDLE)uLo; // 取出DDEPOKE句柄 ATOM atomItem = (ATOM)uHi; // 取出数据项原子标识值 DDEPOKE* lpDDEPoke = (DDEPOKE*)GlobalLock(hDDEPoke); // 锁定内存块 if (lpDDEPoke == NULL) { // 组合消息参数lParam LONG lDataPack = PackDDElParam(WM_DDE_ACK, (UINT)0, atomItem); // 向客户发送否定应答 ::PostMessage((HWND)wParam, WM_DDE_ACK, (WPARAM)m_hwndServer, (LPARAM)lDataPack); return; } if (lpDDEPoke->cfFormat == CF_TEXT) { // 检验数据格式 // 报告服务器返回的数据项信息 CString sMessage = "客户发来数据:" + CString(lpDDEPoke->Value); AfxMessageBox(sMessage); } else { // 组合消息参数lParam LONG lDataPack = PackDDElParam(WM_DDE_ACK, (UINT)0, atomItem); // 向客户发送否定应答 ::PostMessage((HWND)wParam, WM_DDE_ACK, (WPARAM)m_hwndServer, (LPARAM)lDataPack); GlobalUnlock(hDDEPoke); // 内存解锁 return; } GlobalUnlock(hDDEPoke); // 内存解锁 // 组合消息参数lParam LONG lDataPack = PackDDElParam(WM_DDE_ACK, (UINT)0x8000, atomItem); ::PostMessage((HWND)wParam, WM_DDE_ACK, (WPARAM)m_hwndServer, (LPARAM)lDataPack); // 向客户发送肯定应答 |
小结
本文主要探讨了动态数据交换技术中的数据传送处理的具体实现过程,并给出了各主要环节的相关实现代码。本文所述代码在Windows 2000 Professional下由Microsoft Visual C++(www.cppentry.com) 6.0编译通过。 |