//每个进程拥有的4GB空间是私有的,一个进程不能访问另一个进程地址空间中的数据,这里介绍4种进程间的通信方式:剪贴板、匿名管道、命名管道、邮槽。
//先建立一个对话框应用程序,命名为Clipboard,然后添加如图所示的控件。实现的基本功能就是向左边编辑框输入数据,单击发送按钮,将数据发送到剪切板上;单击接收按钮,从剪切板上面取出数据,并在右边的编辑框中显示出来。
//数据放到剪贴板之前,首先得打开剪切板,利用CWnd类的OpenClipboard成员函数完成。
BOOL OpenClipboard(
HWND hWndNewOwner // handle to window opening clipboard
);
//返回值为非0表示打开剪切板操作成功;返回0表示当前窗口已经打开了剪切板。CloseClipboard表示关闭剪切板;EmptyClipboard表示清空剪切板。SetClipboardData表示向剪切板上面放置数据。
HANDLE SetClipboardData(
UINT uFormat, // clipboard format
HANDLE hMem // data handle
);
//第一个参数指定剪切板的格式,因为将传输文本数据,所以选择CF_TEXT格式;第二个参数指定格式的数据的句柄,该参数可以是NULL,窗口直到有对剪切板数据的请求时,才提供剪切板格式的数据。如果窗口采用延迟提交技术,则窗口必须处理WM_READERFORMAT和WM_READERALLFORMATS消息。
//如果hMen参数标识了一个内存对象,那么这个对象必须是利用GWEN_MOVEABLE标志调用GlobalAlloc函数为其分配内存
HGLOBAL GlobalAlloc(
UINT uFlags, // allocation attributes
DWORD dwBytes // number of bytes to allocate
);
//第一个参数是一个标记,用来指定分配内存的方式;第二个参数指定分配的字节数。
//GlobalLock函数的作用就是对全局内存对象加锁,然后返回该对象内存块第一个字节的指针
LPVOID GlobalLock(
HGLOBAL hMem // handle to the global memory object
);
//每个内存对象的内部数据结构都包含了一个初始值为0的锁计数,GlobalLock函数将其锁计数加一,而GlobalUnLock将其锁计数减一。被锁定内存对象的的内存块将保持锁定,直到它的锁计数为0这是内存块才能被移动或者废弃。另外已被加锁的内存不能移动或者废弃,除非调用了GlobalRealloc函数重新分配了该内存对象。
//使用GMEN_FIXED标志分配的内存对象其锁计数为0,如果一个函数采用HGLOBAL类型的参数,为了保证安全,我们就应该用GMEM_MOVEABLE标志调用GlobalAlloc函数来生成这个参数值。
//双击对话框上面的发送按钮,为该按钮创建单击命令响应函数:OnBtnSend,在该函数中实现向剪切板发送数据的功能。
void CClipboardDlg::OnBtnSend()
{
// TODO: Add your control notification handler code here
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(pBuf);
//在剪切板放置数据
setClipboard(CF_TEXT,hClip);
//关闭剪切板
CloseClipboard();
}
}
//运行后,输入数据,点击发送按钮,然后选择打开一个文件粘贴,就出现了刚刚发送的数据。
//同样地双击接收按钮,添加相应的命令消息响应函数,完后完成从剪切板接收数据的功能:
void CClipboardDlg::OnBtnRecv()
{
// TODO: Add your control notification handler code here
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();
}
}
//接收端这时不应该调用EmptyClipboard函数,因为这时是从剪切板中得到数据;在获得数据之前,先看一下剪贴板中是否有我们想要的特定格式的数据,通过调用GetClipboardData函数实现。