Visual C++进程间数据通信的实现
2009-10-07 20:29:24 来源:WEB开发网二、编程步骤
1、启动Visual C++6.0,新建一个基于对话框的MFC应用程序,取名为DDEdemo,添加两个Group Box控件并分别在其上放置编辑控件IDC_EDIT、静态控件ID_STATIC1、ID_STATIC2、 ID_STATIC3,用Wizard添加对应成员变m_edit(CString类型),添加并将其Caption置空,最后的界面如图一所示;
2、使用CLASSWIZARD添加对话框函数,分别为WM_DESTORY、WM_INITDIALOG、WM_TIMER及IDC_EDIT的EN_CHANGE消息建立对应函数;
3、在DDEdemoDlg.CPP中加入#include "ddel.h"以使用DDEML函数。并添加以下宏定义和全局变量:
#define NITEM 2 //定义ITEM的数量;
const char szApp[]="Server"; //server DDE服务名;
const char szTopic[]="Topic";//Server DDE目录名;
const char *pszItem[NITEM]={"Item1","Item2"};//SERVER ITEM名称字符串数组;
int count=0;//记数,在Static1中显示;
CString ServerData[NITEM];//存放服务器中的数据项内容;
HCONV hConv=0; //会话句柄;
DWORD idlnst=0; //DDEML实例句柄;
HWND hWnd; //窗口句柄;
HANDLE hlnst; //实例句柄;
HSZ hszApp=0; //SERVER服务字符串句柄;
HSZ hszTopic=0; //SERVER目录字符串句柄;
HSZ hszItem[NITEM]; //Server ITEM字符串句柄;
BOOL bConnect; // 建立连接标志;
4、输入代码,编译运行程序。
三、程序代码
//////////////////////////////////////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=0;I<NITEM;I++)
if(Item==hszItem[I])
{
DdeGetData(hData,(PBYTE)tmp,255,0);//取得数据;
switch(I)
{
case 0:
SetDlgItemText(hWnd,IDC_STATIC2,tmp);
break;
case 1:
SetDlgItemText(hWnd,IDC_STATIC3,tmp);
break;
}
}
return ((HDDEDATA)DDE_FACK);//回执;
case XTYP_ADVREQ:
case XTYP_REQUEST://数据请求;
for(I=0;I<NITEM;I++)
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 strAboutMenu;
strAboutMenu.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=0;I<NITEM;I++)
hszItem[I]=DdeCreateStringHandle(idlnst,pszItem[I],0);
//注册服务;
DdeNameService(idlnst,hszApp,0,DNS_REGISTER);
bConnect=FALSE;
SetTimer(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 dlgAbout;
dlgAbout.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 rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int 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=0;I<NITEM;I++)
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=0;I<NITEM;I++)
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更新该数据项目;
}
四、小结
Windows提供了很多方法来实现进程之间的通信,相互传递数据,如通过系统剪贴板方法、共享DLL方法、管道方法等,这些方法的存在保证了程序的健壮性和鲁棒性(稳定性),有兴趣的读者可以自行参考有关资料。
- ››Visual Basic 2008 数学函数
- ››Visual Studio2005中Smart Device的问题
- ››Visual Studio 中根据数据库字段动态生成控件
- ››Visual Studio 11全新黑色主题
- ››Visual Studio 2011 Beta新特性(一):安装VS201...
- ››Visual Studio自定义调试窗体两个小技巧
- ››Visual Studio 2005 Team Edition for Database P...
- ››Visual C#两分钟搭建BHO IE钩子
- ››Visual C++优化对大型数据集合的并发访问
- ››VISUAL C++中的OCX控件的使用方法
- ››Visual C++实现视频图像处理技术
- ››Visual C++制作一个Sniffer实例
更多精彩
赞助商链接