Windows includes four functions that let you create an old-style bitmap in your program. They are:
hBitmap = CreateBitmap (cxWidth, cyHeight, nPlanes, nBitsPixel, lpBits) ;
hBitmap = CreateBitmapIndirect (&bitmap) ;
hBitmap = CreateCompatibleBitmap (hdc, cxWidth, cyHeight) ;
hBitmap = CreateDiscardableBitmap (hdc, cxWidth, cyHeight) ;
The cxWidth and cyHeight parameters are the width and the height of the bitmap in pixels. In CreateBitmap, the nPlanes and nBitsPixel parameters are the number of color planes and the number of color bits per pixel in the bitmap. At least one of these parameters should be set to 1. If both parameters are 1, the function creates a monochrome bitmap. (I'll discuss how the color planes and color bits represent color shortly.)
In the CreateBitmap function, lpBits can be set to NULL if you are creating an uninitialized bitmap. The resultant bitmap contains random data. In the CreateCompatibleBitmap and CreateDiscardableBitmap functions, Windows uses the device context referenced by hdc to obtain the number of color planes and number of color bits per pixel. The bitmap created by these functions is uninitialized.
CreateBitmapIndirect is similar to CreateBitmap except that it uses the bitmap structure of type BITMAP to define the bitmap. The following table shows the fields of this structure:
Field | Type | Description |
bmType | short | Set to 0 |
bmWidth | short | Width of bitmap in pixels |
bmHeight | short | Height of bitmap in scan lines |
bmWidthBytes | short | Width of bitmap in bytes (must be even) |
bmPlanes | BYTE | Number of color planes |
bmBitsPixel | BYTE | Number of color bits per pixel |
bmBits | LPSTR | Far pointer to array of bits |
The bmWidthBytes field must be an even number—the lowest even number of bytes required to store one scan line. The array of the bits referenced by bmBits must be organized based on the bmWidthBytes field. If bm is a structure variable of type BITMAP, you can calculate the bmWidthBytes field by the following statement:
bm.bmWidthBytes = (bm.bmWidth * bm.bmBitsPixel + 15) / 16 * 2 ;
If Windows cannot create the bitmap (generally because not enough memory is available), it will return a NULL. You should check the return value from the bitmap creation functions, particularly if you're creating large bitmaps.
The handle to the bitmap is not a handle to a global memory block, so don't try to use the GlobalLock function on it. The handle is instead a local handle to the GDI module's data segment. This handle references a small local memory block in GDI that contains a second handle to a global memory block containing the information in the BITMAP structure and the actual bits.
Once you create a bitmap, you cannot change the size, the number of color planes, or the number of color bits per pixel. You would have to create a new bitmap and transfer the bits from the original bitmap to this new bitmap. If you have a handle to a bitmap, you can get the size and color organization using:
GetObject (hBitmap, sizeof (BITMAP), (LPSTR) &bitmap) ;
This copies the information about the bitmap into a structure (called bitmap here) of type BITMAP. This function doesn't fill in the bmBits field. To get access to the actual bits of the bitmap, you must call:
GetBitmapBits (hBitmap, dwCount, lpBits) ;
This copies dwCount bits into a character array referenced by the far pointer lpBits. To ensure that all the bits of the bitmap are copied into this array, you can calculate the dwCount parameter based on the fields of the bitmap structure:
dwCount = (DWORD) bitmap.bmWidthBytes * bitmap.bmHeight *
bitmap.bmPlanes ;
You can also direct Windows to copy a character array containing the bitmap bits back into an existing bitmap using the function:
SetBitmapBits (hBitmap, dwCount, lpBits) ;
Because bitmaps are GDI objects, you should delete any bitmap you create:
DeleteObject (hBitmap) ;