这玩意儿原理挺简单的;但真的实现起来细节特别多、特别麻烦也特别容易出错。
参与这玩意儿的角色大概分为四类:
1、用户,计算机的操作者
2、内容提供者,如资源管理器、word、记事本、画图以及截屏软件等
3、剪贴板实现者,一般是操作系统(或其提供的桌面环境管理器)
4、内容接收者,如另一个资源管理器、记事本、word/excel、图像编辑软件等
其中,剪贴板实现者主要提供一组接口,允许其它角色通过这个接口把资源上传给剪贴板、或者从剪贴板获取资源——至于剪贴板,那只是一块任何人都可以访问的内存而已。
内容提供者则需要响应CTRL+C/CTRL+X等快捷键,把资源上传到系统剪贴板——当然,它也完全可以不理睬CTRL+C快捷键,而是通过自带的菜单或其它快捷键触发“资源上传系统剪贴板”功能。
类似的,内容接收者要响应CTRL+V快捷键,把剪贴板内容取下来、插入自己的编辑环境。
同样的,它也可以不理CTRL+V快捷键,而是用上下文菜单获取剪贴板内容。比如,通过菜单选择“只粘贴文本”还是“粘贴文本以及格式”。
当然,同时响应CTRL+V和菜单也是可行的;有的软件也允许你配置它,使得它响应CTRL+V的行为从“粘贴文本及格式”改为“默认接受无格式文本”。
类似的,当鼠标选中一些对象、开始拖曳时,就会触发“drag start”事件;停止拖曳并松开左/右键,则触发“drag end”事件。你只需像响应CTRL+C/CTRL+V一样写一个事件响应程序、然后在里面调用系统剪贴板接口就好了。
这里面真正的困难在于:需要拷贝的东西是千变万化的。可能是记事本里面的一段话、也可能是word里面一段图文混排的富文本;可能是excel的一整个sheet页面,也可能是文件系统里面一个40G的大文件——甚至是隔一个选一个、一共8000个400G的媒体文件。
懂得编程的话,就知道文本只是一串数字,这串数字是ascii或者Unicode编码的;而富文本则不光有数字编码的文本,还有一些格式标签;图片呢,又是数字编码的一个个像素点的组合(还可能有很多种格式);excel的sheet页面是一个复杂的运行时对象;视频文件……那么大怎么可能放到区区8G内存里!
这下麻烦大了,对吧……
因此,Windows提供了一组标准格式识别标记,允许你往剪贴板上传纯文本、位图数据等信息;如果你需要借助剪贴板传递的对象过于复杂,它还有三个DSP开头的格式(CF_DSPTEXT、CF_DSPBITMAP和CF_DSPMETAFILEPICT),允许你通过剪贴板在自己写的程序之间交换数据。或者,你也可以注册新的数据格式并上传数据——比如,注册一个file path/URI格式,然后把需要拷贝的文件路径上传到剪贴板,自然就能通过剪贴板“复制文件”或者往网上上传文件了。
说白了,在复制文件的场景里,这里传的仅仅是源文件路径,文件本身没动;选定了目标后,才把源文件路径、目标路径作为参数开始执行复制/移动操作。
类似的,在网络上传这个场景里,也是把源文件路径当成参数,丢给了upload相关函数……
不仅如此。每次剪贴板操作都还可以上传不同类型的多个数据。比如,可以同时上传一个富文本数据、一个纯文本数据、一个选择区域的截图数据;那么接受剪贴板内容的应用程序就可以根据自身需要,选择读取其中一个。这就是我前面提到的“粘贴文本及格式”和“仅粘贴文本”的实现原理(当然,程序员的事,极少限死一条道的。比如你完全可以写个算法剔除富文本里面的格式标签、内链对象,仅仅保留纯文本,从而实现“把剪贴板里面的富文本当纯文本粘贴”功能)。
知道了原理,那么,写一个剪贴板管理器,完成“给用户展示最近提交到剪贴板的若干项内容、并允许用户选择自历史粘贴”、“把剪贴板内容存入硬盘,系统重启后仍然可以粘贴”、“在家里电脑上按CTRL+C,在办公室电脑按CTRL+V”、“在虚拟机里面的Linux桌面按CTRL+C,到外部宿主机的Windows桌面按CTRL+V”之类花里胡哨的功能,你心里已经有方案了吧。