Handling Notifications

OK. You have your list view control, you have your image lists, you're able to switch between views—but you still aren't ready to compile, link, and run. Before you do that, you must set up a way to handle the WM_NOTIFY messages that will be sent to the parent window. List view controls receive notifications when text is needed for display, when items are being dragged and dropped, when labels are being edited, and when columns are being sorted (to name just a few cases). The C code you'll see next is an implementation of a handler that I set up for the WM_NOTIFY message. When the parent window receives the WM_NOTIFY message, it calls this function to determine the following:

When the WM_NOTIFY message is sent, the lParam parameter serves as a pointer to an NM_LISTVIEW or LV_DISPINFO structure. Which structure lParam points to is determined by the notification sent. Each item in my list view control has an associated item containing information about the house it describes. I saved the pointer to this information in the lParam member of the LV_ITEM structure when I added the item to the control. The following code shows what the sample does in response to a request for text and in response to a column click. (We'll discuss label editing later in this chapter.)

LRESULT NotifyHandler (HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
LV_DISPINFO *pLvdi = (LV_DISPINFO *)lParam;
NM_LISTVIEW *pNm = (NM_LISTVIEW *)lParam;
HOUSEINFO *pHouse = (HOUSEINFO *)(pLvdi->item.lParam);
static char szText [10];

if (wParam != ID_LISTVIEW)
return 0L;

switch (pLvdi->hdr.code)
{
case LVN_GETDISPINFO:

switch (pLvdi->item.iSubItem)
{
case 0: // address
pLvdi->item.pszText = pHouse->szAddress;
break;

case 1: // city
pLvdi->item.pszText = pHouse->szCity;
break;

case 2: // price
sprintf (szText, "$%u", pHouse->iPrice);
pLvdi->item.pszText = szText;
break;

case 3: // number of bedrooms
sprintf (szText, "%u", pHouse->iBeds);
pLvdi->item.pszText = szText;
break;

case 4: // number of bathrooms
sprintf (szText, "%u", pHouse->iBaths);
pLvdi->item.pszText = szText;
break;

default:
break;
}
break;
§
case LVN_COLUMNCLICK:
// The user clicked a column header; sort by this criterion.
ListView_SortItems (pNm->hdr.hwndFrom,
ListViewCompareProc,
(LPARAM)(pNm->iSubItem));
break;

default:
break;
}

return 0L;
}

When I ported this sample to MFC, I had to find a way to get to the WM_NOTIFY message because ClassWizard does not offer WM_NOTIFY as an option for a message map. I decided to overload the WindowProc function in the Cwnd class and call my notification handler from there:

LRESULT CMfclistView::WindowProc (UINT message, WPARAM wParam,
LPARAM lParam)
{
if (message == WM_NOTIFY)
NotifyHandler (message, wParam, lParam);
return CView::WindowProc (message, wParam, lParam);
}