gpt4 book ai didi

winapi - Windows clipboard::GetClipboardData() for CF_DIBV5 导致剪贴板上的图像被修改和损坏?

转载 作者:行者123 更新时间:2023-12-04 04:10:40 25 4
gpt4 key购买 nike

我发现(至少)Win10 在通过 Alt-PrtScrn(可能是合成格式)创建的 CF_DIBV5 上调用 ::GetClipboardData() 会导致图像被修改(并且基本上被破坏).

例如,在 ON_WM_CLIPBOARDUPDATE() 的处理程序上,下面的简单循环将导致损坏(请注意,您需要使用 Debug模式,这样::GetClipboardData() 就不会被优化掉)。

要进行测试,首先不要运行处理剪贴板的应用,使用 Alt-PrntScrn 捕获数据,然后将其粘贴到画图。现在运行处理剪贴板的应用程序(下面的示例)。重复 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();
}
}

要启用处理程序,您需要调用 AddClipboardFormatListener(GetSafeHwnd()); 类似 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 然后 RemoveClipboardFormatListener( GetSafeHwnd());void CMainFrame::OnDestroy()

那么这是 Win10(和其他 Windows 版本)中的错误,还是我应该做一些示例没有做的其他事情? (我知道存在其他格式,但 CF_DBIV5 是我想要的)。

我使用的是版本 1903(操作系统内部版本 18362.838)

请注意示例图片左侧有右侧项目,左下角有一些垃圾像素。我在应用程序运行时按 alt-prtscrn,粘贴在画图中。

sample pic

我的分辨率是 2560x1600。

这是一个会导致问题的项目的链接:

Sample Project

最佳答案

您可以在 documentation 中找到以下说明:

The red, green, and blue bitfield masks for BI_BITFIELD bitmaps immediately follow the BITMAPINFOHEADER, BITMAPV4HEADER, and BITMAPV5HEADER structures. The BITMAPV4HEADER and BITMAPV5HEADER structures contain additional members for red, green, and blue masks as follows.

enter image description here

BITMAPINFOHEADERbiCompression 成员设置为 BI_BITFIELDS 并且函数接收类型为 LPBITMAPINFO 的参数时, 颜色 mask 将紧随标题。颜色表(如果存在)将遵循颜色掩码。 BITMAPCOREHEADER 位图不支持颜色 mask 。

当您正确处理 CF_DIBV5 时,您将成功绘制图像。以下是Win32 C++的例子,您可以引用:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static UINT uFormat = (UINT) -1;
HDC hdcMem = NULL;
RECT rc = {0};
BYTE * pData = NULL;
BITMAPV5HEADER *pDibv5Info = NULL;

switch (message)
{
case WM_CLIPBOARDUPDATE:
{
if (IsClipboardFormatAvailable(CF_DIBV5))
{
uFormat = CF_DIBV5;

::CloseClipboard();

GetClientRect(hWnd, &rc);
InvalidateRect(hWnd, &rc, TRUE);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);

switch (uFormat)
{
case CF_DIBV5:
hdcMem = CreateCompatibleDC(hdc);
if (hdcMem != NULL)
{
if (::OpenClipboard(hWnd)) {
HANDLE hglobal = ::GetClipboardData(uFormat);
pData = (BYTE*)GlobalLock(hglobal);
if (pData)
{
pDibv5Info = (BITMAPV5HEADER *)pData;
int offset = pDibv5Info->bV5Size + pDibv5Info->bV5ClrUsed * sizeof(RGBQUAD);
if (pDibv5Info->bV5Compression == BI_BITFIELDS)
offset += 3 * sizeof(DWORD); //three DWORD color masks that specify the red, green, and blue components

pData += offset;
SetDIBitsToDevice(hdc, 20, 20, pDibv5Info->bV5Width, pDibv5Info->bV5Height, 0, 0, 0, pDibv5Info->bV5Height, pData, (BITMAPINFO *)pDibv5Info, 0);
}

GlobalUnlock(hglobal);
::CloseClipboard();
}
}
break;
}
EndPaint(hWnd, &ps);
}
break;
}

在我的应用程序窗口中绘制的正确图像:

enter image description here

我可以在没有代码的情况下重现同样的问题:

if (pDibv5Info->bV5Compression == BI_BITFIELDS)
offset += 3 * sizeof(DWORD);

损坏的图像:

enter image description here

关于winapi - Windows clipboard::GetClipboardData() for CF_DIBV5 导致剪贴板上的图像被修改和损坏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61788908/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com