DDE是进程间通讯(InterProcess Communication,IPC)的方法。进程间通讯(IPC)包括进程之间和同步事件之间的数据传递。DDE使用共享内存来实现进程之间的数据交换以及使用DDE协议获得传递数据的同步。DDE协议是一组所有的DDE应用程序都必须遵循的规则集。
使用DDE通讯需要两个Windows应用程序,其中一个作为服务器处理信息,另外一个作为客户机从服务器获得信息。客户机应用程序向当前所激活的服务器应用程序发送一条消息请求信息,服务器应用程序根据该信息作出应答,从而实现两个程序之间的数据交换。
DDE会话发生在客户应用程序和服务器应用程序之间。
客户应用程序从服务器应用程序请求数据或服务,服务器应用程序响应客户应用程序的数据或服务请求。
DDE应用程序采用三层识别系统:应用程序名(Application)、主题名(Topic)和项目名(Item)。
应用程序族宏名位于层次结构的顶层,用于指出特定的DDE服务器应用程序名。
主题名更兆虚册深刻地定义了服务器誉缓应用程序会话的主题内容,
服务器应用程序可支持一个或多个主题名。
项目名更进一步确定了会话的详细内容,每个主题名可拥有一个或多个项目名。
在数据库应用程序中,经常需要与外部的数据源进行数据交换。通常我们会考虑利用开放式数据库互连标准ODBC。ODBC由驱动程序管理器和一系列把SQL作为它们访问语言的驱动程序所组成。当需要时袭亏此,ODBC驱动程序翻译各种产品的SQL语言以使不同产品间的连接完美无缺,从空贺而使得连接另外一个应用程序上的数据成为可能,甚至可以在Visual FoxPro并不直接支持的格式(例如电子表格)中提取和修改数据。鉴于ODBC早已经被很多程序员所熟知,我们这里仅仅讨论一种不太常用的方法:DDE。
----DDE是一种动态数据交换机制(Dynamic Data Exchange,DDE)。使用DDE通讯需要两个Windows应用程序,其中一个作为服务器处理信息,另外一个作为客户机从服务器获得信息。客户机应用程序向当前所激活的服务器应用程序发送一条消息请求信息,服务器应用程序根据该信息作出应答,从而实现两个程序之间的数据交换。在Visual FoxPro中,一共十一个常用的DDE函数,它们是:
DDEAbortTrans() 删除异步的DDE处理
DDEAdvise() 建立与服务器应用程序的温或热连接
DDEEnabled() 设置或返回DDE状态
DDEExecute() 向服务器应用程序发送一条执行消息
DDEInitiate() 打开到服务器应用程序的DDE控制板
DDELastError() 返回DDE函数引起的最后一条错误信息
DDEPoke() 传送数据库到客户机或服务器应用程序
DDERequest() 服务器应用程序请求数据
DDESetOption() 修改或返回DDE设置
DDESetService() 添加、删除、修改服务名的状态
DDESetTopic() 连接服务名与标题名
DDETerminte() 关闭DDE控制板
----Visual FoxPro既可以作为DDE客户机,也可以作为DDE服务器。当Visual FoxPro作为客户机时,一个典型的请求从拍迅其他应用程序输入数据的FoxPro程序由包含以下步骤的代码组成:
调用DDEInitiate()函数建立与服务器应用程序的连接。
如果成功地建立了连接关系,调用DDERequest()函数请求从服务器应用程序输入信息。可以重复调用DDERequest()函数请求输入其他的信息。
完成对数据的请求后,调用DDETerminate()函数技术与服务器应用程序的连接关系。只有这样做才能够释放系统资源。
当Visual FoxPro作为服务器时,一个典型的响应其他应用程序请求数据的FoxPro程序由包含以下步骤的代码组成:
调用DDESetService()函数生成服务过程(建立服务过程名)并且指定服务过程的类型。
调用DDESetTopic()函数生成服务标题并且指定客户机请求中设定标题时的运行过程。
生成DDESetTopic()中指定的过程用以接受传递给过程的参量。客户机请求信息调用此过程,此过程执行请求 *** 作并且向客户机应用程序返回所请求的信息。
----应用程序之间的DDE会话可以使用冷连接、温连接和热连接。当Visual FoxPro做为客户机时,所建立的连接为冷连接;当Visual FoxPro做为服务器时,可以使用其中任意的一种连接方式。可以使用DDEAdvise()函数来初始化DDE温连接和热连接的会话。传递给DDEAdvise()函数的参数之一是一个用户自定义函数的名称,服务器应用程序调用该函数通知客户机数据已经改动。因此,在温连接和热连接会话中,当数据源有所改动时,客户机能够根据服务器的通知自动进行数据更新。
----以下是一个利用DDE与Word进行数据交换的示例程序。该程序打开一个DOC文件,将其全部内容拷贝到剪贴板上,然后关闭文件并退出Word。
* 启动应用程序Word
RUN /N1 D:\WORD\WINWORD.EXE
* 建立DDE连接
Channel=DDEInitiate(“WinWord”,”System”)
* 判断连接是否已经建立
IF Channel>-1
* 将Word应用程序化
=DDEExecute(Channel,”[AppMaximize]”)
* 打开文件d:\word\test.doc
=DDEExecute(Channel,’[FileOpen “d:\word\test.doc”]’)
* 选取所有内容
//////////////////////////////////////DDE回调函数; HDDEDATA CALLBACK DdeCallback(UINT wType,UINT wFmt,HCONV hConv,HSZ Topic,HSZ Item, HDDEDATA hData,DWORD lData1,DWORD lData2) { 启销int I char tmp[255] switch(wType) { case XTYP_ADVSTART: case XTYP_CONNECT://请求连接; return ((HDDEDATA)TRUE)//允许; case XTYP_ADVDATA: //有数据到来; for(I=0I<NITEMI++) if(Item==hszItem[I]) { DdeGetData(hData,(PBYTE)tmp,255,0)//取得数据; switch(I) { case 0: SetDlgItemText(hWnd,IDC_STATIC2,tmp) breakcase 1: SetDlgItemText(hWnd,IDC_STATIC3,tmp) break } } return ((HDDEDATA)DDE_FACK)//回执; case XTYP_ADVREQ: case XTYP_REQUEST://数据请求; for(I=0I<NITEMI++) if(Item==hszItem[I]) 陆搭 return(DdeCreateDataHandle(idlnst,(PBYTE)(LPCTSTR)ServerData[I], ServerData[I].GetLength()+1,0,Item,wFmt,0)) } return(0)} ///////////////////////////////////////////////////// CddedemoDlg.cpp CDdedemoDlg::CDdedemoDlg(CWnd* pParent /*=NULL*/) : CDialog(CDdedemoDlg::IDD, pParent) { //{{AFX_DATA_INIT(CDdedemoDlg) m_edit = _T("悄悉游") //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME)} void CDdedemoDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX) //{{AFX_DATA_MAP(CDdedemoDlg) DDX_Text(pDX, IDC_EDIT1, m_edit) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CDdedemoDlg, CDialog) //{{AFX_MSG_MAP(CDdedemoDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_TIMER() ON_WM_DESTROY() ON_EN_CHANGE(IDC_EDIT1, OnChangeEdit1) //}}AFX_MSG_MAP END_MESSAGE_MAP() //////////////////////////////////////////CDdedemoDlg message handlers BOOL CDdedemoDlg::OnInitDialog() { CDialog::OnInitDialog() // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX &0xFFF0) == IDM_ABOUTBOX) ASSERT(IDM_ABOUTBOX <0xF000) CMenu* pSysMenu = GetSystemMenu(FALSE) if (pSysMenu != NULL) { CString strAboutMenustrAboutMenu.LoadString(IDS_ABOUTBOX)if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR) pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu)} } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE)// Set big icon SetIcon(m_hIcon, FALSE)// Set small icon // TODO: Add extra initialization here hWnd=m_hWnd if (DdeInitialize(&idlnst,(PFNCALLBACK)DdeCallback,APPCMD_FILTERINITS| CBF_FAIL_EXECUTES|CBF_SKIP_CONNECT_CONFIRMS|CBF_FAIL_SELFCONNECTIONS| CBF_FAIL_POKES,0)) { MessageBox("DDE SERVER初始化失败!")return FALSE } hlnst=AfxGetApp()->m_hInstance //创建DDE string hszApp=DdeCreateStringHandle(idlnst,szApp,0) hszTopic=DdeCreateStringHandle(idlnst,szTopic,0) for(int I=0I<NITEMI++) hszItem[I]=DdeCreateStringHandle(idlnst,pszItem[I],0)//注册服务; DdeNameService(idlnst,hszApp,0,DNS_REGISTER)bConnect=FALSESetTimer(1,1000,NULL)//开始定时; return TRUE// return TRUE unless you set the focus to a control } void CDdedemoDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID &0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAboutdlgAbout.DoModal() } else { CDialog::OnSysCommand(nID, lParam) } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CDdedemoDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this)// device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0)// Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON)int cyIcon = GetSystemMetrics(SM_CYICON)CRect rectGetClientRect(&rect)int x = (rect.Width() - cxIcon + 1) / 2int y = (rect.Height() - cyIcon + 1) / 2// Draw the icon dc.DrawIcon(x, y, m_hIcon) } else { CDialog::OnPaint() } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CDdedemoDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon} void CDdedemoDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default count++ ServerData[1].Format("%d",count) SetDlgItemText(IDC_STATIC1,ServerData[1]) DdePostAdvise(idlnst,hszTopic,hszItem[1])//通知更新; if(!bConnect)//如果没有建立连接 { hConv=DdeConnect(idlnst,hszApp,hszTopic,NULL)//连接服务器端; if(hConv) //如果建立成功 { DWORD dwResult bConnect=TRUE for(int I=0I<NITEMI++) DdeClientTransaction(NULL,0,hConv,hszItem[I],CF_TEXT,XTYP_ADVSTART, TIMEOUT_ASYNC,&dwResult)} } CDialog::OnTimer(nIDEvent)} void CDdedemoDlg::OnDestroy() { CDialog::OnDestroy() // TODO: Add your message handler code here KillTimer(1)//销毁定时; DdeNameService(idlnst,0,0,DNS_UNREGISTER)//注销服务; DdeFreeStringHandle(idlnst,hszApp) DdeFreeStringHandle(idlnst,hszTopic) for(int I=0I<NITEMI++) DdeFreeStringHandle(idlnst,hszItem[I])DdeUninitialize(idlnst)} void CDdedemoDlg::OnChangeEdit1() { // TODO: If this is a RICHEDIT control, the control will not // send this notification unless you override the CDialog::OnInitDialog() // function and call CRichEditCtrl().SetEventMask() // with the ENM_CHANGE flag ORed into the mask. // TODO: Add your control notification handler code here UpdateData() ServerData[0]=m_edit DdePostAdvise(idlnst,hszTopic,hszItem[0])//通知DDE更新该数据项目; }欢迎分享,转载请注明来源:内存溢出
评论列表(0条)