11.6.5 Adding a WM_CREATE Case

The Bitmap application must have a WM_CREATE case and supporting variable and function declarations to create or load the bitmaps and to set the menus. The WM_CREATE case creates four 8-by-8-pixel monochrome bitmaps to be used as patterns in a pattern brush for the window background. It also creates or loads three 64-by-32-pixel bitmaps to be displayed in the window. So that the user can choose a bitmap or pattern for viewing, the WM_CREATE case adds the bitmap or pattern to the Bitmap or Pattern menu by using the AppendMenu function. Finally, the case sets the initial values of the brush, bitmap, and stretching modes and creates the memory device context from which the bitmaps are copied.

The WM_CREATE case creates the four patterns by using the CreateBitmap function. It loads two bitmaps, Dog and Cat, and creates a third by using the MakeColorBitmap function defined within the application. After creating the patterns and bitmaps, the WM_CREATE case creates pop-up menus, appends the patterns and bitmaps to the appropriate menus, and replaces the existing Bitmap and Pattern menus with the new pop-up menus. Next, it sets the hBrush, hBitmap, and fwStretchMode variables to the initial values for the background brush, bitmap, and stretching modes. Finally, the case creates the memory device context from which the bitmaps will be copied to the screen. To create this case, add the following statements to your window procedure:

case WM_CREATE:

    hbmpWhite = CreateBitmap(8, 8, 1, 1, (LPSTR) White);
    hbmpBlack = CreateBitmap(8, 8, 1, 1, (LPSTR) Black);
    hbmpZigZag = CreateBitmap(8, 8, 1, 1, (LPSTR) Zigzag);
    hbmpCrossHatch = CreateBitmap(8, 8, 1, 1, (LPSTR) CrossHatch);

    hbmpDog = LoadBitmap(hinst, "dog");
    hbmpCat = LoadBitmap(hinst, "cat");
    if ((hbmpClrPattern = MakeColorBitmap(hwnd)) == NULL)
        return -1;

    hmenuBitmap1 = LoadBitmap(hinst, "dog");
    hmenuBitmap2 = LoadBitmap(hinst, "cat");
    if ((hmenuBitmap3 = MakeColorBitmap(hwnd)) == NULL)
        return -1;

    hmenu = CreateMenu();
    AppendMenu(hmenu, MF_STRING | MF_CHECKED, IDM_PATTERN1,
        "&White");
    AppendMenu(hmenu, MF_STRING | MF_CHECKED, IDM_PATTERN2,
        "&Black");
    AppendMenu(hmenu, MF_BITMAP, IDM_PATTERN3,
        (LPSTR) hbmpZigZag);
    AppendMenu(hmenu, MF_BITMAP, IDM_PATTERN4,
        (LPSTR) hbmpCrossHatch);

    ModifyMenu(GetMenu(hwnd), 1, MF_POPUP | MF_BYPOSITION,
        (UINT) hmenu, "&Pattern");

    hmenu = CreateMenu();

    /* Use bitmaps for menu items. */

    AppendMenu(hmenu, MF_BITMAP, IDM_BITMAP1,
        (LPSTR) hmenuBitmap1);
    AppendMenu(hmenu, MF_BITMAP, IDM_BITMAP2,
        (LPSTR) hmenuBitmap2);
    AppendMenu(hmenu, MF_BITMAP, IDM_BITMAP3,
        (LPSTR) hmenuBitmap3);

    ModifyMenu(GetMenu(hwnd), 0, MF_BYPOSITION | MF_POPUP,
        (UINT) hmenu, "&Bitmap");

    hBrush = CreatePatternBrush(hbmpWhite);
    fwStretchMode = IDM_BLACKONWHITE;

    /* Select the first bitmap */

    hdc = GetDC(hwnd);
    hdcMemory = CreateCompatibleDC(hdc);
    ReleaseDC(hwnd, hdc);
    hOldBitmap = SelectObject(hdcMemory, hbmpDog);
    GetObject(hbmpDog, 16, (LPSTR) &Bitmap);

    break;

The CreateBitmap and LoadBitmap functions work as described in earlier sections in this chapter. The MakeColorBitmap function is created for this application. It creates and draws a color bitmap, using the same method described in Section 11.2.2, “Creating and Filling a Blank Bitmap.” The statements of this function are specified later in this section. Note that each bitmap is loaded or created twice. This is required, since no single bitmap handle may be selected into two device contexts at the same time. To display a bitmap in a menu requires a selection, as does displaying the bitmap in the client area.

The CreateMenu function creates an empty menu and returns a handle to the menu. The ChangeMenu functions that specify the pattern handles add the patterns as menu items to the new menu. The MF_BITMAP option specifies that a bitmap will be added. The CheckMenuItem function places a check mark next to the current menu item, and the last ChangeMenu function replaces the existing Pattern menu. The same steps are then repeated for the Bitmap menu.

The CreateCompatibleDC function creates a memory device context that is compatible with the display. The SelectObject function selects the current bitmap into the memory device context so that it is ready to be copied to the display. The GetObject function copies the dimensions of the bitmap into the Bitmap structure. The structure can then be used in subsequent BitBlt and StretchBlt functions to specify the width and height of the bitmap.

The following MakeColorBitmap function creates a color bitmap by creating a bitmap that is compatible with the display; then it paints a plaid color pattern by using red, green, and blue brushes and the PatBlt function. To use this function, add the following definition to the end of your source file:

HBITMAP MakeColorBitmap(HWND hwnd)
{
    HDC hdc;
    HDC hdcMemory;
    HBITMAP hBitmap;
    HBITMAP hOldBitmap;
    HBRUSH hRedBrush;
    HBRUSH hGreenBrush;
    HBRUSH hBlueBrush;
    HBRUSH hOldBrush;
        .
        .
        .
    hdc = GetDC(hwnd);
    if ((hdcMemory = CreateCompatibleDC(hdc)) == NULL)
        return NULL;
    if ((hBitmap = CreateCompatibleBitmap(hdc, 64, 32)) == NULL)
        return NULL;
    hOldBitmap = SelectObject(hdcMemory, hBitmap);
    hRedBrush = CreateSolidBrush(RGB(255, 0, 0));
    hGreenBrush = CreateSolidBrush(RGB(0, 255, 0));
    hBlueBrush = CreateSolidBrush(RGB(0, 0, 255));

    PatBlt(hdcMemory, 0, 0, 64, 32, BLACKNESS);
    hOldBrush = SelectObject(hdcMemory, hRedBrush);
    PatBlt(hdcMemory, 0, 0, 24, 11, PATORDEST);
    PatBlt(hdcMemory, 40, 10, 24, 12, PATORDEST);
    PatBlt(hdcMemory, 20, 21, 24, 11, PATORDEST);
    SelectObject(hdcMemory, hGreenBrush);
    PatBlt(hdcMemory, 20, 0, 24, 11, PATORDEST);
    PatBlt(hdcMemory, 0, 10, 24, 12, PATORDEST);
    PatBlt(hdcMemory, 40, 21, 24, 11, PATORDEST);
    SelectObject(hdcMemory, hBlueBrush);
    PatBlt(hdcMemory, 40, 0, 24, 11, PATORDEST);
    PatBlt(hdcMemory, 20, 10, 24, 12, PATORDEST);
    PatBlt(hdcMemory, 0, 21, 24, 11, PATORDEST);

    BitBlt(hdc, 0, 0, 64, 32, hdcMemory, 0, 0, SRCCOPY)

    SelectObject(hdcMemory, hOldBrush);
    DeleteObject(hRedBrush);
    DeleteObject(hGreenBrush);
    DeleteObject(hBlueBrush);
    SelectObject(hdcMemory, hOldBitmap);
    ReleaseDC(hwnd, hdc);
    DeleteDC(hdcMemory);
    return hBitmap;
}

This function carries out the same steps described at the end of Section 11.2.3, “Creating a Bitmap with Hard-Coded Bits.”