近日要实现将缩小的位图保存在后台,以便在OnPaint刷新的时候仍然可以看到正确的图像,遂在lg_Bitmap类中添加了这样一个函数
BOOL lg_Bitmap::LoadFromHDC(HDC hDC)
{
if(NULL == hDC)
return FALSE;
BITMAP Bitmap;
HBITMAP hBitmap = (HBITMAP)::GetCurrentObject(hDC,OBJ_BITMAP);
::GetObject(hBitmap,sizeof(BITMAP),&Bitmap);
if(Bitmap.bmHeight <= 0||Bitmap.bmWidth <= 0||Bitmap.bmWidthBytes <= 0)
return FALSE;
BITMAPINFOHEADER& bih = m_bmi.bmiHeader;
::ZeroMemory( &bih, sizeof( BITMAPINFOHEADER ));
bih.biSize = sizeof( BITMAPINFOHEADER );
bih.biWidth = Bitmap.bmWidth;
bih.biHeight = Bitmap.bmHeight;
bih.biCompression = BI_RGB;//BI_JPEG;//BI_JPEG
bih.biPlanes = 1;
bih.biBitCount = 24;
int nLineDataSize = ((bih.biBitCount * Bitmap.bmWidth+31)/32)*4;
bih.biWidth = nLineDataSize/(bih.biBitCount/8);//(width * nChannels * 8 +31) / 8;
int nLineCopySize = bih.biWidth*(bih.biBitCount/8);
DWORD dwWholeSize = nLineDataSize * abs(bih.biHeight);
BYTE* pTemp = new BYTE[dwWholeSize];
memset(pTemp,0,dwWholeSize);
int nLine = ::GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
pTemp,&m_bmi, DIB_RGB_COLORS);
if(nLine <= 0)
{
delete [] pTemp;
return FALSE;
}
BOOL bSuccess=CreateBitmapIndirect(&m_bmi, pTemp);
delete [] pTemp;
return bSuccess;
}
{
if(NULL == hDC)
return FALSE;
BITMAP Bitmap;
HBITMAP hBitmap = (HBITMAP)::GetCurrentObject(hDC,OBJ_BITMAP);
::GetObject(hBitmap,sizeof(BITMAP),&Bitmap);
if(Bitmap.bmHeight <= 0||Bitmap.bmWidth <= 0||Bitmap.bmWidthBytes <= 0)
return FALSE;
BITMAPINFOHEADER& bih = m_bmi.bmiHeader;
::ZeroMemory( &bih, sizeof( BITMAPINFOHEADER ));
bih.biSize = sizeof( BITMAPINFOHEADER );
bih.biWidth = Bitmap.bmWidth;
bih.biHeight = Bitmap.bmHeight;
bih.biCompression = BI_RGB;//BI_JPEG;//BI_JPEG
bih.biPlanes = 1;
bih.biBitCount = 24;
int nLineDataSize = ((bih.biBitCount * Bitmap.bmWidth+31)/32)*4;
bih.biWidth = nLineDataSize/(bih.biBitCount/8);//(width * nChannels * 8 +31) / 8;
int nLineCopySize = bih.biWidth*(bih.biBitCount/8);
DWORD dwWholeSize = nLineDataSize * abs(bih.biHeight);
BYTE* pTemp = new BYTE[dwWholeSize];
memset(pTemp,0,dwWholeSize);
int nLine = ::GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
pTemp,&m_bmi, DIB_RGB_COLORS);
if(nLine <= 0)
{
delete [] pTemp;
return FALSE;
}
BOOL bSuccess=CreateBitmapIndirect(&m_bmi, pTemp);
delete [] pTemp;
return bSuccess;
}
然后在外部如此调用
CDC * pScreenDC = new CDC;
pScreenDC->CreateCompatibleDC(pDC);
CBitmap TempBitmap;
TempBitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());
CBitmap* pOldScreenDC = NULL;
pOldScreenDC = (CBitmap*)pScreenDC->SelectObject(&TempBitmap);
pScreenDC->StretchBlt(0,0,rect.Width(),rect.Height(),pMemDC,0,0,BIT.bmWidth,BIT.bmHeight,SRCCOPY);
DrawTxtInDC(pScreenDC,5,15,topinfo,strPosition,rect.Height());
if(g_ScreenBitmap.LoadFromHDC(pScreenDC->GetSafeHdc()))
{
m_bHaveDataInBuffer = TRUE;
}else{
m_bHaveDataInBuffer = FALSE;
}
pScreenDC->SelectObject(pOldScreenDC);
delete pScreenDC;
pScreenDC->CreateCompatibleDC(pDC);
CBitmap TempBitmap;
TempBitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());
CBitmap* pOldScreenDC = NULL;
pOldScreenDC = (CBitmap*)pScreenDC->SelectObject(&TempBitmap);
pScreenDC->StretchBlt(0,0,rect.Width(),rect.Height(),pMemDC,0,0,BIT.bmWidth,BIT.bmHeight,SRCCOPY);
DrawTxtInDC(pScreenDC,5,15,topinfo,strPosition,rect.Height());
if(g_ScreenBitmap.LoadFromHDC(pScreenDC->GetSafeHdc()))
{
m_bHaveDataInBuffer = TRUE;
}else{
m_bHaveDataInBuffer = FALSE;
}
pScreenDC->SelectObject(pOldScreenDC);
delete pScreenDC;
再然后界面显示了一张这样的图
我就郁闷了,好好的图咋整这样了呢?开始找原因
由于位图类中没有提供保存位图的功能,遂再增加两个函数
1,保存lg_Bitmap自身的图 2,保存指定LPBITMAPINFOHEADER,和缓冲的图
//不支持调色板
BOOL lg_Bitmap::SaveThis(LPCTSTR fn)
{
BITMAP bmp;
GetBitmap(&bmp);
return Save(&m_bmi.bmiHeader,bmp.bmBits,fn);
}
BOOL lg_Bitmap::Save(LPBITMAPINFOHEADER lpIn,LPVOID lpBuf,LPCTSTR fn)
{
//位图文件大小 , 写入文件字节数
DWORD dwBmBitsSize,dwDIBSize;
//位图文件头结构
BITMAPFILEHEADER bmfHdr;
//指向位图信息头结构
LPBITMAPINFOHEADER lpbi;
dwBmBitsSize = ((lpIn->biWidth *lpIn->biBitCount+31)/32)* 4*lpIn->biHeight;
//为位图内容分配内存
HANDLE hDib = GlobalAlloc(GHND,dwBmBitsSize+sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
memcpy(lpbi,lpIn,sizeof(BITMAPINFOHEADER));
memcpy((LPSTR)lpbi + sizeof(BITMAPINFOHEADER),lpBuf,dwBmBitsSize);
// 设置位图文件头
bmfHdr.bfType = 0x4D42; // "BM"
dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmBitsSize;
bmfHdr.bfSize = dwDIBSize;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
if(!SaveDataToFile((LPSTR)&bmfHdr,sizeof(BITMAPFILEHEADER),fn,TRUE))
{
GlobalUnlock(hDib);
GlobalFree(hDib);
return FALSE;
}
if(!SaveDataToFile((LPSTR)lpbi,dwDIBSize,fn))
{
GlobalUnlock(hDib);
GlobalFree(hDib);
return FALSE;
}
GlobalUnlock(hDib);
GlobalFree(hDib);
return TRUE;
}
BOOL lg_Bitmap::SaveThis(LPCTSTR fn)
{
BITMAP bmp;
GetBitmap(&bmp);
return Save(&m_bmi.bmiHeader,bmp.bmBits,fn);
}
BOOL lg_Bitmap::Save(LPBITMAPINFOHEADER lpIn,LPVOID lpBuf,LPCTSTR fn)
{
//位图文件大小 , 写入文件字节数
DWORD dwBmBitsSize,dwDIBSize;
//位图文件头结构
BITMAPFILEHEADER bmfHdr;
//指向位图信息头结构
LPBITMAPINFOHEADER lpbi;
dwBmBitsSize = ((lpIn->biWidth *lpIn->biBitCount+31)/32)* 4*lpIn->biHeight;
//为位图内容分配内存
HANDLE hDib = GlobalAlloc(GHND,dwBmBitsSize+sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
memcpy(lpbi,lpIn,sizeof(BITMAPINFOHEADER));
memcpy((LPSTR)lpbi + sizeof(BITMAPINFOHEADER),lpBuf,dwBmBitsSize);
// 设置位图文件头
bmfHdr.bfType = 0x4D42; // "BM"
dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmBitsSize;
bmfHdr.bfSize = dwDIBSize;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
if(!SaveDataToFile((LPSTR)&bmfHdr,sizeof(BITMAPFILEHEADER),fn,TRUE))
{
GlobalUnlock(hDib);
GlobalFree(hDib);
return FALSE;
}
if(!SaveDataToFile((LPSTR)lpbi,dwDIBSize,fn))
{
GlobalUnlock(hDib);
GlobalFree(hDib);
return FALSE;
}
GlobalUnlock(hDib);
GlobalFree(hDib);
return TRUE;
}
然后在lg_Bitmap::LoadFromHDC(HDC hDC)的结尾加入这么一段
lg_TimeString Tsing;
string sPath = Tsing.Format("e:\抓图\%N%Y%R%S%F%M%H.bmp");
CreateAllDirectory(sPath.c_str());
// SaveThis(sPath.c_str());
Save(&bih,pTemp,sPath.c_str());
string sPath = Tsing.Format("e:\抓图\%N%Y%R%S%F%M%H.bmp");
CreateAllDirectory(sPath.c_str());
// SaveThis(sPath.c_str());
Save(&bih,pTemp,sPath.c_str());
结果无论是lg_Bitmap自身还是外部传来的位图无一例外的变成了上面那个图的样子
..............思考中,无意中在google上看到一句话,在使用StretchBlt缩小位图的时候要SetStretchBltMode(COLORONCOLOR).......我晕,管他先试试。
CDC * pScreenDC = new CDC;
pScreenDC->CreateCompatibleDC(pDC);
CBitmap TempBitmap;
TempBitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());
CBitmap* pOldScreenDC = NULL;
pOldScreenDC = (CBitmap*)pScreenDC->SelectObject(&TempBitmap);
pScreenDC->SetStretchBltMode(COLORONCOLOR);
pScreenDC->StretchBlt(0,0,rect.Width(),rect.Height(),pMemDC,0,0,BIT.bmWidth,BIT.bmHeight,SRCCOPY);
DrawTxtInDC(pScreenDC,5,15,topinfo,strPosition,rect.Height());
if(g_ScreenBitmap.LoadFromHDC(pScreenDC->GetSafeHdc()))
{
m_bHaveDataInBuffer = TRUE;
}else{
m_bHaveDataInBuffer = FALSE;
}
pScreenDC->SelectObject(pOldScreenDC);
delete pScreenDC;
pScreenDC->CreateCompatibleDC(pDC);
CBitmap TempBitmap;
TempBitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());
CBitmap* pOldScreenDC = NULL;
pOldScreenDC = (CBitmap*)pScreenDC->SelectObject(&TempBitmap);
pScreenDC->SetStretchBltMode(COLORONCOLOR);
pScreenDC->StretchBlt(0,0,rect.Width(),rect.Height(),pMemDC,0,0,BIT.bmWidth,BIT.bmHeight,SRCCOPY);
DrawTxtInDC(pScreenDC,5,15,topinfo,strPosition,rect.Height());
if(g_ScreenBitmap.LoadFromHDC(pScreenDC->GetSafeHdc()))
{
m_bHaveDataInBuffer = TRUE;
}else{
m_bHaveDataInBuffer = FALSE;
}
pScreenDC->SelectObject(pOldScreenDC);
delete pScreenDC;
结果