关于将View的内容保存为位图

luokun 2004-10-19 08:59:07
我们想实现将一个视图内的内容以bitmap的形式存储起来
void MyView::InitView()
{
...
//创建一个CBitmap对象:m_bitmap 及内存DC:m_memDC
CDC *pDC = GetDC();
m_bitmap.CreateCompatibleBitmap(pDC, 600 ,800);
m_memDC.CreateCompatibleDC(pDC);
m_pOldbmp = m_memDC.SelectObject(&m_bitmap);
...
}

void MyView::OnPaint()
{
CPaintDC dc(this);

// Draw something on dc

//将dc的内容传到m_memDC中
m_memDC.BitBlt(
20,
20,
600,
800,
&dc,
0,0,SRCCOPY
);
}
但我们得到的m_bitmap,并不是只有视图内的内容,它将屏幕的内容也拷贝了进来,比如,
其他窗口的一部分。感觉不像视图内容的拷贝,而是整个windows窗口的拷贝。
...全文
232 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
linxy2002 2004-10-21
  • 打赏
  • 举报
回复
我这样做都可以的,以下是我的代码:
CClientDC client(this);
CDC cdc;

RECT rect;
GetClientRect(&rect);
int cx = rect.right - rect.left;
int cy = rect.bottom - rect.top;

bitmap.CreateCompatibleBitmap(&client, cx, cy);
cdc.CreateCompatibleDC(NULL);

CBitmap * oldbitmap = (CBitmap* ) cdc.SelectObject(&bitmap);
cdc.BitBlt(0, 0, cx, cy, &client, 0, 0, SRCCOPY);

cdc.SelectObject(oldbitmap);

::OpenClipboard(this->m_hWnd);
::EmptyClipboard();
::SetClipboardData(CF_BITMAP, bitmap);
::CloseClipboard();
golq 2004-10-21
  • 打赏
  • 举报
回复
还可以将读出的bitmap写入文件
BOOL CAnimaMakeView::WriteDIB(CString szFile , HANDLE hDIB)
{
BITMAPFILEHEADER hdr;
LPBITMAPINFOHEADER lpbi;

if (!hDIB)
return FALSE;

CFile file;
if( !file.Open( szFile, CFile::modeWrite|CFile::modeCreate) )
return FALSE;

lpbi = (LPBITMAPINFOHEADER)hDIB;
int nColors = 1 << lpbi->biBitCount;
// Fill in the fields of the file header
hdr.bfType = ((WORD) ('M' << 8) | 'B'); // is always "BM"
hdr.bfSize=(DWORD)GlobalSize (hDIB) + sizeof( hdr );
hdr.bfReserved1=0;
hdr.bfReserved2=0;
hdr.bfOffBits=(DWORD) (sizeof( hdr ) + lpbi->biSize +
nColors * sizeof(RGBQUAD));

// Write the file header
file.Write( &hdr, sizeof(hdr) );

// Write the DIB header and the bits
file.Write( lpbi, (UINT)GlobalSize(hDIB) );

return TRUE;

}
golq 2004-10-21
  • 打赏
  • 举报
回复
视图上的是DDB,要转换成DIB才有用。你可幸运了,正好手上有源码(来自程序员大本营CD):
HANDLE CAnimaMakeView::DDBToDIB(CBitmap& Bitmap, DWORD dwCompression, CPalette* pPal)
{
// BITMAP bmp;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
DWORD dwLen;
HANDLE hDIB;
HANDLE handle;
HDC hDC;
HPALETTE hPal;
ASSERT( bitmap.GetSafeHandle() );

// The function has no arg for bitfields
if( dwCompression == BI_BITFIELDS )
return NULL;

// 如果未提供调色板,则使用默认调色板
hPal = (HPALETTE) pPal->GetSafeHandle();
if (hPal==NULL)
hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);

// 获取位图信息
bitmap.GetObject(sizeof(bm),(LPSTR)&bm);

// 初始化BITMAPINFOHEADER
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = bm.bmPlanes * bm.bmBitsPixel;
bi.biCompression = dwCompression;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;

// 计算BITMAPINFOHEADER和颜色表的大小
int nColors = (1 << bi.biBitCount);
if( nColors> 256 )
nColors = 0;
dwLen = bi.biSize + nColors * sizeof(RGBQUAD);

// We need a device context to get the DIB from
hDC = ::GetDC(NULL);
hPal = SelectPalette(hDC,hPal,FALSE);
RealizePalette(hDC);

// 分配一个内存空间用于存储BITMAPINFOHEADER和颜色表
hDIB = GlobalAlloc(GMEM_FIXED,dwLen);

if (!hDIB)
{
SelectPalette(hDC,hPal,FALSE);
::ReleaseDC(NULL,hDC);
return NULL;
}

lpbi = (LPBITMAPINFOHEADER)hDIB;

*lpbi = bi; // 将初始化过一部分数据的BITMAPINFOHEADER复制到分配的堆里

// Call GetDIBits with a NULL lpBits param, so the device driver
// will calculate the biSizeImage field
GetDIBits(hDC, (HBITMAP)bitmap.GetSafeHandle(),
0L, (DWORD)bi.biHeight, (LPBYTE)NULL,
(LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);

bi = *lpbi;
// If the driver did not fill in the biSizeImage field, then compute it
// Each scan line of the image is aligned on a DWORD (32bit) boundary
if(bi.biSizeImage == 0)
{
bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8)
* bi.biHeight;

// If a compression scheme is used the result may infact be larger
// Increase the size to account for this.
if (dwCompression != BI_RGB)
bi.biSizeImage = (bi.biSizeImage * 3) / 2;
}

// 位hDIB重新分配缓冲区,以便保存DIBs
dwLen += bi.biSizeImage;
if (handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE))
hDIB = handle;
else{
GlobalFree(hDIB);

// Reselect the original palette
SelectPalette(hDC,hPal,FALSE);
::ReleaseDC(NULL,hDC);
return NULL;
}

// Get the bitmap bits
lpbi = (LPBITMAPINFOHEADER)hDIB;

// FINALLY get the DIB
// LIUQIANG
bm.bmBits = (LPBYTE)lpbi + (bi.biSize + nColors * sizeof(RGBQUAD));

BOOL bGotBits = GetDIBits( hDC,
(HBITMAP)bitmap.GetSafeHandle(),
0L, // Start scan line
(DWORD)bi.biHeight, // # of scan lines
(LPBYTE)lpbi + (bi.biSize + nColors * sizeof(RGBQUAD)),// address for bitmap bits
(LPBITMAPINFO)lpbi, // address of bitmapinfo
(DWORD)DIB_RGB_COLORS); // Use RGB for color table

if( !bGotBits )
{
GlobalFree(hDIB);

SelectPalette(hDC,hPal,FALSE);
::ReleaseDC(NULL,hDC);
return NULL;
}

SelectPalette(hDC,hPal,FALSE);
::ReleaseDC(NULL,hDC);
return hDIB;
}
luokun 2004-10-21
  • 打赏
  • 举报
回复
还是不行,得到的仍然是整个屏幕的图像。

int CEngineView::SaveClip()
{
CClientDC dc(this);//源DC,即视图区
CDC memDC;//目标DC,为一内存设备环境
memDC.CreateCompatibleDC(&dc);//为目标DC创建一兼容DC

CBitmap bitmap;
//用源DC创建一幅位图bitmap,其宽度和高度分别为图形的大小
bitmap.CreateCompatibleBitmap(&dc, 1000,1000);
CBitmap* pOldBitmap=memDC.SelectObject(&bitmap);//将bitmap选入目标DC

//将dc中的位图,从(GetX,GetY)开始,宽度为GetW,高度为GetH的区域复制到 memDC上
memDC.BitBlt (0,0,900,900,&dc,0,0,SRCCOPY);
memDC.SelectObject(pOldBitmap);//抓图结束,此时bitmap中为结果图形

if (::OpenClipboard(GetSafeHwnd()))
{
SetClipboardData(CF_BITMAP, bitmap); // m_bitmap
::CloseClipboard();
}
return 0;
}
huyansoft 2004-10-21
  • 打赏
  • 举报
回复
楼主可以把上面的GetW(nScreenIndex),GetH(nScreenIndex)分别换成视图区的宽度和高度
GetX(nScreenIndex),GetY(nScreenIndex)都换成0
huyansoft 2004-10-21
  • 打赏
  • 举报
回复
这个问题俺也是发了无数遍贴子才琢磨出来的,基本能够实现,贴出来共享,有什么不对的地方请大家指教

//将视图区中显示的图形保存到CBitmap类对象bitmap中)
CClientDC dc(this);//源DC,即视图区
CDC memDC;//目标DC,为一内存设备环境
memDC.CreateCompatibleDC(&dc);//为目标DC创建一兼容DC

CBitmap bitmap;
bitmap.CreateCompatibleBitmap(&dc, GetW(nScreenIndex),GetH(nScreenIndex));//用源DC创建一幅位图bitmap,其宽度和高度分别为图形的大小
CBitmap* pOldBitmap=memDC.SelectObject(&bitmap);//将bitmap选入目标DC

memDC.BitBlt(0,0,GetW(nScreenIndex),GetH(nScreenIndex),&dc,GetX(nScreenIndex),GetY(nScreenIndex),SRCCOPY);//将dc中的位图,从(GetX,GetY)开始,宽度为GetW,高度为GetH的区域复制到memDC上
memDC.SelectObject(pOldBitmap);//抓图结束,此时bitmap中为结果图形
carolss 2004-10-20
  • 打赏
  • 举报
回复
应该只获取窗口区的东东
lixiaosan 2004-10-20
  • 打赏
  • 举报
回复
得到view的rect,然后写入兼容dc,然后保存
ddszhan 2004-10-19
  • 打赏
  • 举报
回复
GetClientRect()

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧