概述
剪切、复制、粘贴都是我们在操作电脑的时候经常会用到的功能。但是你知道当我们剪切或者复制的 时候,数据会保存到什么地方吗?当我们粘贴的时候,又是从什么地方将数据输出出来呢?这都源自于系统中给我们提供了一个暂存数据的存储区域,我们称之为剪 切板,当新的内容送到剪切板后,新的内容将会覆盖掉旧的内容,即剪切板只能保存一份内容。因为剪切板是在内存当中,所以,电脑关闭或者是重启以后,存在剪 切板中的内容将会丢失掉。
除了我们人工的ctrl+C或ctrl+V进行对剪切板的操作以外,我们同时可以使用Windows给我们提供的API来让程序来进行剪切板的复制及粘贴。本篇文章以Visual Studio 2012为编程环境,使用C语言来演示程序操作剪切板的详细教程。
当我们想往剪切板中写入数据时,我们首先需要做的就是打开剪切板:
Bool OpenClipboard(HWND hWndNewOwner);
hWndNewOwner参数指定关联到打开剪切板的窗口句柄,传入NULL表示关联到当前任务。每次只允许一个进程打开并访问。当打开后,操作完剪切板以后,就必须要关闭剪切板,因为剪切板每次只能允许一个进程对其进行访问。如果打开剪切板后不关闭,除非程序结束,否则其他进程就无法使用剪切板。
当我们打开剪切板后,需要做的操作便是清空剪切板,在写入剪切板数据之前,我们必须得先清空剪切板,得到剪切板的操控权:
Bool EmptyClipboard(void)
当完成以上两个操作以后,我们开始为剪切板分配内存:
HGLOBAL GlobalAlloc(UINT uFlags, SIZE_T dwBytes);
第一个参数为分配内存属性,可以是以下内存属性:
GMEM_FIXED | 分配一块固定的内存去续,不允许系统移动,这时返回值是一个指针。 |
GMEM_MOVEABLE | 分配一块可移动的内存区域,实际上内存块在物理内存中是不可移动的,这里的可移动指的是在应用程序 的默认逻辑堆内可以移动。返回值是内存对象的句柄。可以通过调用GlobalLock()函数讲一个句柄转化为 一个指针,这个标志不能和GMEM_FIXED同时使用。 |
GMEM_ZEROINT | 初始化内存对象为全0,如果不用这个标志,内存对象将为不确定的内 |
GHND | GMEM_MOVEABLE和GMEM_ZEROINT联合使用,即可移动同时初始化为0 |
GPTR | GMEM_FIXED和GMEM_ZEROINT同时使用,即不可移动同时初始化为0 |
第二个参数为分配的大小。如果成功则指向该内存,如果失败则返回NULL。
如果我们分配内存的参数一的内存属性为GMEM_FIXED或GPTR,获得的便是一个指向内存区域的指针,不需要进行锁定内存及解锁内存的操作,直接使用memcpy函数将数据复制到分配的内存区域中即可,如果内存属性为GMEM_MOVEABLE或GHND,获得的便是一块内存区域,我们需要将内存区域转化为一个指针:
LPVOID GlobalLock(HGLOBAL hMem);
如果分配内存时分配的内存属性为GMEM_MOVEABLE或GHND,那么就需要锁定内存,锁定由GlobalAlloc分配的内存,并将内存对象的锁定计数器+1。如果该函数成功,则返回内存区域的起始地址指针,失败则返回NULL,GlobalLock会将计数器加1,而GlobalUnlock函数将使计数器减1。对于每次GlobalLock的每一次调用,都必须相应的调用一次GlobalUnlock函数。否则被锁定的内存空间不能够被移动或释放。直到计数器为0时被锁定的内存快才会被移动或者是释放。(更详细的解释请参考MSDN文档:GlobalLock function(Windows))
如果执行成功,返回的便是内存区域的起始地址指针,我们可以使用memcpy将数据复制到该片内存区域,当执行完毕复制以后,我们需要解除锁定的内存:
BOOL GlobalUnlock(HGLOBAL hMem);
参数1为使用分配内存返回的内存区域。
当内存分配完毕后,便可以将数据写入剪切板了。
HANDLE SetClipboardData(UINT uFormat, HANDLE hMem);
参数1为剪切板的数据格式,可以是以下格式:
CF_TEXT | 以NULL结尾的ANSI字符集字符串。它在每行末尾包含一个carriage return和linefeed字符,这是最简单的剪切板数据格式 |
CF_OEMTEXT | 含有文字数据(与CF_TEXT类似)的内存块。但是它使用的是OEM字符集。 |
CF_UNICODETEXT | 含有Unicode文字的内存快。与CF_TEXT类似,它在每一行的末尾包含一个carriage return和linefeed字符,以及一个NULL字符(两个0字节)以表示数据结束。CF_UNICODETEXT针对UNICONDE格式 |
CF_SYLK | 包含Microsoft 「符号连结」数据格式的整体内存块。这种格式用在Microsoft的Multiplan、Chart和Excel程序之间交换数据,它是一种ASCII码格式。 |
CF_DIF | 包含数据交换格式(DIF)之数据的整体内存块。用于把数据送到VisiCalc电子表格程序中。这也是一种ASCII码格式 |
CF_BITMAP | 与设备相关的位图格式。位图是通过位图句柄传送给剪贴簿的。 |
CF_DIB | 定义一个设备无关位图的内存块。 |
CF_PALETTE | 调色盘句柄。 |
CF_METAFILEPICT | 以旧的metafile格式存放的「图片」。 |
CF_ENHMETAFILE | 增强型metafile(32位Windows支持的)句柄。 |
CF_PENDATA | 与Windows的笔式输入扩充功能联合使用 |
CF_WAVE | 声音(波形)文件。 |
CF_RIFF | 使用资源交换文件格式(Resource Interchange File Format)的多媒体数据。 |
CF_HDROP | 与拖放服务相关的文件列表。 |
该数据表使用谷歌自动翻译完成,如果英文较好,可查看MSDN文档:Standard Clipboard Formats(Windows)
参数2为分配的内存区域。如果执行成功,则返回数据句柄,否则返回NULL。
当完成对剪切板的操作以后,我们还需要关闭剪切板:
Bool CloseClipboard(void);
直接调用该函数便可关闭剪切板,只有执行此函数后,其他进程才能使用剪切板,关闭剪切板后,当前进程就不能写入数据。
如果我们想获取剪切板中数据,可以使用GetClipboardData函数:
HANDLE GetClipboardData(UINT uFormat);
参数1为剪切板的数据格式,参见:剪切板的数据格式
如果执行成功,则返回数据句柄,否则返回NULL。
下面是代码例程:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <Windows.h> int main(int argc, char * argv[]) { HGLOBAL hMemory; LPTSTR lpMemory; char * content = "蓝雨麦郎版权所有"; // 待写入数据 int contentSize = strlen(content) + 1; if(!OpenClipboard(NULL)) // 打开剪切板,打开后,其他进程无法访问 { puts("剪切板打开失败"); return 1; } if(!EmptyClipboard()) // 清空剪切板,写入之前,必须先清空剪切板 { puts("清空剪切板失败"); CloseClipboard(); return 1; } if((hMemory = GlobalAlloc(GMEM_MOVEABLE, contentSize)) == NULL) // 对剪切板分配内存 { puts("内存赋值错误!!!"); CloseClipboard(); return 1; } if((lpMemory = (LPTSTR)GlobalLock(hMemory)) == NULL) // 将内存区域锁定 { puts("锁定内存错误!!!"); CloseClipboard(); return 1; } memcpy_s(lpMemory, contentSize, content, contentSize); // 将数据复制进入内存区域 GlobalUnlock(hMemory); // 解除内存锁定 if(SetClipboardData(CF_TEXT, hMemory) == NULL) { puts("设置剪切板数据失败!!!"); CloseClipboard(); return 1; } system("pause"); return 0; }
转载于:https://www.cnblogs.com/cnlyml/archive/2013/03/02/2940434.html
最后
以上就是辛勤鲜花为你收集整理的Windows 剪切板API详解的全部内容,希望文章能够帮你解决Windows 剪切板API详解所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复