Qt 粘贴板获取图片不全,使用windows api 获取粘贴板图片

在偶然中发现Qt程序自带的粘贴板无法正常获取OutLook邮箱中邮件里的图片,获取的图片都不是原图(现象:图片丢失了一部分)。

使用Windows API方法成功解决。(库要加 user32.lib,头文件 windows.h)
代码如下:

/*!
 * \brief 使用windows api获取粘贴板中的图片(不支持粘贴板复制的本地文件)
 * \param filePath 保存文件路径
 */
bool Tool::getWindowsClipboardBmpFile(const QString &filePath)
{
    
    
    HWND hWnd = GetDesktopWindow();                            // 获取安全窗口句柄
    ::OpenClipboard(hWnd);                                     // 打开剪贴板
    HANDLE hBitmap = ::GetClipboardData(CF_BITMAP);            // 获取剪贴板数据句柄
    HDC hDC = ::GetDC(hWnd);                                   // 获取设备环境句柄
    HDC hdcMem = CreateCompatibleDC(hDC);                      // 创建与设备相关的内存环境
    SelectObject(hdcMem, hBitmap);                             // 选择对象
    SetMapMode(hdcMem, GetMapMode(hDC));                       // 设置映射模式
    BITMAP csBitmap;                                           // 得到位图对象
    int index = GetObject(hBitmap, sizeof(BITMAP), &csBitmap);

    if(hBitmap)
    {
    
    
        unsigned long n_BPP, n_Width, n_Height;

        if(index)
        {
    
    
            n_Width   = (unsigned long)csBitmap.bmWidth;
            n_Height  = (unsigned long)csBitmap.bmHeight;
            n_BPP     = (unsigned long)csBitmap.bmBitsPixel;
            long sz   = csBitmap.bmWidth*csBitmap.bmHeight*(csBitmap.bmBitsPixel>>3);
            csBitmap.bmBits = (void *) new BYTE[sz];
            GetBitmapBits((HBITMAP)hBitmap, sz, csBitmap.bmBits);

            qDebug()<< "图片属性为:"<< n_Width<< n_Height<< n_BPP<< csBitmap.bmBits;
        }
        else
        {
    
    
            delete csBitmap.bmBits;
            csBitmap.bmBits = nullptr;

            DeleteObject(hBitmap);

            ::ReleaseDC(hWnd, hDC); // 释放设备环境句柄
            DeleteDC(hdcMem);       // 删除内存环境
            ::CloseClipboard();     // 关闭剪贴板
            qDebug()<< "剪贴板缓冲区中的对象无效";
            return false;
        }

        DWORD *lp_Canvas = new DWORD[ n_Width * n_Height];
        if (n_BPP == 32)
        {
    
    
            for(unsigned long y = 0; y < n_Height; y ++)
            {
    
    
                for(unsigned long x = 0; x < n_Width; x ++)
                {
    
    
                    RGBQUAD * rgb = ((RGBQUAD *) ((char*)(csBitmap.bmBits)
                                                  + csBitmap.bmWidthBytes*y + x*sizeof(DWORD)));

                    lp_Canvas[(n_Height - 1 - y)*n_Width + x] = *((DWORD *)rgb);
                }
            }
        }
        else if(n_BPP == 24)
        {
    
    
            for(unsigned long y = 0; y < n_Height; y ++)
            {
    
    
                for(unsigned long x = 0; x < n_Width; x ++)
                {
    
    

                    RGBTRIPLE rgbi = *((RGBTRIPLE *) ((char*)(csBitmap.bmBits)
                                                      + csBitmap.bmWidthBytes*y + x*3));

                    RGBQUAD rgbq;
                    rgbq.rgbRed   = rgbi.rgbtRed;
                    rgbq.rgbGreen = rgbi.rgbtGreen;
                    rgbq.rgbBlue  = rgbi.rgbtBlue;
                    lp_Canvas[(n_Height - 1 - y)*n_Width + x] = *((DWORD *)(&rgbq));
                }
            }
        }

        unsigned long n_Bits = 32;
        FILE *pFile = fopen(filePath.toLatin1().data(), "wb");
        if(pFile == nullptr)
        {
    
    
            delete csBitmap.bmBits;
            csBitmap.bmBits = nullptr;

            delete lp_Canvas;
            lp_Canvas = nullptr;

            pFile = nullptr;

            DeleteObject(hBitmap);

            ::ReleaseDC(hWnd, hDC); // 释放设备环境句柄
            DeleteDC(hdcMem);       // 删除内存环境
            ::CloseClipboard();     // 关闭剪贴板

            qDebug()<< "文件打开失败";
            return false;
        }

        // 保存位图文件头
        BITMAPFILEHEADER fileHeader;
        fileHeader.bfType = 0x4d42;
        fileHeader.bfSize = 0;
        fileHeader.bfReserved1 = 0;
        fileHeader.bfReserved2 = 0;
        fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
        fwrite((char*)&fileHeader, sizeof(fileHeader), 1, pFile);

        // 保存位图信息标题
        BITMAPINFOHEADER infoHeader;
        infoHeader.biSize = sizeof(infoHeader);
        infoHeader.biWidth = n_Width;
        infoHeader.biHeight = n_Height;
        infoHeader.biPlanes = 1;
        infoHeader.biBitCount = (unsigned short)( n_Bits & 0xffff);
        infoHeader.biCompression = BI_RGB;
        infoHeader.biSizeImage = 0;
        infoHeader.biXPelsPerMeter = 0;
        infoHeader.biYPelsPerMeter = 0;
        infoHeader.biClrUsed = 0;
        infoHeader.biClrImportant = 0;
        fwrite((char*)&infoHeader, sizeof(infoHeader), 1, pFile);
        fwrite((char*)lp_Canvas, 1, (n_Bits >> 3) * n_Width*n_Height, pFile);
        fclose(pFile);

        delete csBitmap.bmBits;
        csBitmap.bmBits = nullptr;

        delete lp_Canvas;
        lp_Canvas = nullptr;

        pFile = nullptr;

        DeleteObject(hBitmap);

        ::ReleaseDC(hWnd, hDC); // 释放设备环境句柄
        DeleteDC(hdcMem);       // 删除内存环境
        ::CloseClipboard();     // 关闭剪贴板
    }
    else
    {
    
    
        qDebug()<< "粘贴板的缓冲区中没有BMP任何内容";

        DeleteObject(hBitmap);

        ::ReleaseDC(hWnd, hDC); // 释放设备环境句柄
        DeleteDC(hdcMem);       // 删除内存环境
        ::CloseClipboard();     // 关闭剪贴板
        return false;
    }

    return true;
}

猜你喜欢

转载自blog.csdn.net/qq_40650582/article/details/108281734