7、进程间通信-剪贴板
进程间通信-剪贴板
位于同一个进程中的多个线程共享同一个地址空间,因此线程之间的通信很简单。
进程间通信的四种方式
剪贴板
匿名管道
命名管道
邮槽
1、剪贴板
Win32平台下,内存块在物理内存中从来不会被移动,但可以在缺省的堆中被移动。
BOOL OpenClipboard( );
打开了剪贴板之后,还必须调用EmptyClipboard ,才能使当前窗口拥有剪贴板。
BOOL EmptyClipboard(VOID)
SetClipboardData
The SetClipboardData function places data on the clipboard in a specified clipboard format.
The window must be the current clipboard owner, and the application must have called the
OpenClipboard function. (When responding to the WM_RENDERFORMAT and WM_RENDERALLFORMATS
messages, the clipboard owner must not call OpenClipboard before calling SetClipboardData.)
HANDLE SetClipboardData(
UINT uFormat, // clipboard format
HANDLE hMem // data handle
);
步骤:
a.打开剪贴板:OpenClipboard,注意:一旦打开了剪贴版,其它运用程序将无法修改剪贴板,直到调用了CloseClipboard。
b. 清空剪贴板:EmptyClipboard,清空剪切板,并将所有权交付给打开剪贴板的运用程序
c. 为即将拷贝的内容分配内存空间:GlobalAlloc,第一个参数指示分配内存的类型,重要的有两类,GMEM_FIXED:Allocates fixed memory. The return value is a pointer;GMEM_MOVEABLE:Allocates movable
memory. In Win32, memory blocks are never moved in physical memory, but they can be moved within the default heap. The
return value is a handle to the memory object. To translate the handle into a pointer, use the GlobalLock function. This flag
cannot be combined with the GMEM_FIXED flag.
本例中采用GMEM_MOVEABLE,其返回值是一个指向内存对象的句柄。
d. 将句柄转换为指针:GlobalLock,将指定内存块锁定。
The internal data structures for each memory object include a lock count that is initially zero.
For movable memory objects, GlobalLock increments the count by one, and the GlobalUnlock
function decrements the count by one. For each call that a process makes to GlobalLock for an
object, it must eventually call GlobalUnlock. Locked memory will not be moved or discarded,
unless the memory object is reallocated by using the GlobalReAlloc function. The memory block
of a locked memory object remains locked until its lock count is decremented to zero, at which
time it can be moved or discarded.
e.将字符串的内容拷贝到可移动堆中:strcpy
f.释放内存块锁定:GlobalUnlock
g.放置数据:SetClipboardData, The SetClipboardData function places data on the clipboard in a specified clipboard format. The
window must be the current clipboard owner, and the application must have called the OpenClipboard function.
SetClipboardData的第一个参数可以是指定的格式或NULL,如果是NULL,则采用的是延迟提交的技术,所谓延迟提交表示的是为了避免下面这种情况:当一个拷贝数据到剪贴板的动作发生时,直到下一个从剪贴板上取出数据的过程中,数据一直占用着内存空间,造成了资源浪费。为了改善这种情况,延迟提交技术采用SetClipboardData调用一个空的内存区块,当下一个从剪贴板取出数据的动作发生时,自动发送一个WM_RENERFORMAT消息,剪贴板的所有者程序再次调用具有实际内存区块参数的SetClipboardData方法,发生实际剪贴动作。第二次调用前不用再调用OpenClipboard方法。
h. 关闭剪贴板:CloseClipboard
实现代码如下:
if(OpenClipboard()) //打开剪贴板
{
CString str;
HANDLE hClip; //剪贴板句柄
char* pBuf;
EmptyClipboard();
GetDlgItemText(IDC_EDIT_SEND,str);
//分配内存的长度一般是字符串的长度加1用来存放空字符,否则系统将自动覆盖掉现有字符串的最后一位用来存放空字符,空字符作为结尾标识
hClip=GlobalAlloc(GMEM_MOVEABLE,str.GetLength()+1);
pBuf=(char*)GlobalLock(hClip); //将句柄转换为指针,返回内存对象地址并加锁,如果GlobalAlloc参数是GMEM_FIXED,则这样不需要这样的转换。 GMEM_FIXED锁计数总为零,该语句将增长Lock数
strcpy(pBuf,str); //为分配好的内存空间填充想赋的值
GlobalUnlock(hClip); //如果GlobalAlloc参数是GMEM_FIXED,则不起作用。该语句将减少Lock数,如果Lock数为0,则指定动态内存区域将可被移动和抛弃
SetClipboardData(CF_TEXT,hClip); //以指定格式存放数据,不完成指定格式转换,不能完成粘贴
CloseClipboard();
}
从剪贴板上提取数据:
具体代码如下:
if(OpenClipboard())
{ GMEM_FIXED
if(IsClipboardFormatAvailable(CF_TEXT)) //指定格式数据在接贴板上是否存在
{
HANDLE hClip=GetClipboardData(CF_TEXT); //从剪贴板上得到数据,且拿到了数据块的句柄
char* pBuf;
pBuf=(char*)GlobalLock(hClip);
GlobalUnlock(hClip);
SetDlgItemText(IDC_EDIT_RECV,pBuf);
}
CloseClipboard();
}