闲来无事,说说Windows剪贴板 -- 剪贴板概述部分

来源:互联网 发布:淘宝打不开我的购物车 编辑:程序博客网 时间:2024/06/04 19:37


<小fisher首发office精英俱乐部-http://www.officefans.net/cdb/,转载请注明出处>
  首先,讨论一下剪贴板是什么
  Windows的帮助文件中对剪贴板的描述是这样的:剪贴板是从一个地方复制或移动并打算在其他地方使用的信息的临时存储区域。可以选择文本或图形,然后使用“剪切”或“复制”命令将所选内容移动到剪贴板,在使用“粘贴”命令将该内容插入到其他地方之前,它会一直存储在剪贴板中。例如,您可能要复制网站上的一部分文本,然后将其粘贴到电子邮件中。大多数 Windows 程序中都可以使用剪贴板。
  对于经常使用Ctrl+C/X、Ctrl+V的Windows用户来说,这个解释是非常易懂并且符合人们感观上的认识的。
  既然我们今天讨论的话题是如何在VBA程序中通过API调用剪贴板,那就先看看微软MSDN中对于剪贴板的定义吧:剪贴板是一组用于在多个应用程序之间交换数据的函数和消息(原文:The clipboard is a set of functions and messages that enable applications to transfer data)。
  呵呵,是不是有些晕?没关系,因为这句话是针对C/C++程序员给出的说明,我们仍然可以按习惯上的理解把它当做一个对象(使用过VB6的同志们可能更容易理解,因为VB6中确实有一个名字叫ClipBoard的对象,它其实是VB对windows的剪贴板API函数封装后产生的真正的对象)。
  然后,再来看看这个对象有什么特点,又是如何工作的呢?概括来说,剪贴板有以下的特性(这是我个人总结的,不一定正确或精确,也不一定全面):
公开性
剪贴板中的数据存放在全局内存中,因此大部分的windows应用程序都可以访问其中的数据,在遵守相关API函数约定的前提下,应用程序可以自由地打开剪贴板(OpenClipboard),读取剪贴板内的数据(GetClipboardData)、或者清空剪贴板(EmptyClipboard)、然后设置剪贴板内的数据(SetClipboardData),最后关闭剪贴板(CloseClipboard);
独占性
既然剪贴板是公开的,那么多个程序同时访问必然会导致冲突,比如数据互相覆盖。因此,Windows规定应用程序对剪贴板的访问是独占性的,当一个应用程序使用OpenClipboard打开剪贴板之后,其他程序 就不可以再访问剪贴板,直至前一程序使用CloseClipboard关闭剪贴板 。通常我们使用剪贴板的时候不会感觉受其他程序的影响,这是因为剪贴板内的数据操作都是在内存中进行的,速度非常快,对于特大块的数据,应用程序还可以选择延时处理(Delayed Rendering)机制以保证速度。但是,我们在对剪贴板编程的时候要注意以下两点:1)每次使用完剪贴板之后一定要记得使用CloseClipBoard关闭 它;2)在OpenClipboard和CloseClipboard之间不要放置耗时很长的代码,以免影响其他程序正常工作。
设置剪贴板内数据的应用程序窗口被称为剪贴板数据拥有者(ClipboardOwner),可以通过GetClipboardOwner函数获得它的句柄。反过来说,如果一个应用程序想向剪贴板中放入数据,需要先成为ClipboardOwner。程序要成为ClipboardOwner需要先将自己的句柄传给OpenClipboard函数,如果剪贴板中已经有数据存在,还需要先调用EmptyClipboard;
多元性
剪贴板中可以同时存放多种格式的数据,各自放在全局内存的不同位置 ;剪贴板中的数据有标准格式/预定义格式的,如文本、位图、Wav声音……;也有非标准格式/用户自定义格式,比如word中的域和公式、Excel中的图表
可检索性
对于每种在剪贴板中存放过的格式,Windows都会给它分配一个独特的长整型编号,通过这个编号可以知道对应的数据格式的名称(GetClipboardFormatName),或者 查询对应的数据在剪贴板中是否存在(IsClipBoardFormatAvailable),如果存在,还可以通过这个编号找到对应的数据在内存中存放的位置(GetClipboardData);
对于标准格式,这个编号是固定的,可以通过VB6自带的APIViewer查询以CF_开头的常量得到,比如:
Public Const CF_TEXT = 1
Public Const CF_BITMAP = 2
Public Const CF_METAFILEPICT = 3
Public Const CF_SYLK = 4
……
对于非标准格式,这个编号由提供此格式数据的应用程序给此格式定义一个名称,然后将此名称传递给RegisterClipboardFormat函数,如果此名称已经存在,函数将返回此名称对应的编号,如果此名称不存在,函数将返回一个之前未使用的编号,在系统关机重启之前,这个名称和编号可以一直使用下去。
可监视性
有一组特别的窗口可以持续监视剪贴板内的数据变化,这组窗口被称作剪贴板观察程序(ClipboardViewer),由它们构成的这个小圈子叫作剪贴板观察程序链ClipBoardViewerChain,每当剪贴板内数据发生变化时,windows将向消息链中的第一个窗口发送一个WM_DRAWCLIPBOARD消息,再由它转发给第二个……直至消息到达消息链中的最后一个窗口,同样,当消息链中的成员发生变化时,每个窗口都会收到一个WM_CHANGECBCHAIN消息;
通过SetClipboardViewer函数,应用程序可以将自己的窗口句柄告诉windows,从而注册成为剪贴板观察程序链中的一员;通过ChangeClipboardChain函数,应用程序可以退出剪贴板观察程序链而不影响它后面的窗口继续接收相关消息。
希望以上文字能对大家重新认识剪贴板能够有所帮助。休息一会儿,我们再讨论剪贴板在Office VBA中的用途。