Click to Rate and Give Feedback
MSDN
MSDN Library
User Interface
Windows Controls
Control Library
List Box
 Using List Boxes
Using List Boxes
This section explains how to perform tasks associated with list boxes. The following code examples demonstrate how to perform the tasks.

Creating a Simple List Box

The following example demonstrates how a dialog box procedure creates a simple list box and fills it with the names of people on a sports team. When a name in the list is selected, additional information about the player is retrieved. The following illustration shows the dialog box.

Dialog box containing a list box

The window style for the list box includes LBS_SORT. The code initializes the dialog box while processing the WM_INITDIALOG message. As each item is added, the index of the player data in the array is saved as item data. When the selection changes, the player data is retrieved and displayed in a static control.

typedef struct 
{ 
    TCHAR tchName[MAX_PATH]; 
    TCHAR tchPosition[12]; 
    int nGamesPlayed; 
    int nGoalsScored; 
} Player; 

Player Roster[] = 
{ 
    {TEXT("Haas, Jonathan"), TEXT("Midfield"), 18, 4 }, 
    {TEXT("Pai, Jyothi"), TEXT("Forward"), 36, 12 }, 
    {TEXT("Hanif, Kerim"), TEXT("Back"), 26, 0 }, 
    {TEXT("Anderberg, Michael"), TEXT("Back"), 24, 2 }, 
    {TEXT("Jelitto, Jacek"), TEXT("Midfield"), 26, 3 }, 
    {TEXT("Raposo, Rui"), TEXT("Back"), 24, 3}, 
    {TEXT("Joseph, Brad"), TEXT("Forward"), 13, 3 }, 
    {TEXT("Bouchard, Thomas"), TEXT("Forward"), 28, 5 }, 
    {TEXT("Salmre, Ivo "), TEXT("Midfield"), 27, 7 }, 
    {TEXT("Camp, David"), TEXT("Midfield"), 22, 3 }, 
    {TEXT("Kohl, Franz"), TEXT("Goalkeeper"), 17, 0 }, 
}; 


BOOL CALLBACK DialogProc (HWND hDlg, 
                          UINT message, 
                          WPARAM wParam, 
                          LPARAM lParam)
{
    switch (message)
    {
    case WM_INITDIALOG:
        {
            // Add items to list. 
            HWND hwndList = GetDlgItem(hDlg, IDC_LIST1);  
            for (int i = 0; i < ARRAYSIZE(Roster); i++) 
            { 
                int pos = (int)SendMessage(hwndList, LB_ADDSTRING, 0, 
                    (LPARAM) Roster[i].tchName); 
                // Set the array index of the player as item data.
                // This enables us to retrieve the item from the array
                // even after the items are sorted by the list box.
                SendMessage(hwndList, LB_SETITEMDATA, pos, (LPARAM) i); 
            } 
            // Set input focus to the list box.
            SetFocus(hwndList); 
            return FALSE;               
        } 
       // return TRUE;

    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDOK:
        case IDCANCEL:
            DestroyWindow (hDlg);
            return TRUE;

        case IDC_LIST1:
            {
                switch (HIWORD(wParam)) 
                { 
                case LBN_SELCHANGE:
                    {
                        HWND hwndList = GetDlgItem(hDlg, IDC_LIST1); 

                        // Get selected index.
                        int nItem = (int)SendMessage(hwndList, LB_GETCURSEL, 0, 0); 

                        // Get item data.
                        int i = (int)SendMessage(hwndList, LB_GETITEMDATA, nItem, 0);

                        // Do something with the data from Roster[i]
                        TCHAR buff[MAX_PATH];
                        StringCbPrintf (buff, ARRAYSIZE(buff),  
                            TEXT("Position: %s\nGames played: %d\nGoals: %d"), 
                            Roster[i].tchPosition, Roster[i].nGamesPlayed, 
                            Roster[i].nGoalsScored);
                        SetDlgItemText(hDlg, IDC_STATS, buff); 
                        return TRUE; 
                    } 
                }
            }
            return TRUE;
        }

    case WM_DESTROY:
        PostQuitMessage(0);
        return TRUE;

    case WM_CLOSE:
        DestroyWindow (hDlg);
        return TRUE;
    }
    return FALSE;
}

Creating a Directory Listing in a Single-selection List Box

The following example demonstrates how to display the content of the current directory in a list box and enable the user to delete one file at a time.

In addition to the standard list box styles, this list box has the LBS_MULTICOLUMN and LBS_HSCROLL styles. The code initializes the list box by using the DlgDirList function to fill the list box with the names of all the files in the current directory. When the user chooses the Delete button, the DlgDirSelectEx function retrieves the name of the selected file. The code deletes the file by using the DeleteFile function and updates the directory list box by sending the LB_DELETESTRING message.

BOOL APIENTRY DlgDelFileProc( 
    HWND hDlg,            // window handle to dialog box 
    UINT message,         // type of message 
    UINT wParam,          // message-specific information 
    LONG lParam) 
{ 
 
    LPTSTR lpszCurDir; 
    LPTSTR lpszFileToDelete; 
    int nItem; 
    int nTotal; 
    TCHAR tchBuffer[MAX_PATH]; 
    BOOL fResult;	 
 
    switch (message) 
    { 
        case WM_INITDIALOG: 
 
           // Initialize the list box by filling it with files from 
           // the current directory. 
 
           lpszCurDir = tchBuffer; 
           GetCurrentDirectory(MAX_PATH, lpszCurDir); 
           DlgDirList(hDlg, lpszCurDir, IDL_FILES, IDS_PATHTOFILL, 0); 
           SetFocus(GetDlgItem(hDlg, IDL_FILES)); 
           return FALSE; 
 
        case WM_COMMAND: 
 
            switch (LOWORD(wParam)) 
            { 
                case IDOK: 
 
                    // When the user presses the DEL (IDOK) button, 
                    // delete the selected file. 
 
                    lpszFileToDelete = tchBuffer; 
 
                    DlgDirSelectEx(hDlg, lpszFileToDelete, MAX_PATH, 
                        IDL_FILES); 
                    fResult = DeleteFile(lpszFileToDelete); 
                    if (!fResult) 
                    { 
                        MessageBox(hDlg, "Could not delete file.", 
                            NULL, MB_OK); 
                    } 
                    else 
                    { 
                        nItem = SendMessage(GetDlgItem(hDlg, 
                                IDL_FILES), LB_GETCURSEL, 0, 0); 
 
                        nTotal = SendMessage(GetDlgItem(hDlg, 
                            IDL_FILES), LB_DELETESTRING, nItem, 0); 
 
                        // Update the list box. 
 
                        if (nTotal > nItem) 
                        { 
                            SendMessage(GetDlgItem(hDlg, IDL_FILES), 
                                LB_SETCURSEL, nItem, 0); 
                        } 
                        else 
                        { 
                            SendMessage(GetDlgItem(hDlg, IDL_FILES), 
                                LB_SETCURSEL, nTotal, 0); 
                        } 
                    } 
                    return TRUE; 
 
                case IDCANCEL: 
 
                    // Destroy the dialog box. 
 
                    EndDialog(hDlg, TRUE); 
                    return TRUE; 
 
                default: 
                    return FALSE; 
            } 
 
        default: 
            return FALSE; 
    } 
} 

Creating a Multiple-selection List Box

The following example displays and initializes the dialog box used in the preceding example. However, this code uses the LBS_MULTIPLESEL style to enable the user to select more than one file at a time. When the user chooses the Delete button, the example sends the LB_GETSELCOUNT message (to retrieve the number of files selected) and the LB_GETSELITEMS message (to retrieve an array of selected list box items). After deleting a file, the code removes the corresponding item from the list box by sending the LB_DELETESTRING message.

#define BUFFER MAX_PATH 
 
#define BIGBUFF 8192 
 
BOOL APIENTRY DlgDelFilesProc( 
    HWND hDlg,            // window handle to dialog box 
    UINT message,         // type of message 
    UINT wParam,          // message-specific information 
    LONG lParam) 
{ 
    DWORD cchCurDir; 
    LPTSTR lpszCurDir; 
    LPTSTR lpszFileToDelete; 
    int nSelItems; 
    int nSelItemsInBuffer; 
    TCHAR tchBuffer[BUFFER+1]; 
    TCHAR tchMsgBuff[BUFFER+1]; 
    int nBuffer[BIGBUFF]; 
    int i; 
    BOOL fResult; 
    HWND hListBox;
	HRESULT hr; 
 
    switch (message) { 
 
        case WM_INITDIALOG: 
 
           // Initialize the list box by filling it with files from 
           // the current directory. 
 
           lpszCurDir = tchBuffer; 
           GetCurrentDirectory(cchCurDir, lpszCurDir);
		   lpszCurDir[BUFFER+1] = '\0'; 
           DlgDirList(hDlg, lpszCurDir, IDL_FILES, IDS_PATHTOFILL, 0); 
 
           SetFocus(GetDlgItem(hDlg, IDL_FILES)); 
 
           return FALSE; 
 
        case WM_COMMAND: 
 
            switch (LOWORD(wParam)) 
            { 
                case IDOK: 
 
                    // When the user presses the Delete (IDOK) 
                    // button, delete all the selected files. 
 
                    lpszFileToDelete = tchBuffer; 
 
                    hListBox = GetDlgItem(hDlg, IDL_FILES); 
                    nSelItems = SendMessage(hListBox, 
                            LB_GETSELCOUNT, 0, 0); 
 
                    nSelItemsInBuffer = SendMessage(hListBox, 
                            LB_GETSELITEMS, 512, (LPARAM) nBuffer); 
 
                    if (nSelItems > nSelItemsInBuffer) 
                    { 
                        MessageBox(hDlg, "Too many items selected.", 
                                NULL, MB_OK); 
                    } 
                    else 
                    { 
                        // Go through the list backward because after 
                        // deleting an item the indices change for 
                        // every subsequent item. By going backward, 
                        // the indices are never invalidated. 
 
                        for (i = nSelItemsInBuffer - 1; i >= 0; i--) 
                        { 
                            SendMessage(hListBox, LB_GETTEXT, 
                                        nBuffer[i], 
                                        (LPARAM) lpszFileToDelete); 
 
                            fResult = DeleteFile(lpszFileToDelete); 
                            if (!fResult) 
                            {                     
                                hr = StringCchPrintf(tchMsgBuff,
                                    BUFFER, "Could not delete file: %s " 
                                    "GetLastError = %u", 
                                    (LPARAM) lpszFileToDelete);
                                if (FAILED(hr))
                                {
                                    // TODO: Handle error.
                                }
                            } 
                            else 
                            { 
                                SendMessage(hListBox, LB_DELETESTRING, 
                                        nBuffer[i], 0); 
                            } 
                        } 
                        SendMessage(hListBox, LB_SETCARETINDEX, 0, 0); 
                    } 
                    return TRUE; 
 
                case IDCANCEL: 
 
                    // Destroy the dialog box. 
 
                    EndDialog(hDlg, TRUE); 
                    return TRUE; 
 
                default: 
                    return FALSE; 
            } 
 
        default: 
                return FALSE; 
    } 
} 

Creating an Owner-drawn List Box

The following example shows how to draw a list box that contains five owner-drawn items: four drawing implements and a fork. Each list item appears as a bitmap followed by the name of the object. A button prompts the user to select one item that is not like the others. Choosing the button with the fork selected displays a "You're right!" message and closes the dialog box. Choosing the button with any other list item selected displays a "Try again!" message.

The list box has the LBS_OWNERDRAW and LBS_HASSTRINGS styles, in addition to the standard list box styles. The code initializes the list box by sending the LB_ADDSTRING message to set the text, and then sends the LB_SETITEMDATA message to associate a bitmap with each list box item. The code also sets the height of each list box item by processing the WM_MEASUREITEM message and draws the text and bitmap for each item by processing the WM_DRAWITEM message.

#define XBITMAP 80 
#define YBITMAP 20 
 
#define BUFFER MAX_PATH 
 
HBITMAP hbmpPencil, hbmpCrayon, hbmpMarker, hbmpPen, hbmpFork; 
HBITMAP hbmpPicture, hbmpOld; 
 
void AddItem(HWND hwnd, LPSTR lpstr, HBITMAP hbmp) 
{ 
    int nItem; 
 
    nItem = SendMessage(hwnd, LB_ADDSTRING, 0, (LPARAM)lpstr); 
    SendMessage(hwnd, LB_SETITEMDATA, (WPARAM)nItem, (LPARAM)hbmp); 
} 
 
DWORD APIENTRY DlgDrawProc( 
        HWND hDlg,            // window handle to dialog box 
        UINT message,         // type of message 
        UINT wParam,          // message-specific information 
        LONG lParam) 
{ 
    int nItem; 
    TCHAR tchBuffer[BUFFER]; 
    HBITMAP hbmp; 
    HWND hListBox; 
    TEXTMETRIC tm; 
    int y; 
    HDC hdcMem; 
    LPMEASUREITEMSTRUCT lpmis; 
    LPDRAWITEMSTRUCT lpdis; 
    RECT rcBitmap;
	HRESULT hr; 
	size_t * pcch;
 
    switch (message) 
    { 
 
        case WM_INITDIALOG: 
 
            // Load bitmaps. 
 
            hbmpPencil = LoadBitmap(hinst, MAKEINTRESOURCE(700)); 
            hbmpCrayon = LoadBitmap(hinst, MAKEINTRESOURCE(701)); 
            hbmpMarker = LoadBitmap(hinst, MAKEINTRESOURCE(702)); 
            hbmpPen = LoadBitmap(hinst, MAKEINTRESOURCE(703)); 
            hbmpFork = LoadBitmap(hinst, MAKEINTRESOURCE(704)); 
 
            // Retrieve list box handle. 
 
            hListBox = GetDlgItem(hDlg, IDL_STUFF); 
 
            // Initialize the list box text and associate a bitmap 
            // with each list box item. 
 
            AddItem(hListBox, "pencil", hbmpPencil); 
            AddItem(hListBox, "crayon", hbmpCrayon); 
            AddItem(hListBox, "marker", hbmpMarker); 
            AddItem(hListBox, "pen",    hbmpPen); 
            AddItem(hListBox, "fork",   hbmpFork); 
 
            SetFocus(hListBox); 
            SendMessage(hListBox, LB_SETCURSEL, 0, 0); 
            return TRUE; 
 
        case WM_MEASUREITEM: 
 
            lpmis = (LPMEASUREITEMSTRUCT) lParam; 
 
            // Set the height of the list box items. 
 
            lpmis->itemHeight = 20; 
            return TRUE; 
 
        case WM_DRAWITEM: 
 
            lpdis = (LPDRAWITEMSTRUCT) lParam; 
 
            // If there are no list box items, skip this message. 
 
            if (lpdis->itemID == -1) 
            { 
                break; 
            } 
 
            // Draw the bitmap and text for the list box item. Draw a 
            // rectangle around the bitmap if it is selected. 
 
            switch (lpdis->itemAction) 
            { 
                case ODA_SELECT: 
                case ODA_DRAWENTIRE: 
 
                    // Display the bitmap associated with the item. 
 
                    hbmpPicture =(HBITMAP)SendMessage(lpdis->hwndItem, 
                        LB_GETITEMDATA, lpdis->itemID, (LPARAM) 0); 
 
                    hdcMem = CreateCompatibleDC(lpdis->hDC); 
                    hbmpOld = SelectObject(hdcMem, hbmpPicture); 
 
                    BitBlt(lpdis->hDC, 
                        lpdis->rcItem.left, lpdis->rcItem.top, 
                        lpdis->rcItem.right - lpdis->rcItem.left, 
                        lpdis->rcItem.bottom - lpdis->rcItem.top, 
                        hdcMem, 0, 0, SRCCOPY); 
 
                    // Display the text associated with the item. 
 
                    SendMessage(lpdis->hwndItem, LB_GETTEXT, 
                        lpdis->itemID, (LPARAM) tchBuffer); 
 
                    GetTextMetrics(lpdis->hDC, &tm); 
 
                    y = (lpdis->rcItem.bottom + lpdis->rcItem.top - 
                        tm.tmHeight) / 2;
						
                    hr = StringCchLength(tchBuffer, BUFFER, pcch);
                    if (FAILED(hr))
                    {
                        // TODO: Handle error.
                    }
 
                    TextOut(lpdis->hDC, 
                        XBITMAP + 6, 
                        y, 
                        tchBuffer, 
                        pcch); 						
 
                    SelectObject(hdcMem, hbmpOld); 
                    DeleteDC(hdcMem); 
 
                    // Is the item selected? 
 
                    if (lpdis->itemState & ODS_SELECTED) 
                    { 
                        // Set RECT coordinates to surround only the 
                        // bitmap. 
 
                        rcBitmap.left = lpdis->rcItem.left; 
                        rcBitmap.top = lpdis->rcItem.top; 
                        rcBitmap.right = lpdis->rcItem.left + XBITMAP; 
                        rcBitmap.bottom = lpdis->rcItem.top + YBITMAP; 
 
                        // Draw a rectangle around bitmap to indicate 
                        // the selection. 
 
                        DrawFocusRect(lpdis->hDC, &rcBitmap); 
                    } 
                    break; 
 
                case ODA_FOCUS: 
 
                    // Do not process focus changes. The focus caret 
                    // (outline rectangle) indicates the selection. 
                    // The IDOK button indicates the final 
                    // selection. 
 
                    break; 
            } 
            return TRUE; 
 
        case WM_COMMAND: 
 
            switch (LOWORD(wParam)) 
            { 
                case IDOK: 
                    // Get the selected item's text. 
 
                    nItem = SendMessage(GetDlgItem(hDlg, IDL_STUFF), 
                       LB_GETCURSEL, 0, (LPARAM) 0); 
                       hbmp = SendMessage(GetDlgItem(hDlg, IDL_STUFF), 
                            LB_GETITEMDATA, nItem, 0); 
 
                    // If the item is not the correct answer, tell the 
                    // user to try again. 
                    //
                    // If the item is the correct answer, congratulate 
                    // the user and destroy the dialog box. 
 
                    if (hbmp != hbmpFork) 
                    { 
                        MessageBox(hDlg, "Try again!", "Oops", MB_OK); 
                        return FALSE; 
                    } 
                    else 
                    { 
                        MessageBox(hDlg, "You're right!", 
                            "Congratulations.", MB_OK); 
 
                      // Fall through. 
                    } 
 
                case IDCANCEL: 
 
                    // Destroy the dialog box. 
 
                    EndDialog(hDlg, TRUE); 
                    return TRUE; 
 
                default: 
 
                    return FALSE; 
            } 
 
        case WM_DESTROY: 
 
            // Free any resources used by the bitmaps. 
 
            DeleteObject(hbmpPencil); 
            DeleteObject(hbmpCrayon); 
            DeleteObject(hbmpMarker); 
            DeleteObject(hbmpPen); 
            DeleteObject(hbmpFork); 
 
            return TRUE; 
 
        default: 
            return FALSE; 
 
    } 
    return FALSE; 
} 
Tags What's this?: Add a tag
Community Content   What is Community Content?
Add new content RSS  Annotations
Processing
© 2009 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks | Privacy Statement | Site Feedback
Page view tracker