科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件VC下动态数据交换技术之永久数据链路

VC下动态数据交换技术之永久数据链路

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文对动态数据交换技术中的永久数据链路的建立和撤消处理方法作了较为详细的介绍,并给出了具体实现代码。

作者:青岛郎锐 来源:天极网 2007年10月19日

关键字: VC 数据交换 数据链路

  • 评论
  • 分享微博
  • 分享邮件
永久数据链路概述

  在建立了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(); // 获取当前窗口的安全句柄
// 组合消息参数lParam
LONG 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); // 向客户发送肯定应答
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章