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.
// .
}