本文由danny发表于http://blog.youkuaiyun.com/danny_share
前面两篇废话了这么多,本文开始上干货。
本文从剪贴板概念、剪贴板内容监听,普通数据类型,打开剪贴板,读剪贴板,写剪贴板、API汇总、他山之石、通过剪贴板实现进程间通信和总结共10个方面来较为深入地探讨Windows剪贴板的机制和使用。
说明:建议先下载本文配套工程,其中
(1) ClipBoardDemo工程主要演示剪贴板相关API使用
(2) MainProcess工程、ASubProcess工程、BSubProcess工程分别用于演示本文第九部分进程间通信的主进程和两个子进程
下载地址:http://download.youkuaiyun.com/detail/danny_share/7703279
一.剪贴板概念
剪贴板是系统级的堆空间,且任何一个应用程序都具备访问权,主要涉及复制(Ctrl+C),剪切(Ctrl+X)、粘贴(Ctrl+V)、清空和监听五个操作。
二.剪贴板内容监听
1.开始监听
【a】SetClipboardViewer将窗口加入监听链
【b】一旦剪贴板内容变化,系统会向监听链中的第一个注册监听的窗口发送WM_DRAWCLIPBOARD消息。为什么说是第一个呢?参见“消息链顺序”
【c】通过实验发现,如果新拷贝的内容和原来一样,系统还是会出发消息,说明普通的复制操作不管内容相不相同,都是直接覆盖原来剪贴板中的数据的
2.处理消息
(1)WM_CHANGECBCHAIN
【a】除自己以外,其他进程加入了监听链,或者退出了监听链,系统就会发出这个消息
【b】这里只说明监听者发生了变化,并不表示剪贴板中内容发生变化。
【c】如果存在下一个监听进程,那么需要将该消息发送给下一个监听者
否则下一个监听者将收不到该消息
【d】对于MFC,可通过重载OnChangeCbChain函数实现
(2)WM_DRAWCLIPBOARD
【a】进程首次运行时或者是剪贴板内容发生变化时,进程都会收到这个消息
【b】如果存在下一个监听进程,那么需要将该消息发送给下一个监听者
否则下一个监听者将收不到该消息
【c】对于MFC,可通过重载OnDrawClipboard函数实现
3.停止监听
【a】使用ChangeClipboardChain()函数停止监听
【b】本质是发送WM_CHANGECBCHAIN消息,且将自己从监听链中去除
【c】其他监听进程将会收到WM_CHANGECBCHAIN消息
4.消息链顺序
【a】刚才一直在说当剪贴板内容变化时,进程将会收到WM_DRAWCLIPBOARD消息,然后该进程处理完以后,需向下个监听者发送该消息,那下个监听者是谁呢?
【b】我们在WM_DRAWCLIPBOARD消息处理函数OnDrawClipboard中closeClipboard后sleepl两秒后弹窗
【c】然后拷贝ClipBoardOne.exe三份,依次启动,我们分别取名A、B和C
【d】当剪贴板内容变化时,进程弹出剪贴板变化的顺序也是A、B、C,说明加入监听的顺序和收到消息的顺序是一致的。
三.数据类型
分类 |
ID |
格式 |
说明 |
标准 |
1 |
CF_BITMAP |
位图句柄 |
2 |
CF_DIB |
|
|
3 |
CF_DIBV5 |
包含BITMAPV5HEADER结构且跟着位图颜色空间和位图数据 |
|
4 |
CF_DIF |
|
|
5 |
CF_DSPBITMAP |
|
|
6 |
CF_DSPENHMETAFILE |
|
|
7 |
CF_DSPMETAFILEPICT |
|
|
8 |
CF_DSPTEXT |
|
|
9 |
CF_ENHMETAFILE |
|
|
10 |
CF_GDIOBJFIRST |
|
|
11 |
CF_GDIOBJLAST |
|
|
12 |
CF_HDROP |
拖放服务,文件拷贝也是这个类型 |