VC++深入详解(16):进程通信

本文详细解析了VC++中进程通信的概念和实现,通过实例介绍了如何在不同进程中传递数据,揭示了进程间通信的关键技术和应用场景。
摘要由CSDN通过智能技术生成
我们只介绍几种简单的进程间通信机制:剪切板、匿名管道、命名管道、匿名管道和油槽。
平时大家都用过剪切板,比如选中记事本上的一段文字,然后Ctrl+C复制到剪切板上,然后在word中按下Ctrl+V,将其复制。这其实完成了两个进程之间的通信:从记事本到word。实际上,剪切板是系统维护管理的一段内存区域,当在一个进程中复制数据时,是将数据复制到这个内存区域,而在另一个进程中粘贴数据时,是从这个内存区域中取出数据,然后显示在窗口上。
下面我们写一个示例程序来实现剪切板的功能。
首先是程序的外观:一个对话框程序,上面有两个编辑框,分别用来输入发送到剪切板的数据和显示从剪切板接收的数据。然后再增加2个按钮,用来控制发送和接收数据。

我们对发送数据按钮进行响应:

void CCH_16_ClipboardDlg::OnBntSend() 
{
	// TODO: Add your control notification handler code here
	//打开剪切板
	if(!OpenClipboard())
	{
		MessageBox("打开剪切板失败");
		return ;
	}
	//获取剪切板控制权,释放剪切板中之前的数据
	if(!EmptyClipboard())
	{
		MessageBox("进入剪切板失败");
		return ;
	}
	
	//获取编辑框中的文字
	CString str;
	GetDlgItemText(IDC_EDIT_SEND,str);

	//内存对象,从全局堆分配
	HGLOBAL  hClip;
	hClip = GlobalAlloc(GMEM_MOVEABLE,		//
						sizeof(str)+1);		//大小

	//获取内存对象的指针
	char* pBuf;
	pBuf = (char*)GlobalLock(hClip);
	
	//完成数据的拷贝
	strcpy(pBuf,str);

	//减少引用计数,解锁
	GlobalUnlock(hClip);
	//向剪贴板中放入数据
	SetClipboardData(CF_TEXT,	//文本格式
					 hClip);	//内存对象

	//关闭剪切板,使其他进程可以获取剪切板
	CloseClipboard();

}

运行程序,在发送剪切板上输入一些文字,然后可以打开一个记事本程序,选择“粘贴”,之前输入的文字就粘贴到记事本上了。这就实现了我们的进程,用记事本进程的通信。
总体上说,这段程序分为以下几步:
1.打开剪切板
2.进入剪切板
3.获取编辑框中的数据
4.将数据放到剪切板中
5.关闭剪切板


但是在将数据放到剪切板中的SetClipboardData函数值得详细讨论一下:
HANDLE SetClipboardData(UINT uFormat, HANDLE hMem );
uFormat指明了放入的数据的格式,我们既可以选择一个已经注册过的自己的格式,也可以选择标准的格式。这里选择的是标准的文本格式。
hMem是具有指定格式的句柄:如果这个参数为NULL,指示调用窗口直到对剪切板数据有请求时才提供指定剪切板格式的数据。如果窗口采用延迟交换技术,则该窗口必须处理WM_RENDERFORMAT和WM_RENDERALLFORMATS 消息。
这个设置是为了提高效率:当我们把数据复制到剪切板上时,这些数据都要占据内存空间。实际上,我们经常会复制了一堆数据,却并没有使用它们;然后又复制一段数据。这样第一次复制的数据就浪费了。Windows提供了这样一种机制:先提供一个空剪切板,当一个进程需要粘贴已复制的数据时,会发送
WM_RENDERFORMAT消息,而在消息响应函数中,完成之前就应该完成的复制操作。
我们这里并没有使用这个复杂的机制,只是在其中填入一个内存对象。这个内存对象必须由GlobalAlloc分配,且分配标记必须为GMEM_MOVEABLE。
GlobalAlloc从堆上分配指定数目的比特。GMEM_MOVEABLE表明这个内存对象在堆中是可以移动的。因为在必要的某些时候,Windows可以移动内存,从而更好的支持系统内存管理。正因为是可移动的,所以不能直接用指针访问,比较麻烦,可使用函数 GlobalLock 将该句柄转换为一个指针。此时拿到的,才是物理内存的地址。有了指针之后,我们使用strcyp将编辑框中数据拷贝到这个内存对象中。拷贝完成后,使用GlobalUnlock对其解锁。


下面我们看看数据接收功能的实现:

void CCH_16_ClipboardDlg::OnBtnRecv() 
{
	// TODO: Add your control notification handler code here
	if(!OpenClipboard())
	{
		MessageBox("无法打开剪切板");
		return ;
	}
	//判断剪切板中的数据是否是指定格式
	if(!IsClipboardFormatAvailable(CF_TEXT))
	{
		MessageBox("剪切板数据格式错误");
		return ;
	}

	//获取剪切板内存对象
	HANDLE hClip;
	hClip = GetClipboardData(CF_TEXT);

	//获取内存对象指针
	char* pBuf = (char*)GlobalLock(hClip);
	GlobalUnlock(hClip);

	//设置文字
	SetDlgItemText(IDC_EDIT_RECV,pBuf);
	//关闭剪切板,使其他进程可以获取剪切板
	CloseClipboard();
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值