我如何将CImage DIB复制到剪贴板 [英] how do i copy a CImage DIB to clipboard

查看:111
本文介绍了我如何将CImage DIB复制到剪贴板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嗨.我试图将CImage复制到剪贴板.这就是我所拥有的.我在第二个memcpy上遇到了读取访问冲突(应该是在复制图像的位).如何将CImage复制到剪贴板?


hi. im trying to copy a CImage to the clipboard. this is what I''ve got. I get a read access violation on the second memcpy (which is supposed to be copying the bits of the image). how do i copy a CImage to the clipboard?


CImage tmpImage = pDoc->m_imageArray[0];

int w = tmpImage.GetWidth();
int h = tmpImage.GetHeight();
int Bpp = tmpImage.GetBPP();

BITMAPINFOHEADER bmInfohdr;
bmInfohdr.biSize = sizeof(BITMAPINFOHEADER);
bmInfohdr.biWidth = w;
bmInfohdr.biHeight = -h;
bmInfohdr.biPlanes = 1;
bmInfohdr.biBitCount = Bpp;
bmInfohdr.biCompression = BI_RGB;
bmInfohdr.biSizeImage = w*h*Bpp;
bmInfohdr.biXPelsPerMeter = 0;
bmInfohdr.biYPelsPerMeter = 0;
bmInfohdr.biClrUsed = 0;
bmInfohdr.biClrImportant = 0;

BITMAPINFO bmInfo;
bmInfo.bmiHeader = bmInfohdr;
bmInfo.bmiColors[0].rgbBlue=255;


void* pBits = tmpImage.GetBits();
HANDLE hData = ::GlobalAlloc (GMEM_MOVEABLE, sizeof(BITMAPINFO) + w * h * 3);
LPVOID pData = (LPVOID) ::GlobalLock (hData);
LPBYTE p_imagebits;
p_imagebits  = (LPBYTE)pData + sizeof(BITMAPINFO);


memcpy(pData,&bmInfo,sizeof(BITMAPINFO));


DWORD dwBytes = ((DWORD) w * Bpp) / 32;

if(((DWORD) w * Bpp) % 32) {
   dwBytes++;
}
dwBytes *= 4;

unsigned long m_dwSizeImage = dwBytes * h; // no compression


memcpy (p_imagebits, pBits, m_dwSizeImage);


::GlobalUnlock (hData);

COleDataSource* pods = new COleDataSource;
pods->CacheGlobalData (CF_DIB, hData);
pods->SetClipboard ();

推荐答案

您是否看过
Have you given a look to Copying a DIB to the Clipboard[^] CP-Article?
It might help you


您正在计算正确的图像大小(知道扫描线与DWORD对齐)并将其存储在m_dwSizeImage中(也可以存储在bmInfohdr.biSizeImage中) .但是分配全局内存时没有使用此大小.根据图像宽度,m_dwSizeImage可能大于w * h * 3(或者在Bpp为32时始终大于),从而导致访问冲突.

颜色表/BITMAPINFO的用法还有另一个错误:
如果DIB没有色表(Bpp> 8),则不能为其分配空间.否则,必须计算并分配颜色表的大小. BITMAPINFO结构仅包含一个颜色条目作为占位符.

因此,您应该将图像尺寸计算代码移到分配的顶部,并使用类似以下的内容(请注意使用BITMAINFOHEADER而不是BITMAPINFO):
You are calculating the correct image size (knowing that scan lines are DWORD aligned) and store it in m_dwSizeImage (may be also stored in bmInfohdr.biSizeImage). But you did not use this size when allocating the global memory. Depending on the image width, m_dwSizeImage may be greater than w * h * 3 (or it is always greater when Bpp is 32), resulting in the access violation.

There is another error with the color table / usage of BITMAPINFO:
If the DIB has no color table (Bpp > 8), you must not allocate space for it. Otherwise, the size of the color table must be calculated and allocated. The BITMAPINFO structure contains only one color entry as placeholder.

So you should move the image size calculation code on top of the allocation and use something like this (note the usage of BITMAINFOHEADER instead of BITMAPINFO):
SIZE_T dwColTableLen = (Bpp <= 8) ? (1 << Bpp) * sizeof(RGBQUAD) : 0;
HANDLE hData = ::GlobalAlloc(GMEM_MOVEABLE, 
    sizeof(BITMAPINFOHEADER) + dwColTableLen + m_dwSizeImage);
...
if (dwColTableLen)
{
    LPBYTE lpColorTable = (LPBYTE)pData + sizeof(BITMAPINFOHEADER);
    // pColors must point to the source color table
    memcpy(lpColorTable, pColors, dwColTableLen);
}
p_imagebits  = (LPBYTE)pData + sizeof(BITMAPINFOHEADER) + dwColTableLen;


这篇关于我如何将CImage DIB复制到剪贴板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆