关于截图不能成功
//拷贝截图到文件,lpRect 代表选定区域
HBITMAP CIECaptureDlg::CopyScreenToBitmap(LPRECT lpRect,BOOL bSave)
{
HDC hScrDC, hMemDC;
// 屏幕和内存设备描述表
HBITMAP hBitmap, hOldBitmap;
// 位图句柄
int nX, nY, nX2, nY2;
// 选定区域坐标
int nWidth, nHeight;
//the pointer will save all pixel point 's color value
BYTE *lpBitmapBits = NULL;
// 确保选定区域不为空矩形
if ( IsRectEmpty( lpRect ) )
{
return NULL;
}
//为屏幕创建设备描述表
hScrDC = CreateDC( _T( "DISPLAY " ), NULL, NULL, NULL );
//为屏幕设备描述表创建兼容的内存设备描述表
hMemDC = CreateCompatibleDC( hScrDC );
// 获得选定区域坐标
nX = lpRect-> left;
nY = lpRect-> top;
nX2 = lpRect-> right;
nY2 = lpRect-> bottom;
//确保选定区域是可见的
if ( nX < 0 )
{
nX = 0;
}
if ( nY < 0 )
{
nY = 0;
}
if ( nX2 > m_xScreen )
{
nX2 = m_xScreen;
}
if ( nY2 > m_yScreen )
{
nY2 = m_yScreen;
}
nWidth = nX2 - nX;
nHeight = nY2 - nY;
//initialize the struct BITMAPINFO for the bitmap infomation,
//in order to use the function CreateDIBSection
//on wince os, each pixel stored by 24 bits(biBitCount=24)
//and no compressing(biCompression=0)
BITMAPINFO RGB24BitsBITMAPINFO;
memset( &RGB24BitsBITMAPINFO, 0, sizeof(BITMAPINFO) );
RGB24BitsBITMAPINFO.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
RGB24BitsBITMAPINFO.bmiHeader.biWidth = nWidth;
RGB24BitsBITMAPINFO.bmiHeader.biHeight = nHeight;
RGB24BitsBITMAPINFO.bmiHeader.biPlanes = 1;
RGB24BitsBITMAPINFO.bmiHeader.biBitCount = 24;
//use the function CreateDIBSection and SelectObject
//in order to get the bitmap pointer : lpBitmapBits
hBitmap = CreateDIBSection( hMemDC, (BITMAPINFO*)&RGB24BitsBITMAPINFO,
DIB_RGB_COLORS, (void **)&lpBitmapBits, NULL, 0 );
// 把新位图选到内存设备描述表中
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
// 把屏幕设备描述表拷贝到内存设备描述表中
if(bSave)
{
//创建兼容DC,当bSave为真时把开始保存的全屏位图,按截取矩形大小保存
CDC dcCompatible;
dcCompatible.CreateCompatibleDC( CDC::FromHandle( hMemDC ) );
dcCompatible.SelectObject( m_pBitmap );
BitBlt( hMemDC, 0, 0, nWidth, nHeight, dcCompatible, nX, nY, SRCCOPY );
//bimap file header in order to write bmp file
BITMAPFILEHEADER bmBITMAPFILEHEADER;
memset(&bmBITMAPFILEHEADER, 0, sizeof(BITMAPFILEHEADER));
bmBITMAPFILEHEADER.bfType = 0x4d42; //bmp
bmBITMAPFILEHEADER.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmBITMAPFILEHEADER.bfSize = bmBITMAPFILEHEADER.bfOffBits + ((nWidth*nHeight)*3); ///3=(24 / 8)
//保存文件名及路径
int filecount = 0;
CString name;
name.Format( _T( "picture%d.bmp " ), filecount++ );
CFile file;
if( file.Open(name, CFile::modeCreate|CFile::modeWrite) )
{
file.Write( &bmBITMAPFILEHEADER, sizeof(BITMAPFILEHEADER) );
file.Write( &(RGB24BitsBITMAPINFO.bmiHeader), sizeof(BITMAPINFOHEADER) );
file.Write( lpBitmapBits, 3*nWidth*nHeight );
file.Close();
}
}
else
{
BitBlt( hMemDC, 0, 0, nWidth, nHeight,hScrDC, nX, nY, SRCCOPY );
}
//得到屏幕位图的句柄
hBitmap = (HBITMAP)SelectObject( hMemDC, hOldBitmap );
//清除
DeleteDC( hScrDC );
DeleteDC( hMemDC );
// 返回位图句柄
return hBitmap;
}
这是我的截图图像并保存到本地的一个函数
但是在截图的时候,保存到本地后,打开BMP图像显示“绘图失败”,但有时打开BMP图像显示的是截取到的图片。
有达人指点下
看这个函数有什么问题?
谢谢
[解决办法]
不知道有没有别的地方有问题,
但这两行是有问题的
bmBITMAPFILEHEADER.bfSize = bmBITMAPFILEHEADER.bfOffBits + ((nWidth*nHeight)*3);
file.Write( lpBitmapBits, 3*nWidth*nHeight );
BMP有规定,图像的每一行数据所占用的字节数必须为4的整数倍.
比如
nWidth = 16, 则每行占16 * 3 = 48个字节(正好是4的整数倍)
nWidth = 17, 则每行占17 * 3 = 51个字节, 不是4的整数倍, 此时会加一个填充字节(这个字节里的数据无任何意义), 让这行图像数据占到52字节(为4的整数倍).同样若差3个字节是4的整数倍, 那就会加3个填充字节.
所以你上面计算数据长度的公式是错的.
实际每行数据占用的长度是(nWidth*3 + 3) / 4 * 4
改成下面这个样子.
bmBITMAPFILEHEADER.bfSize = bmBITMAPFILEHEADER.bfOffBits + ((nWidth*3 + 3) / 4 * 4 * nHeight);
file.Write( lpBitmapBits, ((3*nWidth + 3) / 4 * 4 *nHeight );