现在的位置: 首页 > 综合 > 正文

MFC(进程间的通信,孙鑫C++第十七讲笔记整理)

2013年08月07日 ⁄ 综合 ⁄ 共 5559字 ⁄ 字号 评论关闭

有四种方法

1.剪贴板

 a.创建个ClipBoard的对话框应用程序,加两EditBox和两个Button发送接收。

 b.具体代码:

   发送端代码:

 if(OpenClipboard())

 {

 CString str;

 HANDLE hClip;

 char *pBuf;

 EmptyClipboard();

 GetDlgItemText(IDC_EDIT_SEND,str);

 hClip=GlobalAlloc(GMEM_MOVEABLE,str.GetLength()+1);

 pBuf=(char*)GlobalLock(hClip);将句柄转换为指针!

 strcpy(pBuf,str);

 GlobalUnlock(hClip);

 SetClipboardData(CF_TEXT,hClip);

 CloseClipboard();

 }

    接收端代码:

 if(OpenClipboard())

 {

 if(IsClipboardFormatAvailable(CF_TEXT))

 {

  HANDLE hClip;

  char *pBuf;

  hClip=GetClipboardData(CF_TEXT);

  pBuf=(char*)GlobalLock(hClip);

  GlobalUnlock(hClip);

  SetDlgItemText(IDC_EDIT_RECV,pBuf);

  CloseClipboard();

 }

 }

 

2.匿名管道:只能在父子进程之间进行通信

 a.先建一个Parent的单文档应用程序,增加“创建管道”“读取数据”“写入数据”三个菜单

 b.增加成员变量HANDLE类型的hRead,hWrite,初始化变量,并在析构函数中释放句柄

 c.响应菜单代码:

void CParentView::OnPipeCreate()菜单“创建管道”代码

{

 // TOD Add your command handler code here

 SECURITY_ATTRIBUTES sa;

 sa.bInheritHandle=TRUE;

 sa.lpSecurityDescriptor=NULL;

 sa.nLength=sizeof(SECURITY_ATTRIBUTES);

 if(!CreatePipe(&hRead,&hWrite,&sa,0))

 {

 MessageBox("创建匿名管道失败!");

 return;

 }

 STARTUPINFO sui;

 PROCESS_INFORMATION pi;

 ZeroMemory(&sui,sizeof(STARTUPINFO));将数据清0

 sui.cb=sizeof(STARTUPINFO);

 sui.dwFlags=STARTF_USESTDHANDLES;

 sui.hStdInput=hRead;

 sui.hStdOutput=hWrite;

 sui.hStdError=GetStdHandle(STD_ERROR_HANDLE);

 

 if(!CreateProcess("..\\Child\\Debug\\Child.exe",NULL,NULL,NULL,

  TRUE,0,NULL,NULL,&sui,&pi))创建子进程

 {

 CloseHandle(hRead);

 CloseHandle(hWrite);关闭句柄,将内核对象的使用计数减少1,这样当操作系统发现内核对象的使用计数为0时,将清除内核对象。

 hRead=NULL;

 hWrite=NULL;

 MessageBox("创建子进程失败!");

 return;

 }

 else

 {

 CloseHandle(pi.hProcess);

 CloseHandle(pi.hThread);

 }

}void CParentView::OnPipeRead()菜单“读取数据”代码

{

 // TOD Add your command handler code here

 char buf[100];

 DWORD dwRead;

 if(!ReadFile(hRead,buf,100,&dwRead,NULL))

 {

 MessageBox("读取数据失败!");

 return;

 }

 MessageBox(buf);

}void CParentView::OnPipeWrite()菜单“写入数据”代码

{

 // TOD Add your command handler code here

 char buf[]="http://www.sunxin.org";

 DWORD dwWrite;

 if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))

 {

 MessageBox("写入数据失败!");

 return;

 }

}

    d.再建一个Child的单文档,在View中增加两个成员hReadhWrite.OnInitialUpdate()中得到句柄的值。

void CChildView::OnInitialUpdate()

{

 CView::OnInitialUpdate();

 

 // TOD Add your specialized code here and/or call the base class

 hRead=GetStdHandle(STD_INPUT_HANDLE);注意这句代码!

 hWrite=GetStdHandle(STD_OUTPUT_HANDLE);

}    e.加菜单“读取数据”“写入数据”其代码如下:

void CChildView::OnPipeRead()

{

 // TOD Add your command handler code here

 char buf[100];

 DWORD dwRead;

 if(!ReadFile(hRead,buf,100,&dwRead,NULL))

 {

 MessageBox("读取数据失败!");

 return;

 }

 MessageBox(buf);

}void CChildView::OnPipeWrite()

{

 // TOD Add your command handler code here

 char buf[]="匿名管道测试程序";

 DWORD dwWrite;

 if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))

 {

 MessageBox("写入数据失败!");

 return;

 }

}

 

3.命名管道:还可以跨网络通信,服务器只能在win2000NT下运行!而客户端可以在95下运行。关键函数CreateNamedPipe

 a.先建一个NamedPipeSRV单文档应用程序,加菜单“创建管道”“读取数据”“写入数据”

 b.View中增加Handle变量hPipe,注意在析构函数中释放它!

 c.响应菜单,创建命名管道

void CNamedPipeSrvView::OnPipeCreate()

{

 // TOD Add your command handler code here

 hPipe=CreateNamedPipe("\\\\.\\pipe\\MyPipe",

 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,

 0,1,1024,1024,0,NULL);

 if(INVALID_HANDLE_VALUE==hPipe)

 {

 MessageBox("创建命名管道失败!");

 hPipe=NULL;

 return;

 }

 HANDLE hEvent;

 hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

 if(!hEvent)

 {

 MessageBox("创建事件对象失败!");

 CloseHandle(hPipe);

 hPipe=NULL;

 return;

 }

 OVERLAPPED ovlap;

 ZeroMemory(&ovlap,sizeof(OVERLAPPED));

 ovlap.hEvent=hEvent;

 if(!ConnectNamedPipe(hPipe,&ovlap))

 {

 if(ERROR_IO_PENDING!=GetLastError())

 {

  MessageBox("等待客户端连接失败!");

  CloseHandle(hPipe);

  CloseHandle(hEvent);

  hPipe=NULL;

  return;

 }

 }

 if(WAIT_FAILED==WaitForSingleObject(hEvent,INFINITE))

 {

 MessageBox("等待对象失败!");

 CloseHandle(hPipe);

 CloseHandle(hEvent);

 hPipe=NULL;

 return;

 }

 CloseHandle(hEvent);

}void CNamedPipeSrvView::OnPipeRead()

{

 // TOD Add your command handler code here

 char buf[100];

 DWORD dwRead;

 if(!ReadFile(hPipe,buf,100,&dwRead,NULL))

 {

 MessageBox("读取数据失败!");

 return;

 }

 MessageBox(buf);

}void CNamedPipeSrvView::OnPipeWrite()

{

 // TOD Add your command handler code here

 char buf[]="http://www.sunxin.org";

 DWORD dwWrite;

 if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))

 {

 MessageBox("写入数据失败!");

 return;

 }

}     d.再建一个NamedPipeCLT单文档工程,加菜单“连接管道”“读取数据”“写入数据”,当然别忘记成员变量hPipe的定义和初始化

     e.响应菜单代码

void CNamedPipeCltView::OnPipeConnect()连接管道

{

 // TOD Add your command handler code here

 if(!WaitNamedPipe("\\\\.\\pipe\\MyPipe",NMPWAIT_WAIT_FOREVER))

 {

 MessageBox("当前没有可利用的命名管道实例!");

 return;

 }

 hPipe=CreateFile("\\\\.\\pipe\\MyPipe",GENERIC_READ | GENERIC_WRITE,

 0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

 if(INVALID_HANDLE_VALUE==hPipe)

 {

 MessageBox("打开命名管道失败!");

 hPipe=NULL;

 return;

 }

}void CNamedPipeCltView::OnPipeRead()读取数据

{

 // TOD Add your command handler code here

 char buf[100];

 DWORD dwRead;

 if(!ReadFile(hPipe,buf,100,&dwRead,NULL))

 {

 MessageBox("读取数据失败!");

 return;

 }

 MessageBox(buf);

}void CNamedPipeCltView::OnPipeWrite()写入数据

{

 // TOD Add your command handler code here

 char buf[]="命名管道测试程序";

 DWORD dwWrite;

 if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))

 {

 MessageBox("写入数据失败!");

 return;

 }

}

 

4.邮槽,使用时应将消息长度限制在424字节以下,关键函数CreateMailSlot()

 a.先建一个MailSlotSRV工程,加菜单“接收数据”

 b.消息响应代码:

void CMailslotSrvView::OnMailslotRecv()菜单“接收数据”的代码

{

 // TOD Add your command handler code here

 HANDLE hMailslot;

 hMailslot=CreateMailslot("\\\\.\\mailslot\\MyMailslot",0,

 MAILSLOT_WAIT_FOREVER,NULL);

 if(INVALID_HANDLE_VALUE==hMailslot)

 {

 MessageBox("创建油槽失败!");

 return;

 }

 char buf[100];

 DWORD dwRead;

 if(!ReadFile(hMailslot,buf,100,&dwRead,NULL))

 {

 MessageBox("读取数据失败!");

 CloseHandle(hMailslot);

 return;

 }

 MessageBox(buf);

 CloseHandle(hMailslot);

}

   c.加工程MailSlotCLT,加菜单“发送数据”

   d.加消息响应,添加代码,客户端也比较简单。

void CMailslotCltView::OnMailslotSend()菜单“发送数据”的代码

{

 // TOD Add your command handler code here

抱歉!评论已关闭.