剪切板是系统维护管理的一块内存区域,本机的所有进程都可以访问。当一个进程复制数据时,先将数据放在该内存区,当另一个进程粘贴时,则是从该内存区块取出数据
剪切板操作:
其实在剪切板中也就那几个API在使用,下面会介绍几个常用的API,然后会给出一个demo示例
剪切板打开—OpenClipboard
- BOOL OpenClipboard(
- [in, optional] HWND hWndNewOwner
- );
OpenClipboard函数用来打开剪切板(放数据前的笔要操作)。参数hWndNewOwner指向一个窗口句柄,即代表是这个窗口打开的剪切板,如果这个参数设置为NULL,则以当前任务来打开剪切板 。如果有另一个窗口打开了剪切板,则函数失败,返回零。
清空剪切板—EmptyClipboard
BOOL EmptyClipboard();
这个函数将清空剪贴板,并释放剪贴板中数据的句柄,然后将剪贴板的所有权分配给当前打开剪贴板的窗口。
因为剪贴板是所有进程都可以访问的,所以应用程序在使用这个剪贴板时,有可能已经有其他的应用程序把数据放置到了剪贴板上,因此该进程打开剪贴板之后,就需要调用 EmptyClipboard 函数来清空剪贴板,释放剪贴板中存放的数据的句柄,并将剪贴板的所有权分配给当前的进程,这样做之后当前打开这个剪贴板的程序就拥有了剪贴板的所有权,因此这个程序就可以往剪贴板上放置数据了。
数据发送到剪切板—SetClipboardData
- HANDLE SetClipboardData(
- [in] UINT uFormat,
- [in, optional] HANDLE hMem
- );
常见的有CF_BTMAP(bitmap类型),CF_TEXT(text类型),CT_DIB等
如果hMen参数标识的是内存对象,则必须带有GME_MOVEABLE属性的函数分配对象。下面的GlobalAlloc函数可以创建这种标识的内存对象句柄。
应用程序在调用了 SetClipboardData 函数之后,系统就拥有了 hMem 参数所标识的数据对象,该应用程序可以读取这个数据对象,但是在应用程序调用 CloseClipboard 函数之前,它都是不能释放该对象的句柄的,或者锁定这个句柄,如果 hMem 标识一个内存对象,那么这个对象必须是利用 GMEM_MOVEABLE 标识调用 GlobalAlloc 函数为其分配内存的。
数据句柄—GlobalAlloc
- DECLSPEC_ALLOCATOR HGLOBAL GlobalAlloc(
- [in] UINT uFlags,
- [in] SIZE_T dwBytes
- );
GlobalAlloc函数从堆上分配指定数目的字节
这里有读者可能会问:为什么我们在自己的应用程序中不使用 GlobalAlloc 函数来分配内存,而是要使用 malloc 或者 new 来实现?
其实,这个也只用稍微想想就知道了,使用 malloc 或者 new 分配的内存是在进程的私有地址空间上分配的,这块私有地址空间归这个进程所拥有,在之后对这块内存的读写会快很多,而全局内存不属于这个进程,你下次要去访问全局内存的时候,还得通过映射转换,这样肯定是运行效率低。
函数执行成功,返回新分配内存对象的句柄,否则返回NULL。
锁定全局内存对象—GlobalLock
- LPVOID GlobalLock(
- [in] HGLOBAL hMem
- );
锁定全局内存对象并返回指向该对象内存块的第一个字节的指针。我们可以通过这个指针对这块内存数据存取,这也保证了其他进程不会对这块内存的数据修改。
每个内存对象的内部数据结构包括最初为零的锁计数。对于可移动内存对象(GME_MOVEABLE),全局锁定将计数递增 1,全局解锁函数将计数递减 1。锁定内存对象的内存块将保持锁定状态,直到其锁定计数减少到零,此时可以移动或丢弃它。
全局内存对象解锁—GlobalUnLock
- BOOL GlobalUnlock(
- [in] HGLOBAL hMem
- );
GlobalUnlock函数递减与分配了GMEM_MOVEABLE的内存对象关联的锁定计数。
若函数执行完后内存对象仍处于锁定状态,则函数返回非零值,如果减少计数后解锁内存对象,则函数返回零(GetLasrError返回NO_ERROR),如果函数失败,则返回零(GetLastError返回NO_ERROR以外的值)
剪切板中的数据格式判断—IsClipboardFormatAvaliable
- BOOL IsClipboardFormatAvailable(
- [in] UINT format
- );
该函数将确定剪贴板是否包含指定格式的数据。如果剪贴板格式可用,则返回值为非零值。否则返回零。
剪贴板中数据接收—GetClipboardData
- HANDLE GetClipboardData(
- [in] UINT uFormat
- );
GetClipboardData以指定格式从剪贴板检索数据。剪贴板之前必须已打开。函数成功,返回指定格式剪切板对象的句柄,失败返回NULL。
Demo示例
创建一个MFC项目

当接收按钮按下后,会打开剪切板,将上方编辑框里的内容放到剪切板内
当接收按钮按下后,则会将剪切板中的内容粘贴到上方编辑框中。
接收按钮程序:
- void CClipDlg::OnBnClickedSendBtn()
- {
-
- //打开剪切板
- if (OpenClipboard()) {
- //清空剪切板
- EmptyClipboard();
-
- char* szSendBuf;//要发送的数据
-
- //获取编辑框的内容
- CStringW strSendW;
- GetDlgItemText(IDC_SEND_EDIT, strSendW);
-
- CStringA strSend = (CStringA)strSendW;
- //分配一个内存对象,内存对象的句柄就是hClip
- HANDLE hClip = GlobalAlloc(GMEM_MOVEABLE, strSend.GetLength() + 1);
- //句柄加锁
- szSendBuf = (char*)GlobalLock(hClip);
-
-
- //将指定字符串复制到目标字符串,若目标字符串大小小于指定字符串,则会溢出
- //第一个参数为目标字符串,第二个参数为指定字符串
- strcpy(szSendBuf, strSend);
-
- //TRACE("seSendBuf =%s", szSendBuf);
- //解锁
- GlobalUnlock(hClip);
- //将数据放在剪切板
- SetClipboardData(CF_TEXT, hClip);
- //关闭剪切板
- CloseClipboard();
- }
- }
发送按钮程序:
- void CClipDlg::OnBnClickedButton1()
- {
- if (OpenClipboard()) {
- //先确认剪切板是否可用
- if (IsClipboardFormatAvailable(CF_TEXT)) {
- HANDLE hClip;
- char* pBuf;
- //向剪切板要数据
- hClip = GetClipboardData(CF_TEXT);
- pBuf = (char*)GlobalLock(hClip);
-
-
-
- USES_CONVERSION;
- LPCWSTR strBuf = A2W(pBuf);
- GlobalUnlock(hClip);
- //显示
- SetDlgItemText(IDC_RECV_EDIT, strBuf);
-
- }
- CloseClipboard();
- }
- }
运行:
