使用StretchBlt之前一定要用SetStretchBltMode(COLORONCOLOR)

近日要实现将缩小的位图保存在后台,以便在OnPaint刷新的时候仍然可以看到正确的图像,遂在lg_Bitmap类中添加了这样一个函数

None.gif     BOOL lg_Bitmap::LoadFromHDC(HDC hDC)
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        
if(NULL == hDC)
InBlock.gif            
return FALSE;
InBlock.gif        BITMAP Bitmap;
InBlock.gif        HBITMAP hBitmap 
= (HBITMAP)::GetCurrentObject(hDC,OBJ_BITMAP);
InBlock.gif        
InBlock.gif        ::GetObject(hBitmap,
sizeof(BITMAP),&Bitmap); 
InBlock.gif
InBlock.gif        
if(Bitmap.bmHeight <= 0||Bitmap.bmWidth <= 0||Bitmap.bmWidthBytes <= 0)
InBlock.gif            
return FALSE;
InBlock.gif
InBlock.gif        BITMAPINFOHEADER
& bih = m_bmi.bmiHeader;
InBlock.gif        ::ZeroMemory( 
&bih, sizeof( BITMAPINFOHEADER ));
InBlock.gif        bih.biSize        
= sizeof( BITMAPINFOHEADER );
InBlock.gif        bih.biWidth       
= Bitmap.bmWidth;
InBlock.gif        bih.biHeight      
= Bitmap.bmHeight;
InBlock.gif        bih.biCompression 
= BI_RGB;//BI_JPEG;//BI_JPEG
InBlock.gif
        bih.biPlanes      = 1;
InBlock.gif        bih.biBitCount      
= 24;
InBlock.gif        
InBlock.gif        
int nLineDataSize = ((bih.biBitCount * Bitmap.bmWidth+31)/32)*4;
InBlock.gif        bih.biWidth       
= nLineDataSize/(bih.biBitCount/8);//(width * nChannels * 8 +31) / 8;
InBlock.gif
        int nLineCopySize = bih.biWidth*(bih.biBitCount/8);
InBlock.gif        DWORD dwWholeSize 
= nLineDataSize * abs(bih.biHeight);
InBlock.gif        BYTE
* pTemp = new BYTE[dwWholeSize];
InBlock.gif        memset(pTemp,
0,dwWholeSize);
InBlock.gif
InBlock.gif        
int nLine = ::GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
InBlock.gif            pTemp,
&m_bmi, DIB_RGB_COLORS);
InBlock.gif
InBlock.gif        
if(nLine <= 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            delete [] pTemp;
InBlock.gif            
return FALSE;
ExpandedSubBlockEnd.gif        }

InBlock.gif        BOOL bSuccess
=CreateBitmapIndirect(&m_bmi, pTemp);
InBlock.gif        delete [] pTemp;
InBlock.gif        
return bSuccess;
ExpandedBlockEnd.gif    }

然后在外部如此调用

None.gif         CDC  *  pScreenDC  =   new  CDC;
None.gif        pScreenDC
-> CreateCompatibleDC(pDC);
None.gif        CBitmap TempBitmap;
None.gif        TempBitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());
None.gif        CBitmap
*  pOldScreenDC  =  NULL;
None.gif        pOldScreenDC 
=  (CBitmap * )pScreenDC -> SelectObject( & TempBitmap);
None.gif        pScreenDC -> StretchBlt( 0 , 0 ,rect.Width(),rect.Height(),pMemDC, 0 , 0 ,BIT.bmWidth,BIT.bmHeight,SRCCOPY);
None.gif        DrawTxtInDC(pScreenDC,
5 , 15 ,topinfo,strPosition,rect.Height());
None.gif        
if (g_ScreenBitmap.LoadFromHDC(pScreenDC -> GetSafeHdc()))
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            m_bHaveDataInBuffer 
= TRUE;
ExpandedBlockStart.gifContractedBlock.gif        }
else dot.gif {
InBlock.gif            m_bHaveDataInBuffer 
= FALSE;
ExpandedBlockEnd.gif        }

None.gif        pScreenDC
-> SelectObject(pOldScreenDC);
None.gif        delete pScreenDC;

再然后界面显示了一张这样的图
2009041217424484.jpg
我就郁闷了,好好的图咋整这样了呢?开始找原因
由于位图类中没有提供保存位图的功能,遂再增加两个函数
1,保存lg_Bitmap自身的图 2,保存指定LPBITMAPINFOHEADER,和缓冲的图

None.gif      // 不支持调色板
None.gif
    BOOL lg_Bitmap::SaveThis(LPCTSTR fn)
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        BITMAP bmp;
InBlock.gif        GetBitmap(
&bmp);
InBlock.gif        
return Save(&m_bmi.bmiHeader,bmp.bmBits,fn);
ExpandedBlockEnd.gif    }

None.gif    BOOL lg_Bitmap::Save(LPBITMAPINFOHEADER lpIn,LPVOID lpBuf,LPCTSTR fn)
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        
//位图文件大小 , 写入文件字节数
InBlock.gif
        DWORD dwBmBitsSize,dwDIBSize;
InBlock.gif
InBlock.gif        
//位图文件头结构
InBlock.gif
        BITMAPFILEHEADER   bmfHdr;    
InBlock.gif    
InBlock.gif        
//指向位图信息头结构
InBlock.gif
        LPBITMAPINFOHEADER lpbi;
InBlock.gif
InBlock.gif        dwBmBitsSize 
= ((lpIn->biWidth *lpIn->biBitCount+31)/32)* 4*lpIn->biHeight;
InBlock.gif
InBlock.gif        
//为位图内容分配内存
InBlock.gif
        HANDLE hDib  = GlobalAlloc(GHND,dwBmBitsSize+sizeof(BITMAPINFOHEADER));
InBlock.gif        lpbi 
= (LPBITMAPINFOHEADER)GlobalLock(hDib);
InBlock.gif        memcpy(lpbi,lpIn,
sizeof(BITMAPINFOHEADER));
InBlock.gif
InBlock.gif        memcpy((LPSTR)lpbi 
+ sizeof(BITMAPINFOHEADER),lpBuf,dwBmBitsSize);
InBlock.gif
InBlock.gif        
// 设置位图文件头
InBlock.gif
        bmfHdr.bfType = 0x4D42;  // "BM"
InBlock.gif
        dwDIBSize    = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmBitsSize;  
InBlock.gif        bmfHdr.bfSize 
= dwDIBSize;
InBlock.gif        bmfHdr.bfReserved1 
= 0;
InBlock.gif        bmfHdr.bfReserved2 
= 0;
InBlock.gif        bmfHdr.bfOffBits 
= (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
InBlock.gif        
if(!SaveDataToFile((LPSTR)&bmfHdr,sizeof(BITMAPFILEHEADER),fn,TRUE))
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            GlobalUnlock(hDib);
InBlock.gif            GlobalFree(hDib);
InBlock.gif            
return FALSE;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
if(!SaveDataToFile((LPSTR)lpbi,dwDIBSize,fn))
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            GlobalUnlock(hDib);
InBlock.gif            GlobalFree(hDib);
InBlock.gif            
return FALSE;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        GlobalUnlock(hDib);
InBlock.gif        GlobalFree(hDib);
InBlock.gif        
return TRUE;
ExpandedBlockEnd.gif    }

 

然后在lg_Bitmap::LoadFromHDC(HDC hDC)的结尾加入这么一段

None.gif         lg_TimeString Tsing;
None.gif        
string  sPath  =  Tsing.Format( " e:\抓图\%N%Y%R%S%F%M%H.bmp " );
None.gif        CreateAllDirectory(sPath.c_str());
None.gif
//         SaveThis(sPath.c_str());
None.gif
        Save( & bih,pTemp,sPath.c_str());

结果无论是lg_Bitmap自身还是外部传来的位图无一例外的变成了上面那个图的样子
..............思考中,无意中在google上看到一句话,在使用StretchBlt缩小位图的时候要SetStretchBltMode(COLORONCOLOR).......我晕,管他先试试。

None.gif         CDC  *  pScreenDC  =   new  CDC;
None.gif        pScreenDC
-> CreateCompatibleDC(pDC);
None.gif        CBitmap TempBitmap;
None.gif        TempBitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());
None.gif        CBitmap
*  pOldScreenDC  =  NULL;
None.gif        pOldScreenDC 
=  (CBitmap * )pScreenDC -> SelectObject( & TempBitmap);
None.gif        pScreenDC
-> SetStretchBltMode(COLORONCOLOR);
None.gif        pScreenDC
-> StretchBlt( 0 , 0 ,rect.Width(),rect.Height(),pMemDC, 0 , 0 ,BIT.bmWidth,BIT.bmHeight,SRCCOPY);
None.gif        DrawTxtInDC(pScreenDC,
5 , 15 ,topinfo,strPosition,rect.Height());
None.gif        
if (g_ScreenBitmap.LoadFromHDC(pScreenDC -> GetSafeHdc()))
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            m_bHaveDataInBuffer 
= TRUE;
ExpandedBlockStart.gifContractedBlock.gif        }
else dot.gif {
InBlock.gif            m_bHaveDataInBuffer 
= FALSE;
ExpandedBlockEnd.gif        }

None.gif        pScreenDC
-> SelectObject(pOldScreenDC);
None.gif        delete pScreenDC;

结果
2009041217401248.jpg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值