原理:Windows系统支持剪贴板IPC的基本机制是由系统预留的一块全局共享内存,可用于被各进程暂时存储数据。写入进程首先创建一个全局内存块,并将数据写到该内存块;接受数据的进程通过剪贴板机制获取此内存块的句柄,并完成对该内存块数据的读取。
Windows系统在USER32.dll中为剪贴板提供了一组API函数和多种消息。还包括多种数据格式,使读取进程能够以原有格式读取剪贴板中的数据。
#include <cstdio> #include "Clipboard.h" Clipboard::Clipboard() { } Clipboard::~Clipboard() { } void Clipboard::SetClipBoardData(char* StrData) { //将 OpenClipboard 函数的参数指定为 NULL,表明为当前进程打开剪贴板 if (OpenClipboard(NULL)) { char * pDataBuf; //全局内存对象 HGLOBAL hGlobalClip; //给全局内存对象分配全局内存 hGlobalClip = GlobalAlloc(GHND, strlen(StrData) + 1); //通过给全局内存对象加锁获得对全局内存块的引用 pDataBuf = (char *)GlobalLock(hGlobalClip); memcpy(pDataBuf, StrData, sizeof(StrData)); //使用完全局内存块后需要对全局内存块解锁 GlobalUnlock(hGlobalClip); //清空剪贴板 EmptyClipboard(); //设置剪贴板数据,这里直接将数据放到了剪贴板中,而没有使用延迟提交技术 SetClipboardData(CF_TEXT, hGlobalClip); //关闭剪贴板 CloseClipboard(); } } void Clipboard::GetClipBoardData(char **DataBuf) { if (OpenClipboard(NULL)) { //判断剪贴板中的数据格式是否为 CF_TEXT if (IsClipboardFormatAvailable(CF_TEXT)) { HGLOBAL hGlobalClip; //从剪贴板中获取格式为 CF_TEXT 的数据 hGlobalClip = GetClipboardData(CF_TEXT); GlobalLock(hGlobalClip); //memcpy(DataBuf, szBuffer, sizeof(szBuffer)); *DataBuf = (char *)GlobalLock(hGlobalClip); GlobalUnlock(hGlobalClip); } CloseClipboard(); } }
#pragma once #include <Windows.h> class Clipboard { public: Clipboard(); ~Clipboard(); void SetClipBoardData(char* StrData); void GetClipBoardData(char **DataBuf); };
延时提交技术:
/*在数据提供进程创建了剪贴板数据后,一直到有其他进程获取剪贴板数据前, 这些数据都要占据内存空间。如在剪贴板放置的数据量过大,就会浪费内存空间, 降低对资源的利用率。 为避免这种浪费,可以采取延迟提交(Delayed rendering)技术, 即由数据提供进程先创建一个指定数据格式的空(NULL)剪贴板数据块, 直到有其他进程需要数据或自身进程要终止运行时才真正提交数据。 延迟提交的实现并不复杂,只需剪贴板拥有者进程在调用SetClipboardData() 将数据句柄参数设置为NULL即可。 延迟提交的拥有者进程需要做的主要工作是对WM_RENDERFORMAT、 WM_DESTORYCLIPBOARD和WM_RENDERALLFORMATS等剪贴板延迟提交消息的处理。 当另一个进程调用GetClipboardData()函数时, 系统将会向延迟提交数据的剪贴板拥有者进程发送WM_RENDERFORMAT消息。 剪贴板拥有者进程在此消息的响应函数中应使用相应的格式和实际的数据句柄来 调用SetClipboardData()函数,但不必再调用OpenClipboard()和EmptyClipboard() 去打开和清空剪贴板了。在设置完数据有也无须调用CloseClipboard()关闭剪贴板。 如果其他进程打开了剪贴板并且调用EmptyClipboard()函数去清空剪贴板的内容, 接管剪贴板的拥有权时, 系统将向延迟提交的剪贴板拥有者进程发送WM_DESTROYCLIPBOARD消息, 以通知该进程对剪贴板拥有权的丧失。 而失去剪贴板拥有权的进程在收到该消息后则不会再向剪贴板提交数据。 另外,在延迟提交进程在提交完所有要提交的数据后也会收到此消息。 如果延迟提交剪贴板拥有者进程将要终止,系统将会为其发送一条WM_RENDERALLFORMATS消息, 通知其打开并清除剪贴板内容。在调用SetClipboardData()设置各数据句柄后关闭剪贴板。*/