Windows允许把数据从一个程序传送到另一个程序,它的原理相对简单。
Windows支持不同的预先定义的数据格式:CF_TEXT, CF_OEMTEXT, CF_UNICODETEXT, CF_LOCALE, CF_SYLK, CF_DIF, CF_BITMAP, CF_DIB, CF_PALETTE, CF_TIFF, CF_METAFILEPICT, CF_ENHMETAFILE, CF_PENDATA, CF_WAVE, CF_RIFF, CF_HDROP
程序向剪贴板传输数据时,必须分配一个内存块,并且剪贴板在根本上拥有它。malloc函数不适合此项任务。
GlobalAlloc在实模式中来分配一块内存,它返回一个HGLOBAL类型的句柄。 GlobalReAlloc是再分配函数。 GlobalSize可以得到内存块的大小。 通过GlobalFree释放内存块。 需要访问内存块时调用GlobalLock将句柄转为指针。在锁定期间,Windows将固定虚拟内存中的地址,不再移动。 访问结束后调用GlobalUnlock。 也可以通过指针得到内存句柄GlobalHandle。
首先将需要传送的数据复制到全局内存中, 打开剪贴板OpenClipboard, 清空剪贴板EmptyClipboard, 设置剪贴板数据SetClipboardData, 关闭剪贴板CloseClipboard。
IsClipboardFormatAvailable如果含有数据返回TRUE(非0)。如果含有需要数据: 打开剪贴板OpenClipboard, 得到数据指针GetClipboardData, 完成数据复制后关闭剪贴板CloseClipboard。
打开剪贴板并把数据传送给它时,必须先调用EmptyClipboard,通知Windows释放或删除剪贴板内容。
从某种意义上说,剪贴板只能保存一个数据项,可以再EmptyClipboard和CloseClipboard调用之间多次调用setClipboardData ,每次都使用不同的剪贴板格式。利用这种方法可以使字符串不仅能为从剪贴板读取文本的程序使用,也可以为从剪贴板读取位图和元文件的程序使用。当然,这些程序不知道文件或位图包含了一个字符串。
下次调用EmptyClipboard时,Windows将释放或删除保留的多个句柄。再将不同文本格式,不过的位图格式添加到剪贴板时,不要使用这种技术。
通过打开剪贴板,然后调用EnumClipboardFormats,程序可以确定剪贴板存储所有格式。可以通过CountClipboardFormats得到剪贴板中格式的个数。
当把数据放入剪贴板时,一般说要制作一份数据的备份。并将包含副本的内存块句柄传给剪贴板。对非常大的数据项来说,这种方法会浪费内存空间。如果用户不把数据粘贴到另一个程序,那么在其他内容取代之前,它将一直占据内存空间。
通过“延迟生成”的技术可以避免这个问题。在SetClipboardData调用时用NULL传给剪贴板。当有程序调用GetClipboardData时,Windows会检查内存是否为NULL。如果是,Windows将传给剪贴板所有者发送消息,要求获得数据实际句柄。这时,程序必须提供这个句柄。
“延迟生成”需要处理三个消息: 当另一个程序调用GetClipboardData时发送WM_RENDERFORMAT, 如果程序仍然是剪贴板所有者,那么它退出时收到WM_RENDERALLFORMATS, 当另一程序调用EmptyClipboard时发送WM_DESTROYCLIPBOARD。
可能想用剪贴板来存储私有数据。来实现在一个程序内部传送数据。有几种使用私有数据的方法,最简单的方法用标准剪贴板格式存储只有一个应用程序才能理解的数据。这种情况可以使用CF_DSPTEXT、CF_DSPBITMAP、CF_DSPMETAFILEPICT或CF_DSPENHMETAFILE。这些格式允许Windows按文本、位图或元文件来浏览或显示数据。使用这种方法时需要确定数据是否来自程序的另一个实例。可以通过GetClipboardOwner得到剪贴板所有者,再通过GetClipboardOwner得到窗口句柄的类名。如果类名相同,那么数据来自程序另一个实例。
第二中方法涉及CF_OWNERDISPLAY标志。