下载本文示例代码
永久数据链路概述 在建立了DDE对话后,客户应用程序能够创建与服务器相连的一条或多条永久数据链路。在一个给定的数据项值被改变时,由服务器通过此数据链路向客户报告,该链路直到链路或DDE对话终止时才会被撤消。对于没有建立任何永久性数据链路的条件下客户只能对一个项目的值查询一次。这种永久性数据链路可以分为热数据链路与温数据链路两种。通过热数据链路,服务器可以在数据发生改变时立即将改动结果传送给客户;对于温数据链路,服务器仅仅是通知客户数据发生了改变,由客户决定是否传递和何时传递新值。 永久数据链路的建立 与永久数据链路相对的是一种被称为冷数据链路的临时数据链路,客户并不知道其要访问的数据何时发生变化,因此不能及时请求传送。通过建立永久数据链路可以较好的解决这个问题。在该链路保持有效时,服务器能够定期传送给客户应用程序更新后的资料。每一个目标数据的改变,服务器都要通知客户。该通知可以建立在热的或温的数据链路上。该数据链路将一直存在,直到客户发出撤消请求。 客户窗口邮寄出一条WM_DDE_ADVISE消息给服务器窗口,要求建立数据项的永久链接,服务器通过传送WM_DDE_ACK消息作出肯定或否定应答(由消息参数lParam的低字指定)。在成功建立永久链路后,一旦数据有变,服务器将有责任向客户发出WM_DDE_DATA消息通知。伴随消息WM_DDE_ADVISE的全局共享内存块数据结构为DDEADVISE,若其fDeferUpd成员为FALSE,数据变化时服务器将把更新后的数据放置于DDEDATA结构中,再通过消息WM_DDE_DATA传送给客户,由此建立的链路也就是热数据链路。如果fDeferUpd为TRUE,则在数据变化时只是简单的把一个空(NULL)数据装入DDEDATA结构,并用WM_DDE_DATA通知客户数据已更新。如客户对更新后的数据感兴趣,还要向服务器发送WM_DDE_REQUEST消息去请求。由这种方式所建立的数据链路是温数据链路。建立一个永久链路所要发出的消息流程如图1所示:
图1 永久数据链路的建立与撤消 下面给出客户向服务器窗口邮寄WM_DDE_ADVISE消息的实现代码:
HGLOBAL hOptions = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(DDEADVISE)); // 分配内存块DDEADVISE* lpOptions = (DDEADVISE*)GlobalLock(hOptions); // 锁定内存lpOptions->cfFormat = CF_TEXT; // 格式设置lpOptions->fAckReq = TRUE; // 需要服务器应答lpOptions->fDeferUpd = FALSE; // FALSE为热链接,TRUE为温链接GlobalUnlock(hOptions); // 解锁内存ATOM atomItem = GlobalAddAtom("Item C"); // 得到数据项原子标识值HWND hwndClient = GetSafeHwnd(); // 获取当前窗口的安全句柄// 组合消息参数lParamLONG lDataPack = PackDDElParam(WM_DDE_ADVISE, (UINT)hOptions, atomItem);::PostMessage(m_hwndServer, WM_DDE_ADVISE, (WPARAM)hwndClient, (LPARAM)lDataPack); // 向服务器发送WM_DDE_ADVISE消息 虽然DDE协议规定在客户和服务器之间建立好永久链路后每当数据发生变化,服务器都有责任通知客户或直接将数据传送给客户。但是这一协议的执行却是通过对服务器程序的逻辑设计来体现的。通常的做法是,在创建服务器窗口时为其设置一个私有的数据结构,对应其所提供的数据项。在本例中定义的数据结构为:
typedef struct{ // ddeadv UINT fAdvise:1, // 开通数据链路 fDeferUpd:1, // 推迟更新 fAckReq:1, // 要求应答 dummy:13; LONG lPrev; // 数据项原项} SERVERADVISE; 在处理WM_DDE_ADVISE消息时首先检查是否有数据项可供建立永久链接,如果不能建立则要向客户返回WM_DDE_ACK的失败应答,否则返回成功应答。在数据链路建立完毕后,每当服务器窗口访问数据项,都要利用私有数据结构SERVERADVISE对数据项是否发生变换进行检测,并以此来决定是否邮寄WM_DDE_DATA消息给客户。下面给出服务器窗口对WM_DDE_ADVISE消息的响应处理代码:
CString sCurrentValue = "Value1"; // 当前数据值UINT uLo, uHi; // lParam消息的低、高字char szItemNameClient[255]; // 客户发来的数据项名UnpackDDElParam(WM_DDE_ADVISE, lParam, &uLo, &uHi); // 对lParam进行解包// 取客户请求的数据项名GlobalGetAtomName(uHi, szItemNameClient, sizeof(szItemNameClient));if (CString(szItemNameClient) != "Item C"){ // 判断是否可建立链接 AfxMessageBox("永久链路无法建立!"); // 反馈信息 // 组合消息参数lParam LONG lDataPack = PackDDElParam(WM_DDE_ACK, (UINT)0, HIWORD(lParam)); ::PostMessage((HWND)wParam, WM_DDE_ACK, (WPARAM)m_hwndServer, (LPARAM)lDataPack); // 向客户发送否定应答 return;}// 锁定内存DDEADVISE* lpDDEAdvise = (DDEADVISE*)GlobalLock((HGLOBAL)uLo);// 锁定内存SERVERADVISE* lpServerAdvise = (SERVERADVISE*)GlobalLock(m_hServerAdvise);lpServerAdvise->fAdvise = TRUE; // 数据项建立连接lpServerAdvise->fDeferUpd = lpDDEAdvise->fDeferUpd; // 推迟更新lpServerAdvise->fAckReq = lpDDEAdvise->fAckReq; // 要求应答lpServerAdvise->lPrev = (LONG)&sCurrentValue; // 数据项原值GlobalUnlock(m_hServerAdvise); // 解锁内存m_bHaveALink = TRUE; // 设立建立永久链接的标志AfxMessageBox("成功建立永久链路!"); // 反馈信息LONG lDataPack = PackDDElParam(WM_DDE_ACK, (UINT)0x8000, HIWORD(lParam)); // 组合消息参数lParam::PostMessage((HWND)wParam, WM_DDE_ACK, (WPARAM)m_hwndServer, (LPARAM)lDataPack); // 向客户发送肯定应答共2页。 1 2 :
永久数据链路概述 在建立了DDE对话后,客户应用程序能够创建与服务器相连的一条或多条永久数据链路。在一个给定的数据项值被改变时,由服务器通过此数据链路向客户报告,该链路直到链路或DDE对话终止时才会被撤消。对于没有建立任何永久性数据链路的条件下客户只能对一个项目的值查询一次。这种永久性数据链路可以分为热数据链路与温数据链路两种。通过热数据链路,服务器可以在数据发生改变时立即将改动结果传送给客户;对于温数据链路,服务器仅仅是通知客户数据发生了改变,由客户决定是否传递和何时传递新值。 永久数据链路的建立 与永久数据链路相对的是一种被称为冷数据链路的临时数据链路,客户并不知道其要访问的数据何时发生变化,因此不能及时请求传送。通过建立永久数据链路可以较好的解决这个问题。在该链路保持有效时,服务器能够定期传送给客户应用程序更新后的资料。每一个目标数据的改变,服务器都要通知客户。该通知可以建立在热的或温的数据链路上。该数据链路将一直存在,直到客户发出撤消请求。 客户窗口邮寄出一条WM_DDE_ADVISE消息给服务器窗口,要求建立数据项的永久链接,服务器通过传送WM_DDE_ACK消息作出肯定或否定应答(由消息参数lParam的低字指定)。在成功建立永久链路后,一旦数据有变,服务器将有责任向客户发出WM_DDE_DATA消息通知。伴随消息WM_DDE_ADVISE的全局共享内存块数据结构为DDEADVISE,若其fDeferUpd成员为FALSE,数据变化时服务器将把更新后的数据放置于DDEDATA结构中,再通过消息WM_DDE_DATA传送给客户,由此建立的链路也就是热数据链路。如果fDeferUpd为TRUE,则在数据变化时只是简单的把一个空(NULL)数据装入DDEDATA结构,并用WM_DDE_DATA通知客户数据已更新。如客户对更新后的数据感兴趣,还要向服务器发送WM_DDE_REQUEST消息去请求。由这种方式所建立的数据链路是温数据链路。建立一个永久链路所要发出的消息流程如图1所示:
图1 永久数据链路的建立与撤消 下面给出客户向服务器窗口邮寄WM_DDE_ADVISE消息的实现代码:
HGLOBAL hOptions = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(DDEADVISE)); // 分配内存块DDEADVISE* lpOptions = (DDEADVISE*)GlobalLock(hOptions); // 锁定内存lpOptions->cfFormat = CF_TEXT; // 格式设置lpOptions->fAckReq = TRUE; // 需要服务器应答lpOptions->fDeferUpd = FALSE; // FALSE为热链接,TRUE为温链接GlobalUnlock(hOptions); // 解锁内存ATOM atomItem = GlobalAddAtom("Item C"); // 得到数据项原子标识值HWND hwndClient = GetSafeHwnd(); // 获取当前窗口的安全句柄// 组合消息参数lParamLONG lDataPack = PackDDElParam(WM_DDE_ADVISE, (UINT)hOptions, atomItem);::PostMessage(m_hwndServer, WM_DDE_ADVISE, (WPARAM)hwndClient, (LPARAM)lDataPack); // 向服务器发送WM_DDE_ADVISE消息 虽然DDE协议规定在客户和服务器之间建立好永久链路后每当数据发生变化,服务器都有责任通知客户或直接将数据传送给客户。但是这一协议的执行却是通过对服务器程序的逻辑设计来体现的。通常的做法是,在创建服务器窗口时为其设置一个私有的数据结构,对应其所提供的数据项。在本例中定义的数据结构为:
typedef struct{ // ddeadv UINT fAdvise:1, // 开通数据链路 fDeferUpd:1, // 推迟更新 fAckReq:1, // 要求应答 dummy:13; LONG lPrev; // 数据项原项} SERVERADVISE; 在处理WM_DDE_ADVISE消息时首先检查是否有数据项可供建立永久链接,如果不能建立则要向客户返回WM_DDE_ACK的失败应答,否则返回成功应答。在数据链路建立完毕后,每当服务器窗口访问数据项,都要利用私有数据结构SERVERADVISE对数据项是否发生变换进行检测,并以此来决定是否邮寄WM_DDE_DATA消息给客户。下面给出服务器窗口对WM_DDE_ADVISE消息的响应处理代码:
CString sCurrentValue = "Value1"; // 当前数据值UINT uLo, uHi; // lParam消息的低、高字char szItemNameClient[255]; // 客户发来的数据项名UnpackDDElParam(WM_DDE_ADVISE, lParam, &uLo, &uHi); // 对lParam进行解包// 取客户请求的数据项名GlobalGetAtomName(uHi, szItemNameClient, sizeof(szItemNameClient));if (CString(szItemNameClient) != "Item C"){ // 判断是否可建立链接 AfxMessageBox("永久链路无法建立!"); // 反馈信息 // 组合消息参数lParam LONG lDataPack = PackDDElParam(WM_DDE_ACK, (UINT)0, HIWORD(lParam)); ::PostMessage((HWND)wParam, WM_DDE_ACK, (WPARAM)m_hwndServer, (LPARAM)lDataPack); // 向客户发送否定应答 return;}// 锁定内存DDEADVISE* lpDDEAdvise = (DDEADVISE*)GlobalLock((HGLOBAL)uLo);// 锁定内存SERVERADVISE* lpServerAdvise = (SERVERADVISE*)GlobalLock(m_hServerAdvise);lpServerAdvise->fAdvise = TRUE; // 数据项建立连接lpServerAdvise->fDeferUpd = lpDDEAdvise->fDeferUpd; // 推迟更新lpServerAdvise->fAckReq = lpDDEAdvise->fAckReq; // 要求应答lpServerAdvise->lPrev = (LONG)&sCurrentValue; // 数据项原值GlobalUnlock(m_hServerAdvise); // 解锁内存m_bHaveALink = TRUE; // 设立建立永久链接的标志AfxMessageBox("成功建立永久链路!"); // 反馈信息LONG lDataPack = PackDDElParam(WM_DDE_ACK, (UINT)0x8000, HIWORD(lParam)); // 组合消息参数lParam::PostMessage((HWND)wParam, WM_DDE_ACK, (WPARAM)m_hwndServer, (LPARAM)lDataPack); // 向客户发送肯定应答共2页。 1 2 :
下载本文示例代码
VC下动态数据交换技术之永久数据链路VC下动态数据交换技术之永久数据链路VC下动态数据交换技术之永久数据链路VC下动态数据交换技术之永久数据链路VC下动态数据交换技术之永久数据链路VC下动态数据交换技术之永久数据链路VC下动态数据交换技术之永久数据链路VC下动态数据交换技术之永久数据链路VC下动态数据交换技术之永久数据链路VC下动态数据交换技术之永久数据链路VC下动态数据交换技术之永久数据链路VC下动态数据交换技术之永久数据链路VC下动态数据交换技术之永久数据链路VC下动态数据交换技术之永久数据链路VC下动态数据交换技术之永久数据链路