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; }