要从服务器检索项目,客户端将向服务器发送一条WM_DDE_REQUEST消息,指定要检索的项目和格式,如以下示例所示。
if ((atomItem = GlobalAddAtom(szItemName)) != 0) {
if(!PostMessage(hwndServerDDE,
WM_DDE_REQUEST,
(WPARAM)hwndClientDDE,
PackDDElParam(WM_DDE_REQUEST,CF_TEXT,atomItem)))
GlobalDeleteAtom(atomItem);
}
if (atomItem == 0) {
.
./ *错误处理* /
.
}
在此示例中,客户端将剪贴板格式CF_TEXT指定为所请求数据项的首选格式。
WM_DDE_REQUEST消息的接收方(服务器)通常必须删除项目原子,但如果PostMessage调用失败,客户端必须删除该原子。
如果服务器可以访问所请求的项目并且可以以请求的格式呈现它,则服务器将项目值复制为共享内存对象,并向客户端发送WM_DDE_DATA消息,如以下示例所示。
/*
*分配DDE数据头的大小,加上数据:a
* string,< CR > < LF > < NULL >.字符串终止的字节
*空字符由DDEDATA.Value [1]计算。
*/
if (!(hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
(LONG)sizeof(DDEDATA)+ lstrlen(szItemValue)+ 2)))
return;
if (!(lpData = (DDEDATA FAR*) GlobalLock(hData))) {
GlobalFree(hData);
return;
}
.
.
.
lpData->cfFormat = CF_TEXT;
lstrcpy((LPSTR) lpData->Value, (LPSTR) szItemValue);
/ * CF_TEXT数据的每一行都由CR / LF终止。*/
lstrcat((LPSTR) lpData->Value, (LPSTR) "\r\n");
GlobalUnlock(hData);
if ((atomItem = GlobalAddAtom((LPSTR) szItemName)) != 0) {
lParam = PackDDElParam(WM_DDE_ACK, (UINT) hData, atomItem);
if(!PostMessage(hwndClientDDE,
WM_DDE_DATA,
(WPARAM)hwndServerDDE,
lParam)){
GlobalFree(hData);
GlobalDeleteAtom(atomItem);
FreeDDElParam(WM_DDE_ACK, lParam);
}
}
if (atomItem == 0) {
.
./ *错误处理* /
.
}
在这个例子中,服务器应用程序分配一个内存对象来包含数据项。内存分配了GMEM_DDESHARE选项,以便服务器和客户端应用程序可以共享内存。分配内存对象后,服务器应用程序锁定对象,以便可以获取对象的地址。数据对象初始化为DDEDATA结构。
然后,服务器应用程序将结构的cfFormat成员设置为CF_TEXT以通知客户端应用程序数据是文本格式。客户端通过将请求的数据的值复制到DDEDATA结构的值成员中进行响应。在服务器填充数据对象后,服务器解锁数据并创建一个包含数据项名称的全局原子。
最后,服务器通过调用PostMessage发出WM_DDE_DATA消息。数据对象的句柄和包含项目名称的原子由PackDDElParam函数打包到消息的【lParam的】参数中。
如果PostMessage失败,服务器必须使用FreeDDElParam功能来释放打包的【lParam的】参数。服务器还必须为收到的WM_DDE_REQUEST消息释放包装的【lParam的】参数。
如果服务器不能满足请求,则向客户端发送否定消息(989796102),如下例所示。
/ *否定确认* /
PostMessage(hwndClientDDE,
WM_DDE_ACK,
(WPARAM)hwndServerDDE,
PackDDElParam(WM_DDE_ACK, 0, atomItem));
收到WM_DDE_DATA消息后,客户端会根据需要处理数据项。然后,如果WM_DDE_DATA消息中指向的fAckReq成员为1,则客户端必须向服务器发送肯定的WM_DDE_ACK消息,如以下示例所示。
UnpackDDElParam(WM_DDE_DATA,lParam,(PUINT)& hData,
(PUINT) &atomItem);
if (!(lpDDEData = (DDEDATA FAR*) GlobalLock(hData))
|| (lpDDEData->cfFormat != CF_TEXT)) {
PostMessage(hwndServerDDE,
WM_DDE_ACK,
(WPARAM)hwndClientDDE,
PackDDElParam(WM_DDE_ACK, 0, atomItem)); /* negative ACK */
}
/ *将数据从lpDDEData复制到这里* /
if(lpDDEData- > fAckReq){
PostMessage(hwndServerDDE,
WM_DDE_ACK,
(WPARAM)hwndClientDDE,
PackDDElParam(WM_DDE_ACK,为0x8000,
atomItem)); /* positive ACK */
}
bRelease = lpDDEData->fRelease;
GlobalUnlock(hData);
如果(bRelease)
GlobalFree(hData);
在这个例子中,客户端检查数据的格式。如果格式不是CF_TEXT(或者如果客户端无法锁定数据的内存),则客户端发送否定WM_DDE_ACK消息,以指示它无法处理数据。如果客户端无法锁定数据句柄,因为句柄包含fAckReq成员,客户端不应发送负WM_DDE_ACK消息。相反,客户端应该终止对话。
如果客户端响应WM_DDE_DATA消息发送否定确认,则服务器负责释放与否定确认关联的WM_DDE_DATA消息引用的内存(但不是【lParam的】参数)。
如果可以处理数据,客户端将检查DDEDATA结构的fAckReq成员,以确定服务器是否要求通知客户端已成功接收和处理数据。如果服务器确实请求了该信息,客户端会向服务器发送一个正的WM_DDE_ACK消息。
因为解锁数据会使指向数据的指针无效,客户端会在解锁数据对象之前保存fRelease成员的值。保存该值后,客户端将检查它以确定服务器应用程序是否请求客户端释放包含数据的内存;客户行为相应。
收到否定的WM_DDE_ACK消息后,客户端可以再次请求相同的项目值,指定不同的剪贴板格式。通常,客户端将首先要求可以支持的最复杂的格式,然后根据需要逐步降低格式,直到找到服务器可以提供的格式。
如果服务器支持系统主题的“格式”项,客户端可以确定一旦服务器支持哪种剪贴板格式,而不是每次客户端请求一个项目时确定它们。有关系统主题的更多信息,请参阅系统主题.