简体   繁体   English

如何安全正确地创建Windows剪贴板的备份?

[英]How do I safely and correctly create a backup of the Windows clipboard?

I'm trying to create a backup of the Windows clipboard. 我正在尝试创建Windows剪贴板的备份。 Basically what I'm doing is using EnumClipboardFormats() to get all of the formats that exist on the clipboard currently, and then for each format, I'm calling GetClipboardData(format) . 基本上我正在做的是使用EnumClipboardFormats()来获取当前剪贴板上存在的所有格式,然后对于每种格式,我调用GetClipboardData(format)

Part of backing up the data obviously involves duplicating it. 备份数据的一部分显然涉及重复数据。 I do that by calling GlobalLock() (which "Locks a global memory object and returns a pointer to the first byte of the object's memory block." ) on the data returned by GetClipboardData() , then I fetch the size of the data by calling GlobalSize() , and then finally I do a memcpy() to duplicate the data. 我这样做是通过调用GlobalLock()“锁定一个全局内存对象并返回指向对象内存块的第一个字节的指针。” )对GetClipboardData()返回的数据,然后我获取数据的大小调用GlobalSize() ,最后我做一个memcpy()来复制数据。 I then of course call GlobalUnlock() when I'm done. 然后,当我完成时,我当然会调用GlobalUnlock()

Well, this works... most of the time. 嗯,这很有用......大多数时候。 My program crashes at the GlobalLock() if the clipboard contains data with the format CF_BITMAP or CF_METAFILEPICT . 如果剪贴板包含格式为CF_BITMAPCF_METAFILEPICT的数据,我的程序将在GlobalLock()崩溃。 After reading this Old New Thing blog post ( http://blogs.msdn.com/b/oldnewthing/archive/2007/10/26/5681471.aspx ) I found out why the crash occurs: apparently not all data on the clipboard is allocated using GlobalAlloc() (such as CF_BITMAP data), and so calling GlobalLock() on that data causes a crash. 在阅读了这篇Old New Thing博客文章( http://blogs.msdn.com/b/oldnewthing/archive/2007/10/26/5681471.aspx )后,我发现了崩溃发生的原因:显然不是剪贴板上的所有数据使用GlobalAlloc() (例如CF_BITMAP数据)分配,因此对该数据调用GlobalLock()会导致崩溃。

I came across this MSDN article ( http://msdn.microsoft.com/en-us/library/ms649014#_win32_Memory_and_the_Clipboard ) and it gives a list of clipboard formats and how they are freed by the system. 我遇到了这篇MSDN文章( http://msdn.microsoft.com/en-us/library/ms649014#_win32_Memory_and_the_Clipboard ),它给出了一个剪贴板格式列表以及它们如何被系统释放。 So what I did was hard-code into my program all of the clipboard formats ( CF_* ) that are not freed by the GlobalFree() function by the system, and I simply don't back up those formats; 所以我所做的是将所有剪贴板格式( CF_ * )硬编码到我的程序中,系统没有通过GlobalFree()函数释放,我只是不备份这些格式; I skip them. 我跳过它们。

This workaround seems to work well, actually. 实际上,这种解决方法似乎运作良好。 Even if a bitmap is on the clipboard, or "special" data (such as rows copied from Excel to the clipboard), my clipboard backup function works well and I haven't experienced any crashes. 即使位图放在剪贴板上,或“特殊”数据(例如从Excel复制到剪贴板的行),我的剪贴板备份功能也能正常运行,而且我没有遇到任何崩溃。 Also, even if there's a bitmap on the clipboard and I skip some formats during the backup (like CF_BITMAP ), I can still Ctrl+V paste the originally-copied bitmap from the clipboard after restoring my clipboard backup, as the bitmap is represented by other formats on the clipboard as well that don't cause my program to crash ( CF_DIB ). 此外,即使剪贴板上有位图并且我在备份期间跳过一些格式(如CF_BITMAP ),我仍然可以在恢复剪贴板备份后按Ctrl + V从剪贴板粘贴原始复制的位图,因为位图由剪贴板上的其他格式也不会导致我的程序崩溃( CF_DIB )。

However, it's a workaround at best. 但是,这是最好的解决方法。 My fear is that one of these times some weird format (perhaps a private one, ie one between CF_PRIVATEFIRST and CF_PRIVATELAST , or maybe some other type) will be on the clipboard and my program, after calling GlobalLock() , will crash again. 我担心的是,其中一种奇怪的格式(可能是私有格式,即CF_PRIVATEFIRSTCF_PRIVATELAST之间的一种 ,或者可能是其他类型)将在剪贴板上,我的程序在调用GlobalLock()后会再次崩溃。 But since there doesn't seem to be much documentation explaining the best way to back up the clipboard, and it's clear that GlobalLock() does not work properly for all datatypes (unfortunately), I'm not sure how to handle these situations. 但由于似乎没有太多文档解释备份剪贴板的最佳方法,并且很明显GlobalLock() 不能正常处理所有数据类型(不幸的是),我不知道如何处理这些情况。 Is it safe to assume that all other formats -- besides the formats listed in the previous URL that aren't freed by GlobalFree() -- can be "grabbed" using GlobalLock() ? 是否可以安全地假设所有其他格式 - 除了前一个URL中列出的格式,不被GlobalFree()释放 - 可以使用GlobalLock() “抓取”?

Any ideas? 有任何想法吗?

This is folly, as you cannot 100% backup/restore the clipboard. 这是愚蠢的,因为你无法100%备份/恢复剪贴板。 Lots of apps used delayed rendering, and the data is not actually on the clipboard. 许多应用程序使用延迟渲染,数据实际上不在剪贴板上。 When you request to paste, they get notified and produce the data. 当您请求粘贴时,它们会收到通知并生成数据。 This would take several minutes and hundreds of MB for large amounts of data from apps like Excel. 对于来自Excel等应用程序的大量数据,这将需要几分钟和几百MB。 Take a look at the number of formats listed on the clipboard when you copy from Excel. 从Excel复制时,请查看剪贴板上列出的格式数。 There will be more than two dozen, including Bitmap, Metafile, HTML. 将有二十多个,包括Bitmap,Metafile,HTML。 What do you think will happen if you select 255x25000 cells in Excel and copy that? 如果在Excel中选择255x25000单元格并复制它,您认为会发生什么? How large would that bitmap be? 该位图有多大? Tip: save any open documents before attempting this, as you're likely going to have to reboot. 提示:在尝试此操作之前保存所有打开的文档,因为您可能需要重新启动。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM