win32—GrafMenu的CreateBitmapIndirect创建失败的问题

CBitmap::CreateBitmapIndirect 函数创建位图成功却在CDC::SelectObject 选择位图时却失败,原因是CreateBitmapIndirect不能创建彩色位图,只能创建单色位图,虽然CreateBitmapIndirect创建彩色位图时也能返回成功,但用CDC::SelectObject 的时候失败。MSDN只有在CreateBitmapIndirect 有说明:

While the CreateBitmapIndirect function can be used to create color bitmaps, for performance reasons applications should use CreateBitmapIndirect to create monochrome bitmaps and CreateCompatibleBitmap to create color bitmaps. Whenever a color bitmap from CreateBitmapIndirect is selected into a device context, the system must ensure that the bitmap matches the format of the device context it is being selected into. Because CreateCompatibleBitmap takes a device context, it returns a bitmap that has the same format as the specified device context. Thus, subsequent calls to SelectObject are faster with a color bitmap from CreateCompatibleBitmap than with a color bitmap returned from CreateBitmapIndirect.

虽然CreateBitmapIndirect函数可用于创建彩色位图,出于性能方面的应用程序应该使用CreateBitmapIndirect创建单色位图,用CreateCompatibleBitmap创建彩色位图...............................

要创建彩色位图应用 CreateCompatibleBitmap 函数

 

关于CreateBitmapIndirect  BITMAP参数的bmBits 创建成功后返回0的问题

 

CBitmap::CreateBitmapIndirect函数的功能是用一个BITMAP结构体重的高度、宽度和位模式(如果指定了一个的话)来初始化一个位图。调用该函数时,用户可以设置bmBits字段为NULL或者设为像素位数据的地址(用以初始化该位图)。

如您的代码那样,在执行了CBitmap::GetBitmap之后所得的bm.bmBits确实为NULL,为了获得bmBits,您可以调用专门的CBitmap::GetBitmapBits函数来获得位数据。

BYTE bitbuffer[16];
DWORD ret3 = m_aBmp.GetBitmapBits(16, (LPVOID)bitbuffer);//检查bitbuffer中内容,的确是原来的位数据

 

BITMAP bmWidthBytes  计算方法

typedef    struct    tagBITMAP    {     
    
           LONG    bmType;                //必需为0   
           LONG    bmWidth;              //位图的宽度(以像素为单位)   
           LONG    bmHeight;            //位图的高度(以像素为单位)   
    
           /*指定每条光栅所占字节数。此值必须取偶数,   
              因为图形设备接口(GDI)默认为一个位图的位值组成一个2字节的整数数组。*/   
           LONG    bmWidthBytes;     
    
           WORD    bmPlanes;            //    位图调色板颜色数   
    
           WORD    bmBitsPixel;      //    一个点在每个调色板上接近的颜色位数   
    
           LPVOID    bmBits;            //   指向存储像素阵列的数组   
    
   }    BITMAP;

bmWidthBytes : 一行像素所占的字节数,一行像素的存储必须按word对齐,所以该值必须为2的倍数。

单色图像 bmWidthBytes =bmWidth/8+(bmWidth/8)%2

256(8位)色图像 bmWidthBytes=bmWidth+bmWidth%2;

16色图像 bmWidthBytes=bmWidth/2+(bmWidth/2)%2;


//windows程序设计(第五版)14.4.9 GrafMenu程序示例解决办法,部分代码

/缩放位图分辨率
HBITMAP StretchBitmap(HBITMAP hBitmap1)
{
	BITMAP bm1,bm2;
	HBITMAP hBitmap2;
	HDC hdc,hdcMem1,hdcMem2;
	int cxChar,cyChar;
	//获取系统字体宽高
	cxChar=GetDialogBaseUnits()&0xffff;
	cyChar=(GetDialogBaseUnits()>>16)&0xffff;
	//创建两个兼容的内存显示设备
       hdc=CreateIC(TEXT("DISPLAY"),NULL,NULL,NULL);
	 hdcMem1=CreateCompatibleDC(hdc);
	 hdcMem2=CreateCompatibleDC(hdc);

	 //获取位图信息
	 GetObject(hBitmap1,sizeof(BITMAP),&bm1);
	 //在系统字体大小的基础上缩放尺寸
	 bm2=bm1;
	 bm2.bmWidth=(cxChar*bm2.bmWidth)/4;
	 bm2.bmHeight=(cyChar*bm2.bmHeight)/8;
	 

	 //创建位图2  CreateBitmapIndirect不能创建彩色位图,只能创建单色位图
	 //hBitmap2=CreateBitmapIndirect(&bm2);
        //创建彩色位图	 
	 hBitmap2=CreateCompatibleBitmap(hdc,bm2.bmWidth,bm2.bmHeight);

	 //将位图选入内存,做StretchBlt放大或缩小位图
	 SelectObject(hdcMem1,hBitmap1);
	 SelectObject(hdcMem2,hBitmap2);

	 StretchBlt(hdcMem2,0,0,bm2.bmWidth,bm2.bmHeight,hdcMem1,0,0,bm1.bmWidth,bm1.bmHeight,SRCCOPY);

	 DeleteDC(hdc);
	 DeleteDC(hdcMem1);
	 DeleteDC(hdcMem2);
	 DeleteObject(hBitmap1);
     return hBitmap2;
}


原文地址:https://www.cnblogs.com/xieyuan/p/3787440.html