【发布时间】:2020-05-14 03:40:17
【问题描述】:
我在(至少)Win10 上发现,在通过 Alt-PrtScrn(可能是合成格式)创建的 CF_DIBV5 上调用 ::GetClipboardData() 会导致图像被修改(并且基本上已损坏)。
例如,在ON_WM_CLIPBOARDUPDATE() 的处理程序上,下面的简单循环将导致损坏(请注意,您需要使用调试模式,因此不会优化 ::GetClipboardData())。
要进行测试,首先不要运行处理剪贴板的应用,使用 Alt-PrntScrn 捕获数据,然后将其粘贴到 Paint。现在运行处理剪贴板的应用程序(下面的示例)。重复 Alt-PrntScrn 过程,您会发现捕获窗口的右侧最终位于左侧而不是该区域的中心是不同的。
void CMainFrame::OnClipboardUpdate()
if (::OpenClipboard(AfxGetMainWnd()->m_hWnd)) {
UINT uformat=0;
while ((uformat=::EnumClipboardFormats(uformat))!=0) {
if (uformat==CF_DIBV5) {
// get the data - run in debug mode so not optimized out
HGLOBAL hglobal=::GetClipboardData(uformat);
}
}
// clean up
::CloseClipboard();
}
}
要启用处理程序,您需要在 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 中调用 AddClipboardFormatListener(GetSafeHwnd());,然后在 void CMainFrame::OnDestroy() 上调用 RemoveClipboardFormatListener(GetSafeHwnd());
那么这是 Win10(和其他 Windows 版本)中的一个错误,还是我应该做一些示例没有做的事情? (我知道存在其他格式,但 CF_DBIV5 是我想要的)。
我使用的是 1903 版(操作系统内部版本 18362.838)
请注意,示例图片左侧有右侧项目,左下方有一些垃圾像素。我在应用程序运行时 alt-prtscrn,粘贴在油漆中。
我的分辨率是 2560x1600。
这是一个会导致问题的项目的链接:
【问题讨论】:
-
为什么要使用
EnumClipboardFormats()来查找1 格式?您可以改用IsClipboardFormatAvailable()。或者,只需无条件调用GetClipboardData(),如果所需格式不可用,则让它失败。 -
我处理更多格式,这只是为了显示问题而提取出来的。
-
@df234987 我无法在 Windows 10 1909 build 18363.778 上重现此问题。您能否显示您的 Windows 版本和显示损坏图像的快照?
-
添加了操作系统版本和示例图片。
-
我在 Windows 10 1903 (OS Build 18362.836) 上测试,它也适用于我。您的 .838 是错字吗?您能否仔细检查一下,如果您显示的
CMainFrame::OnClipboardUpdate()中的代码行引入了此问题?比如去掉CMainFrame::OnClipboardUpdate()的body,这个问题还能重现吗?