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


    近日要实现将缩小的位图保存在后台,以便在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;
        }

    然后在外部如此调用

            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;

    再然后界面显示了一张这样的图

    我就郁闷了,好好的图咋整这样了呢?开始找原因
    由于位图类中没有提供保存位图的功能,遂再增加两个函数
    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;
        }

    然后在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());

    结果无论是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;

    结果

  • 相关阅读:
    Ubuntu中用户名密码和root密码修改
    在Python中,输出格式:%d , %6d , %-6d, %06d , %.6f的一些区分
    定制的print()输出格式
    python编程系列---Pycharm快捷键(更新中....)
    webbrowser控件——Windows下的开发利器
    Windows读写文件的猫腻
    根据GUID获取设备信息
    转:APDU命令格式
    VC中添加消息响应函数
    VC 取消warning
  • 原文地址:https://www.cnblogs.com/buffer/p/1434219.html
Copyright © 2020-2023  润新知