Creating a Square Meal Dialog Box

Following are the dialog box procedure and supporting functions for the Square Meal dialog box.

HWND hwndMain; 
HWND hwndEdit; 
char achTemp[256];       // temporary buffer 
 
HBITMAP hbmBread; 
HBITMAP hbmDairy; 
HBITMAP hbmFruit; 
HBITMAP hbmMeat; 
HBITMAP hbmBreadMask; 
HBITMAP hbmDairyMask; 
HBITMAP hbmFruitMask; 
HBITMAP hbmMeatMask; 
 
/******************************************************** 
 
    FUNCTION:   FoodDlgProc 
 
    PURPOSE:    Dialog procedure for Food dialog box. 
 
*********************************************************/ 
 
BOOL CALLBACK FoodDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    LPMEASUREITEMSTRUCT lpmis; 
    LPDRAWITEMSTRUCT lpdis; 
    HBITMAP hbmIcon; 
    HBITMAP hbmMask; 
    COLORREF clrBackground; 
    COLORREF clrForeground; 
    TEXTMETRIC tm; 
    HDC hdc; 
    HWND hwnd; 
    int x; 
    int y; 
 
    switch (msg) 
    { 
        case WM_INITDIALOG: 
 
            // Call an application-defined function to load 
            // bitmap resources. 
 
            if (!LoadIconBitmaps()) 
            { 
                EndDialog(hwndDlg, -1); 
                break; 
            } 
 
            // Initialize the drop-down list box. 
 
            if (!InitGroupList(hwndDlg)) 
            { 
                DeleteIconBitmaps(); 
                EndDialog(hwndDlg, -1); 
                break; 
            } 
 
            // Select the first food group. 
 
            SendDlgItemMessage(hwndDlg, IDCOMBO, CB_SETCURSEL, 
                0, 0); 
 
            // List the foods and select the first food. 
 
            InitFoodList(hwndDlg); 
            SendDlgItemMessage(hwndDlg, IDLIST, LB_SETCURSEL, 
                0, 0); 
            break; 
 
        case WM_MEASUREITEM: 
            lpmis = (LPMEASUREITEMSTRUCT) lParam; 
 
            if (lpmis->itemHeight < CY_BITMAP + 2) 
                lpmis->itemHeight = CY_BITMAP + 2; 
 
            break; 
 
        case WM_DRAWITEM: 
            lpdis = (LPDRAWITEMSTRUCT) lParam; 
            if (lpdis->itemID == -1)            // empty item 
                break; 
 
            // Determine the bitmaps used to draw the icon. 
 
            switch (lpdis->itemData) 
            { 
                case ID_BREAD: 
                    hbmIcon = hbmBread; 
                    hbmMask = hbmBreadMask; 
                    break; 
 
                case ID_DAIRY: 
                    hbmIcon = hbmDairy; 
                    hbmMask = hbmDairyMask; 
                    break; 
 
                case ID_FRUIT: 
                    hbmIcon = hbmFruit; 
                    hbmMask = hbmFruitMask; 
                    break; 
 
                default:                /* meat */ 
                    hbmIcon = hbmMeat; 
                    hbmMask = hbmMeatMask; 
                    break; 
            } 
 
            // The colors depend on whether the item is selected. 
 
            clrForeground = SetTextColor(lpdis->hDC, 
                GetSysColor(lpdis->itemState & ODS_SELECTED ? 
                COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT)); 
 
            clrBackground = SetBkColor(lpdis->hDC, 
                GetSysColor(lpdis->itemState & ODS_SELECTED ? 
                COLOR_HIGHLIGHT : COLOR_WINDOW)); 
 
            // Calculate the vertical and horizontal position. 
 
            GetTextMetrics(lpdis->hDC, &tm); 
            y = (lpdis->rcItem.bottom + lpdis->rcItem.top - 
                tm.tmHeight) / 2; 
            x = LOWORD(GetDialogBaseUnits()) / 4; 
 
            // Get and display the text for the list item. 
 
            SendMessage(lpdis->hwndItem, CB_GETLBTEXT, 
                lpdis->itemID, (LPARAM) (LPCSTR) achTemp); 
 
            ExtTextOut(lpdis->hDC, CX_BITMAP + 2 * x, y, 
                ETO_CLIPPED | ETO_OPAQUE, &lpdis->rcItem, 
                achTemp, lstrlen(achTemp), NULL); 
 
            // Restore the previous colors. 
 
            SetTextColor(lpdis->hDC, clrForeground); 
            SetBkColor(lpdis->hDC, clrBackground); 
 
            // Show the icon. 
 
            hdc = CreateCompatibleDC(lpdis->hDC); 
            if (hdc == NULL) 
                break; 
 
            SelectObject(hdc, hbmMask); 
            BitBlt(lpdis->hDC, x, lpdis->rcItem.top + 1, 
                CX_BITMAP, CY_BITMAP, hdc, 0, 0, SRCAND); 
 
            SelectObject(hdc, hbmIcon); 
            BitBlt(lpdis->hDC, x, lpdis->rcItem.top + 1, 
                CX_BITMAP, CY_BITMAP, hdc, 0, 0, SRCPAINT); 
 
            DeleteDC(hdc); 
 
            // If the item has the focus, draw focus rectangle. 
 
            if (lpdis->itemState & ODS_FOCUS) 
                DrawFocusRect(lpdis->hDC, &lpdis->rcItem); 
 
            break; 
 
        case WM_COMMAND: 
            switch (LOWORD(wParam)) 
            { 
                case IDCOMBO: 
                    if (HIWORD(wParam) == CBN_SELENDOK) 
                    { 
                        InitFoodList(hwndDlg); 
                        SendDlgItemMessage(hwndDlg, IDLIST, 
                            LB_SETCURSEL, 0, 0); 
                    } 
                    break; 
 
                case IDLIST: 
                    if (HIWORD(wParam) != LBN_DBLCLK) 
                        break; 
 
                    // For a double-click, process the OK case. 
 
                case IDOK: 
 
                    // Get the text for the selected list item. 
 
                    hwnd = GetDlgItem(hwndDlg, IDLIST); 
                    SendMessage(hwnd, LB_GETTEXT, 
                        SendMessage(hwnd, LB_GETCURSEL, 0, 0), 
                        (LPARAM) achTemp); 
 
                    // Insert the text into the edit window. 
 
                    SendMessage(hwndEdit, EM_REPLACESEL, 0, 
                        (LPARAM) achTemp); 
 
                    EndDialog(hwndDlg, 0); 
                    break; 
 
                case IDCANCEL: 
                    hwnd = GetDlgItem(hwndDlg, IDCOMBO); 
                    if (SendMessage(hwnd, CB_GETDROPPEDSTATE, 0, 0)) 
                        SendMessage(hwnd, CB_SHOWDROPDOWN, FALSE, 0); 
                    else EndDialog(hwndDlg, 0); 
            } 
            break; 
 
        case WM_DESTROY: 
 
            // Call the application-defined function to free the
            // bitmap resources. 
 
            DeleteIconBitmaps(); 
            break; 
 
        default: 
            return FALSE; 
    } 
    return TRUE; 
} 
 
 
/******************************************************** 
 
    FUNCTION:   InitGroupList 
 
    PURPOSE:    Initializes the "food groups" drop-down 
                list box. 
 
    COMMENTS:   The ID of the food group associated with 
                each list item is saved as item data. 
 
*********************************************************/ 
 
BOOL PASCAL InitGroupList(HWND hwndDlg) 
{ 
    HWND hwndCombo = GetDlgItem(hwndDlg, IDCOMBO); 
    DWORD dwIndex; 
 
    // Add an item for each food group. 
 
    LoadString(hinst, ID_BREAD, achTemp, sizeof(achTemp)); 
    dwIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0, 
        (LPARAM) (LPCSTR) achTemp); 
    SendMessage(hwndCombo, CB_SETITEMDATA, dwIndex, ID_BREAD); 
 
    LoadString(hinst, ID_DAIRY, achTemp, sizeof(achTemp)); 
    dwIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0, 
        (LPARAM) (LPCSTR) achTemp); 
    SendMessage(hwndCombo, CB_SETITEMDATA, dwIndex, ID_DAIRY); 
 
    LoadString(hinst, ID_FRUIT, achTemp, sizeof(achTemp)); 
    dwIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0, 
        (LPARAM) (LPCSTR) achTemp); 
    SendMessage(hwndCombo, CB_SETITEMDATA, dwIndex, ID_FRUIT); 
 
    LoadString(hinst, ID_MEAT, achTemp, sizeof(achTemp)); 
    dwIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0, 
        (LPARAM) (LPCSTR) achTemp); 
    SendMessage(hwndCombo, CB_SETITEMDATA, dwIndex, ID_MEAT); 
 
    return TRUE; 
} 
 
 
/******************************************************** 
 
    FUNCTION:   InitFoodList 
 
    PURPOSE:    Clears the contents of the food list, and 
                adds the names of foods for the current 
                food group. 
 
*********************************************************/ 
 
void PASCAL InitFoodList(HWND hwndDlg) 
{ 
    HWND hwndCombo = GetDlgItem(hwndDlg, IDCOMBO); 
    HWND hwndList = GetDlgItem(hwndDlg, IDLIST); 
    UINT idFoodGroup; 
    LPSTR lpsz; 
    LPSTR lpszEnd; 
 
    // Determine the current food group. 
 
    idFoodGroup = SendMessage( 
        hwndCombo, 
        CB_GETITEMDATA, 
        SendMessage(hwndCombo, CB_GETCURSEL, 0, 0), 
        0 
    ); 
 
    // Clear the list contents. 
 
    SendMessage(hwndList, LB_RESETCONTENT, 0, 0); 
 
   // . 
   // . Add food names for the current food group. 
   // . 
 
}