当前位置: 首页 > article >正文

使用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;

结果

http://www.lryc.cn/news/2418916.html

相关文章:

  • 2款安卓漫画阅读器横评:漫画阅读软件哪个好用
  • 世界各国与中国时差查询
  • Sailfish OS
  • 离散数据编码方式总结(OneHotEncoder、LabelEncoder、OrdinalEncoder、get_dummies、DictVectorizer、to_categorical的区别?)
  • java.lang.Integer
  • linux进程优先级与nice,Linux之renice和nice调整进程的优先级
  • ActivityThread源码分析
  • 【工作笔记0010】asp.net后台Request.QueryString获取的url中文参数乱码解决方案
  • UART简介
  • C语言:从零基础到精通—轻松写出第一个C语言程序
  • Xtreme.Toolkit.Pro
  • _Linux结束进程到底有多少种方法?
  • windows密码抓取的多种方法
  • OSIP协议栈(及eXoSIP,Ortp等)使用入门(2)
  • 电路方案分析(七)电源入口欠压保护(阈值设定电路)
  • API::CreateProcess()创建进程失败 返回1
  • 企业网站建设需要多少钱?定制开发费用报价在3000-4000元
  • 什么是线程和应用?线程和进程区别是什么?
  • 软件性能测试怎么做?有哪些常见的技术指标?
  • Python接口测试实战- 接口测试理论
  • Android组织首选项PreferenceScreen及首选项框架 ListPreference
  • http://www.51voa.com/VOA_Special_English/
  • 使用VMware安装Ubuntu虚拟机和VMware Tools
  • 09 内核开发-避免冲突和死锁-spinlock
  • ioctl函数详细说明
  • input标签的各种属性
  • PostgreSQL数据库事务系统——获取事务ID
  • Delphi各个版本的官方下载地址
  • 设计师创业的几种低成本思路
  • “lnk是什么文件 编程“ -> “在编程中,lnk文件的作用和特点“