完善MS官网上DDE的例子

首先是引用的文章: http://support.microsoft.com/kb/279721/zh-cn
—————————————————————————————————————————————————————————————————
本文介绍了如何在 Visual C++ 中使用动态数据交换 (DDE),与 Excel 和 Word 进行通信。

注意: 如果可能,建议使用自动化,不 DDE,与 Excel 或 Word 进行通信。Excel 和 Word 具有丰富的对象模型提供了通过使用 DDE 不可用的自动化功能。5.0 及更高版本的 Excel 版本和版本 7.0 及更高版本的 Word 支持自动化。
DDE 客户示例
下面的示例使用 Excel 工作簿或 Word 文档的 DDE 主题。

对于 Excel,创建一个新工作簿 (C:\Test.xls),其中包含在单元格 A1 和 A2 中的数据。对于 Word,请创建包含文本的新文档 (C:\Test.doc)。选择文档中的文本的部分但非全部) 并创建一个名为"在"在该位置的书签。
    1. 在 Visual C++,将创建一个新的 Win32 控制台应用程序名为"DDEClient"。
    2. 在应用程序向导,选择简单的应用程序,然后单击完成
DDEClient.cpp 中的代码替换为以下:
#include "stdafx.h"
#include "windows.h"
#include "ddeml.h"
#include "stdio.h"

HDDEDATA CALLBACK DdeCallback(
    UINT uType,     // Transaction type.
    UINT uFmt,      // Clipboard data format.
    HCONV hconv,    // Handle to the conversation.
    HSZ hsz1,       // Handle to a string.
    HSZ hsz2,       // Handle to a string.
    HDDEDATA hdata, // Handle to a global memory object.
    DWORD dwData1,  // Transaction-specific data.
    DWORD dwData2)  // Transaction-specific data.
{
    return 0;
}

void DDEExecute(DWORD idInst, HCONV hConv, char* szCommand)
{
    HDDEDATA hData = DdeCreateDataHandle(idInst, (LPBYTE)szCommand,
                               lstrlen(szCommand)+1, 0, NULL, CF_TEXT, 0);
    if (hData==NULL)   {
        printf("Command failed: %s\n", szCommand);
    }
    else    {
        DdeClientTransaction((LPBYTE)hData, 0xFFFFFFFF, hConv, 0L, 0,
                             XTYP_EXECUTE, TIMEOUT_ASYNC, NULL);
    }
}

void DDERequest(DWORD idInst, HCONV hConv, char* szItem, char* sDesc)
{
    HSZ hszItem = DdeCreateStringHandle(idInst, szItem, 0);
    HDDEDATA hData = DdeClientTransaction(NULL,0,hConv,hszItem,CF_TEXT, 
                                 XTYP_REQUEST,5000 , NULL);
    if (hData==NULL)
    {
        printf("Request failed: %s\n", szItem);
    }
    else
    {
        char szResult[255];
        DdeGetData(hData, (unsigned char *)szResult, 255, 0);
        printf("%s%s\n", sDesc, szResult);
    }
}

void DDEPoke(DWORD idInst, HCONV hConv, char* szItem, char* szData)
{
    HSZ hszItem = DdeCreateStringHandle(idInst, szItem, 0);
	DdeClientTransaction((LPBYTE)szData, (DWORD)(lstrlen(szData)+1),
                          hConv, hszItem, CF_TEXT,
                          XTYP_POKE, 3000, NULL);
    DdeFreeStringHandle(idInst, hszItem);
}

int main(int argc, char* argv[])
{
    char szApp[] = "EXCEL";
    char szTopic[] = "C:\\Test.xls";
    char szCmd1[] = "[APP.MINIMIZE()]";
    char szItem1[] = "R1C1";  char szDesc1[] = "A1 Contains: ";
    char szItem2[] = "R2C1";  char szDesc2[] = "A2 Contains: ";
    char szItem3[] = "R3C1";  char szData3[] = "Data from DDE Client";
    char szCmd2[] = "[SELECT(\"R3C1\")][FONT.PROPERTIES(,\"Bold\")][SAVE()][QUIT()]";

    //DDE Initialization
    DWORD idInst=0;
    UINT iReturn;
    iReturn = DdeInitialize(&idInst, (PFNCALLBACK)DdeCallback, 
                            APPCLASS_STANDARD | APPCMD_CLIENTONLY, 0 );
    if (iReturn!=DMLERR_NO_ERROR)
    {
        printf("DDE Initialization Failed: 0x%04x\n", iReturn);
        Sleep(1500);
        return 0;
    }

    //Start DDE Server and wait for it to become idle.
    HINSTANCE hRet = ShellExecute(0, "open", szTopic, 0, 0, SW_SHOWNORMAL);
    if ((int)hRet < 33)
    {
        printf("Unable to Start DDE Server: 0x%04x\n", hRet);
        Sleep(1500); DdeUninitialize(idInst);
        return 0;
    }
    Sleep(1000);

    //DDE Connect to Server using given AppName and topic.
    HSZ hszApp, hszTopic;
    HCONV hConv;
    hszApp = DdeCreateStringHandle(idInst, szApp, 0);
    hszTopic = DdeCreateStringHandle(idInst, szTopic, 0);
    hConv = DdeConnect(idInst, hszApp, hszTopic, NULL);
    DdeFreeStringHandle(idInst, hszApp);
    DdeFreeStringHandle(idInst, hszTopic);
    if (hConv == NULL)
    {
        printf("DDE Connection Failed.\n");
        Sleep(1500); DdeUninitialize(idInst);
        return 0;
    }

    //Execute commands/requests specific to the DDE Server.
    DDEExecute(idInst, hConv, szCmd1);
    DDERequest(idInst, hConv, szItem1, szDesc1); 
    DDERequest(idInst, hConv, szItem2, szDesc2);
    DDEPoke(idInst, hConv, szItem3, szData3);
    DDEExecute(idInst, hConv, szCmd2);

    //DDE Disconnect and Uninitialize.
    DdeDisconnect(hConv);
    DdeUninitialize(idInst);

    Sleep(3000);
    return 1;
}
					
对于 Word,请用以下内容替换main函数中的前 7 行:
    char szApp[] = "WINWORD";
    char szTopic[] = "C:\\test.doc";
    char szCmd1[] = "[AppMinimize][EditGoTo Destination:=\"\\EndofDoc\"][InsertPara]";
    char szItem1[] = "\\Doc";      char szDesc1[] = "Document contains: \n";
    char szItem2[] = "MyBookmark"; char szDesc2[] = "MyBookmark contains: \n";
    char szItem3[] = "\\EndofDoc"; char szData3[] = "Data from DDE Client";
    char szCmd2[] = "[FileSave][FileExit(2)]";
					
生成并运行该应用程序。
使用 Excel,DDE 客户端初始化 DDE 对话 (C:\Test.xls) 的工作簿文件中使用的主题,并执行下列操作:执行该应用程序。
R1C1 和 R2C1 项中的数据的请求。
Pokes 到 R3C1 的数据。
将 R3C1 格式设置为粗体、 保存该工作簿,然后退出 Excel。
使用 Word,DDE 客户端启动文档文件 (C:\Test.doc) 使用该主题的 DDE 对话并执行下列操作:

执行命令,以最小化应用程序,转到文档的末尾插入一个新段落。
请求的项"\Doc"来检索整个文档的内容。
请求的项目"在"以检索在书签中的文本。
执行命令,以将该文档保存并退出 Word。

—————————————————————————————————————————————————————————————————
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    网上找的很多例子也与这个类似,这个例子很好的教大家怎么使用DDE与Excel进行交互,但我在用这个例子大量的读取excel表格时,运行一段时间程序都读异常了,读到表格的内容不正确。

    经过认真观察测试发现,在多次读excel表格的过程中,程序内存也有累计增长(一到两兆)。多种测试后,想到了在调用 DDERequest时加上计数器,结果发现调用到16384(0x4000,或2^14)次之后就出错,改变excel格式,表格中的内容的长短,都在达到这个次数后就报错。于是猜到可能是哪里没有释放,或dde的限制,并查看ddl的相关函数,从网上找用法,最终定位到了DdeFreeDataHandle这个函数(也尝试了DdeFreeStringHandle,但在这里没效果)。

   修改后的DDERequest函数如下:

void DDERequest(DWORD idInst, HCONV hConv, char* szItem, char* sDesc)
{
    HSZ hszItem = DdeCreateStringHandle(idInst, szItem, 0);
    HDDEDATA hData = DdeClientTransaction(NULL,0,hConv,hszItem,CF_TEXT, 
                                 XTYP_REQUEST,5000 , NULL);
    if (hData==NULL)
    {
        printf("Request failed: %s\n", szItem);
    }
    else
    {
        char szResult[255];
        DdeGetData(hData, (unsigned char *)szResult, 255, 0);
        printf("%s%s\n", sDesc, szResult);
    }
	
	//改进,增加的两行
	DdeFreeStringHandle(idInst,hszItem);
	DdeFreeDataHandle(hData); //关键
}


参考:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms648752(v=vs.85).aspx
http://publib.boulder.ibm.com/infocenter/cmod/v7r1m1/index.jsp?topic=%2Fcom.ibm.ondemand.doc%2Fars5u271262.htm
由ibm网站中的例子调用 DdeUnaccessData释放想到,才联想和找到 DdeFreeDataHandle。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

piaopiaolanghua

感谢鼓励,再接再厉!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值