About List Boxes
A list box control contains a simple list from which the user can generally select one or more items. List boxes provide limited flexibility compared with List View controls.
List box items can be represented by text strings, bitmaps, or both. If the list box is not large enough to display all the list box items at once, the list box provides a scroll bar. The user scrolls through the list box items and applies or removes selection status as necessary. Selecting a list box item changes its visual appearance, usually by changing the text and background colors to those specified by the relevant operating system metrics. When the user selects or deselects an item, the system sends a notification message to the parent window of the list box.
For an ANSI application, the system converts the text in a list box to Unicode by using the CP_ACP code page. This can cause problems. For example, accented Roman characters in a non-Unicode list box in Windows, Japanese version will come out garbled. To fix this, either compile the application as Unicode or use an owner-drawn list box.
This section discusses the following topics:
- Creating a List Box
- List Box Types and Styles
- List Box Functions
- Notification Messages from List Boxes
- Messages to List Boxes
- Default Window Message Processing
- Owner-Drawn List Boxes
- Drag List Boxes
Creating a List Box
The easiest way to create a list box in a dialog box is to drag it from the Toolbox in Microsoft Visual Studio onto your dialog resource. To create a list box dynamically, or to create a list box in a window other than a dialog box, use the CreateWindowEx function, specifying the WC_LISTBOX window class and the appropriate list box styles.
List Box Types and Styles
There are two types of list boxes: single-selection (the default) and multiple-selection. In a single-selection list box, the user can select only one item at a time. In a multiple-selection list box, the user can select more than one item at a time. To create a multiple-selection list box, specify the LBS_MULTIPLESEL or the LBS_EXTENDEDSEL style.
The appearance and operation of a list box is controlled by list box styles and window styles. These styles indicate whether the list is sorted, arranged in multiple columns, drawn by the application, and so on. The dimensions and styles of a list box are typically defined in a dialog box template that is included in an application's resources.
To use visual styles with these controls, an application must include a manifest and must call InitCommonControls at the beginning of the program. For information on visual styles, see Visual Styles. For information on manifests, see Enabling Visual Styles.
List Box Functions
The DlgDirList function replaces the contents of a list box with the names of drives, directories, and files that match a specified set of criteria. The DlgDirSelectEx function retrieves the current selection in a list box that is initialized by DlgDirList. These functions make it possible for the user to select a drive, directory, or file from a list box without typing the location and name of the file.
Also, the GetListBoxInfo function returns the number of items per column in a specified list box.
Notification Messages from List Boxes
When an event occurs in a list box, the list box sends a notification code, in the form of a WM_COMMAND message, to the dialog box procedure of the owner window. List box notification codes are sent when a user selects, double-clicks, or cancels a list box item; when the list box receives or loses the keyboard focus; and when the system cannot allocate enough memory for a list box request. A WM_COMMAND message contains the list box identifier in the low-order word of the wParam parameter, and the notification code in the high-order word. The lParam parameter contains the control window handle.
A dialog box procedure is not required to process these messages; the default window procedure processes them.
An application should monitor and process the following list box notification codes.
|LBN_DBLCLK||The user double-clicks an item in the list box.|
|LBN_ERRSPACE||The list box cannot allocate enough memory to fulfill a request.|
|LBN_KILLFOCUS||The list box loses the keyboard focus.|
|LBN_SELCANCEL||The user cancels the selection of an item in the list box.|
|LBN_SELCHANGE||The selection in a list box is about to change.|
|LBN_SETFOCUS||The list box receives the keyboard focus.|
Messages to List Boxes
A dialog box procedure can send messages to a list box to add, delete, examine, and change list box items. For example, a dialog box procedure could send an LB_ADDSTRING message to a list box to add an item, and an LB_GETSEL message to determine whether the item is selected. Other messages set and retrieve information about the size, appearance, and behavior of the list box. For example, the LB_SETHORIZONTALEXTENT message sets the scrollable width of a list box. A dialog box procedure can send any message to a list box by using the SendMessage or SendDlgItemMessage function.
A list box item is often referenced by its index, an integer that represents the item's position in the list box. The index of the first item in a list box is 0, the index of the second item is 1, and so on.
The following table describes how the predefined list box procedure responds to list box messages.
|LB_ADDFILE||Inserts a file into a directory list box that is filled by the DlgDirList function and retrieves the list box index of the inserted item.|
|LB_ADDSTRING||Adds a string to a list box and returns its index.|
|LB_DELETESTRING||Removes a string from a list box and returns the number of strings that remain in the list.|
|LB_DIR||Adds a list of file names to a list box and returns the index of the last file name added.|
|LB_FINDSTRING||Returns the index of the first string in the list box that begins with a specified string.|
|LB_FINDSTRINGEXACT||Returns the index of the string in the list box that is equal to a specified string.|
|LB_GETANCHORINDEX||Returns the index of the item that the mouse last selected.|
|LB_GETCARETINDEX||Returns the index of the item that has the focus rectangle.|
|LB_GETCOUNT||Returns the number of items in the list box.|
|LB_GETCURSEL||Returns the index of the currently selected item.|
|LB_GETHORIZONTALEXTENT||Returns the scrollable width, in pixels, of a list box.|
|LB_GETITEMDATA||Returns the value that is associated with the specified item.|
|LB_GETITEMHEIGHT||Returns the height, in pixels, of an item in a list box.|
|LB_GETITEMRECT||Retrieves the client coordinates of the specified list box item.|
|LB_GETLOCALE||Retrieves the locale of the list box. The high-order word contains the country/region code and the low-order word contains the language identifier.|
|LB_GETSEL||Returns the selection state of a list box item.|
|LB_GETSELCOUNT||Returns the number of selected items in a multiple-selection list box.|
|LB_GETSELITEMS||Creates an array of the indexes of all selected items in a multiple-selection list box and returns the total number of selected items.|
|LB_GETTEXT||Retrieves the string associated with a specified item and the length of the string.|
|LB_GETTEXTLEN||Returns the length, in characters, of the string associated with a specified item.|
|LB_GETTOPINDEX||Returns the index of the first visible item in a list box.|
|LB_INITSTORAGE||Allocates memory for the specified number of items and their associated strings.|
|LB_INSERTSTRING||Inserts a string at a specified index in a list box.|
|LB_ITEMFROMPOINT||Retrieves the zero-based index of the item nearest the specified point in a list box.|
|LB_RESETCONTENT||Removes all items from a list box.|
|LB_SELECTSTRING||Selects the first string it finds that matches a specified prefix.|
|LB_SELITEMRANGE||Selects a specified range of items in a list box.|
|LB_SELITEMRANGEEX||Selects a specified range of items if the index of the first item in the range is less than the index of the last item in the range. Cancels the selection in the range if the index of the first item is greater than the last.|
|LB_SETANCHORINDEX||Sets the item that the mouse last selected to a specified item.|
|LB_SETCARETINDEX||Sets the focus rectangle to a specified list box item.|
|LB_SETCOLUMNWIDTH||Sets the width, in pixels, of all columns in a list box.|
|LB_SETCOUNT||Sets the number of items in a list box.|
|LB_SETCURSEL||Selects a specified list box item.|
|LB_SETHORIZONTALEXTENT||Sets the scrollable width, in pixels, of a list box.|
|LB_SETITEMDATA||Associates a value with a list box item.|
|LB_SETITEMHEIGHT||Sets the height, in pixels, of an item or items in a list box.|
|LB_SETLOCALE||Sets the locale of a list box and returns the previous locale identifier.|
|LB_SETSEL||Selects an item in a multiple-selection list box.|
|LB_SETTABSTOPS||Sets the tab stops to those specified in a specified array.|
|LB_SETTOPINDEX||Scrolls the list box so the specified item is at the top of the visible range.|
Default Window Message Processing
The window procedure for the predefined list box window class carries out default processing for all messages that the list box does not process. When the list box procedure returns FALSE for a message, the predefined window procedure checks the message and performs default actions, as shown in the following table.
|WM_CHAR||Moves the selection to the first item that begins with the character that the user typed. If the list box has the LBS_OWNERDRAW style, no action occurs. Multiple characters that are typed within a short interval are treated as a group, and the first item that begins with that series of characters is selected.
|WM_CREATE||Creates an empty list box.|
|WM_DESTROY||Destroys the list box and frees any resources that it uses.|
|Passes the message to the dialog box procedure or parent window process.|
|WM_ENABLE||If the control is visible, invalidates the rectangle so the strings can be painted gray.|
|WM_ERASEBKGND||Erases the background of a list box. If the list box has the LBS_OWNERDRAW style, the background is not erased.|
|WM_GETDLGCODE||Returns DLGC_WANTARROWS | DLGC_WANTCHARS, indicating that the default list box procedure processes the arrow keys and WM_CHAR messages.|
|WM_GETFONT||Returns a handle to the current font for the list box.|
|WM_HSCROLL||Scrolls the list box horizontally.|
|WM_KEYDOWN||Processes virtual keys for scrolling. The virtual key is the index of the item to move the caret to. The selection is not changed.|
|WM_KILLFOCUS||Turns the caret off and destroys it. Sends an LBN_KILLFOCUS notification code to the owner of the list box.|
|WM_LBUTTONDBLCLK||Tracks the mouse in the list box client area. This enables the user to cancel a selection if the mouse button is released outside the list box client area.|
|WM_LBUTTONDOWN||Tracks the mouse in the list box client area. This enables the user to cancel a selection if the mouse button is released outside the list box client area.|
|WM_LBUTTONUP||Tracks the mouse in the list box client area. This enables the user to cancel a selection if the mouse button is released outside the list box client area.|
|WM_PAINT||Performs a subclassed paint operation by using the list box handle to the device context (DC).|
|WM_SETFOCUS||Turns the caret on and sends an LBN_SETFOCUS notification code to the owner of the list box.|
|WM_SETFONT||Sets a new font for the list box.|
|WM_SETREDRAW||Sets or clears the redraw flag based on the value of wParam.|
|WM_SIZE||Resizes the list box to an integral number of items.|
|WM_VSCROLL||Scrolls the list box vertically.|
The predefined list box procedure passes all other messages to DefWindowProc for default processing.
Owner-Drawn List Boxes
An application can create an owner-drawn list box to take responsibility for painting list items. The parent window or dialog box of an owner-drawn list box (its owner) receives WM_DRAWITEM messages when a portion of the list box needs to be painted. An owner-drawn list box can list information other than, or in addition to, text strings.
The owner of an owner-drawn list box must process the WM_DRAWITEM message. This message is sent whenever a portion of the list box must be redrawn. The owner may need to process other messages, depending on the styles specified for the list box.
An application can create an owner-drawn list box by specifying the LBS_OWNERDRAWFIXED or LBS_OWNERDRAWVARIABLE style. If all list items in the list box are the same height, such as strings or icons, an application can use the LBS_OWNERDRAWFIXED style. If list items are of varying height (for example, bitmaps of different size) an application can use the LBS_OWNERDRAWVARIABLE style.
The owner of an owner-drawn list box can process a WM_MEASUREITEM message to specify the dimensions of list items. If the application creates the list box by using the LBS_OWNERDRAWFIXED style, the system sends the WM_MEASUREITEM message only once. The dimensions that are specified by the owner are used for all list items. If the LBS_OWNERDRAWVARIABLE style is used, the system sends a WM_MEASUREITEM message for each list item that is added to the list box. The owner can determine or set the height of a list item at any time by using the LB_GETITEMHEIGHT and LB_SETITEMHEIGHT messages, respectively.
If the information displayed in an owner-drawn list box includes text, an application can keep track of the text for each list item by specifying the LBS_HASSTRINGS style. List boxes with the LBS_SORT style are sorted based on this text. If a list box is sorted, but is not of the LBS_HASSTRINGS style, the owner must process the WM_COMPAREITEM message.
In an owner-drawn list box, the owner must keep track of list items that contain information other than or in addition to text. One convenient way to do this is to save the handle to the information as item data by using the LB_SETITEMDATA message. To free data objects associated with items in a list box, the owner can process the WM_DELETEITEM message.
For an example of an owner-drawn list box, see How to Create an Owner-Drawn List Box.
Drag List Boxes
A drag list box is a special type of list box that enables the user to drag items from one position to another. An application can use a drag list box to display strings in a particular sequence and enable the user to change the sequence by dragging the items into position.
Creating Drag List Boxes
Drag list boxes have the same window styles and process the same messages as standard list boxes. To create a drag list box, first create a standard list box and then call the MakeDragList function. To convert a list box in a dialog box to a drag list box, you can call MakeDragList when the WM_INITDIALOG message is processed.
Drag List Box Messages
A drag list box notifies the parent window of drag events by sending it a drag list message. The parent window must process the drag list message.
The drag list box registers this message when the MakeDragList function is called. To retrieve the message identifier (numeric value) of the drag list message, call the RegisterWindowMessage function and specify the DRAGLISTMSGSTRING value.
The wParam parameter of the drag list message is the control identifier for the drag list box. The lParam parameter is the address of a DRAGLISTINFO structure, which contains the notification code for the drag event and other information. The return value of the message depends on the notification.
Drag List Box Notification Codes
The drag list notification code, which is identified by the uNotification member of the DRAGLISTINFO structure included with the drag list message, can be DL_BEGINDRAG, DL_DRAGGING, DL_CANCELDRAG, or DL_DROPPED.
The DL_BEGINDRAG notification code is sent when the cursor is on a list item and the user clicks the left mouse button. The parent window can return TRUE to begin the drag operation or FALSE to disallow dragging. In this way, the parent window can enable dragging for some list items and disable it for others. You can determine which list item is at the specified location by using the LBItemFromPt function.
If dragging is in effect, the DL_DRAGGING notification code is sent whenever the mouse is moved, or at regular intervals if the mouse is not being moved. The parent window should first determine the list item under the cursor by using LBItemFromPt and then draw the insert icon by using the DrawInsert function. By specifying TRUE for the bAutoScroll parameter of LBItemFromPt, you can cause the list box to scroll by one line if the cursor is above or below its client area. The value you return for this notification specifies the type of mouse cursor that the drag list box should set.
The DL_CANCELDRAG notification code is sent if the user cancels a drag operation by clicking the right mouse button or pressing the ESC key. The DL_DROPPED notification code is sent if the user completes a drag operation by releasing the left mouse button, even if the cursor is not over a list item. The drag list box releases the mouse capture before sending either notification. The return value of these two notifications is ignored. Drag List