我尝试创建Windows剪贴板的备份。基本上我所做的是使用EnumClipboardFormats()
来获取剪贴板上当前存在的所有格式,然后针对每种格式,我调用GetClipboardData(format)
。
备份数据的一部分显然涉及到复制数据。我通过对GetClipboardData()
返回的数据调用GlobalLock()
(即"Locks a global memory object and returns a pointer to the first byte of the object's memory block."
)来完成此操作,然后通过调用GlobalSize()
获取数据的大小,最后执行memcpy()
来复制数据。完成后,我当然会调用GlobalUnlock()
。
好吧,大多数情况下都是这样的。如果剪贴板包含格式为CF_BITMAP或CF_METAFILEPICT的数据,我的程序会在GlobalLock()
处崩溃。在阅读了Old New Thing的博客文章(https://devblogs.microsoft.com/oldnewthing/20071026-00/?p=24683)后,我发现了崩溃发生的原因:显然,并非剪贴板上的所有数据都是使用GlobalAlloc()
分配的(例如CF_BITMAPdata),因此对该数据调用GlobalLock()
会导致崩溃。
我遇到了this MSDN article,它给出了一个剪贴板格式列表,以及系统是如何释放它们的。因此,我所做的是将系统没有通过GlobalFree()
函数释放的所有剪贴板格式(CF_*)硬编码到我的程序中,并且我只是不备份这些格式;我跳过它们。
实际上,这种变通方法看起来效果不错。即使剪贴板上有位图或“特殊”数据(例如从Excel复制到剪贴板的行),我的剪贴板备份功能运行良好,没有遇到任何崩溃。此外,即使剪贴板上有位图,我在备份过程中跳过了一些格式(如CF_BITMAP),在恢复剪贴板备份后,我仍然可以按Ctrl+V从剪贴板粘贴原始复制的位图,因为位图在剪贴板上也以其他格式表示,不会导致程序崩溃(CF_DIB)。
不过,这充其量只是一个变通办法。我担心的是,其中一个时候,一些奇怪的格式(可能是一个私有的,即CF_PRIVATEFIRST和CF_PRIVATELAST之间的一个,或者可能是其他类型的)将在剪贴板上,我的程序在调用GlobalLock()
后将再次崩溃。但由于似乎没有太多文档解释备份剪贴板的最佳方法,而且很明显GlobalLock()
并不能对所有数据类型都正常工作(不幸的是),我不知道如何处理这些情况。假设所有其他格式--除了前面的URL中列出的GlobalFree()
没有释放的格式--都可以使用GlobalLock()
“抓取”吗?
有什么想法吗?
1条答案
按热度按时间1wnzp6jl1#
这是愚蠢的,因为你不能100%备份/恢复剪贴板。很多应用程序使用延迟渲染,数据实际上并不在剪贴板上。当你请求粘贴时,它们会收到通知并生成数据。对于来自Excel等应用程序的大量数据,这将需要几分钟的时间和数百MB的空间。当您从Excel复制数据时,请查看剪贴板上列出的格式数量。其中包括位图、图元文件、HTML等二十多个。如果您在Excel中选择255 x25000个单元格并进行复制,您认为会发生什么情况?该位图会有多大?提示:在尝试此操作之前,请保存所有打开的文档,因为您可能需要重新启动。