Making a List Box Item Unavailable for Selection

Last reviewed: November 2, 1995
Article ID: Q74792
The information in this article applies to:
  • Microsoft Windows Software Development Kit (SDK) versions 3.1
  • Microsoft Win32 Application Programming Interface (API) included with:

        - Microsoft Windows NT versions 3.5 and 3.51
        - Microsoft Windows 95 version 4.0
    

SUMMARY

In the Microsoft Windows graphical environment, an application can use a list box to enumerate options. However, there are circumstances in which one or more options may not be appropriate. The application can change the appearance of items in a list box and prevent the user from selecting one of these items by using the techniques discussed below.

MORE INFORMATION

Changing the Appearance of a List Box Item

To dim (gray) a particular item in a list box, use an owner-draw list box as follows:

  1. Create a list box that has the LBS_OWNERDRAW and LBS_HASSTRINGS styles.

  2. Use the following code to process the WM_MEASUREITEM message:

    case WM_MEASUREITEM:

          ((MEASUREITEMSTRUCT FAR *)(lParam))->itemHeight = wItemHeight;
          break;
    

    wItemHeight is the height of a character in the list box font.

  3. Use the following code to process the WM_DRAWITEM message:

       #define PHDC (pDIS->hDC)
       #define PRC  (pDIS->rcItem)
    
       DRAWITEMSTRUCT FAR *pDIS;
    
          ...
    
       case WM_DRAWITEM:
          pDIS = (DRAWITEMSTRUCT FAR *)lParam;
    
          /* Draw the focus rectangle for an empty list box or an
             empty combo box to indicate that the control has the
             focus
           */
          if ((int)(pDIS->itemID) < 0)
          {
             switch(pDIS->CtlType)
             {
                case ODT_LISTBOX:
                   if ((pDIS->itemAction) & (ODA_FOCUS))
                      DrawFocusRect (PHDC, &PRC);
                   break;
    
                case ODT_COMBOBOX:
                   if ((pDIS->itemState) & (ODS_FOCUS))
                      DrawFocusRect (PHDC, &PRC);
                   break;
             }
             return TRUE;
          }
    
          /* Get the string */
          switch(pDIS->CtlType)
          {
             case ODT_LISTBOX:
                SendMessage ( pDIS->hwndItem,
                              LB_GETTEXT,
                              pDIS->itemID,
                              (LPARAM)(LPSTR)szBuf);
                break;
    
             case ODT_COMBOBOX:
                SendMessage ( pDIS->hwndItem,
                              CB_GETLBTEXT,
                              pDIS->itemID,
                              (LPARAM)(LPSTR)szBuf);
                break;
          }
    
          if (*szBuf == '!')   // This string is disabled
          {
             hbrGray = CreateSolidBrush (GetSysColor
                                           (COLOR_GRAYTEXT));
             GrayString ( PHDC,
                          hbrGray,
                          NULL,
                          (LPARAM)(LPSTR)(szBuf + 1),
                          0,
                          PRC.left,
                          PRC.top,
                          0,
                          0);
             DeleteObject (hbrGray);
    
             /* SPECIAL CASE - Need to draw the focus rectangle if
                there is no current selection in the list box, the
                1st item in the list box is disabled, and the 1st
                item has gained or lost the focus
              */
             if (pDIS->CtlType == ODT_LISTBOX)
             {
                if (SendMessage ( pDIS->hwndItem,
                                  LB_GETCURSEL,
                                  0,
                                  0L) == LB_ERR)
                   if ( (pDIS->itemID == 0) &&
                        ((pDIS->itemAction) & (ODA_FOCUS)))
                      DrawFocusRect (PHDC, &PRC);
             }
          }
    
          else  // This string is enabled
          {
             if ((pDIS->itemState) & (ODS_SELECTED))
             {
                /* Set background and text colors for selected
                   item */
                crBack = GetSysColor (COLOR_HIGHLIGHT);
                crText = GetSysColor (COLOR_HIGHLIGHTTEXT);
             }
             else
             {
                /* Set background and text colors for unselected
                   item */
                crBack = GetSysColor (COLOR_WINDOW);
                crText = GetSysColor (COLOR_WINDOWTEXT);
             }
    
             // Fill item rectangle with background color
             hbrBack = CreateSolidBrush (crBack);
             FillRect (PHDC, &PRC, hbrBack);
             DeleteObject (hbrBack);
    
             // Set current background and text colors
             SetBkColor (PHDC, crBack);
             SetTextColor (PHDC, crText);
    
             // TextOut uses current background and text colors
             TextOut ( PHDC,
                       PRC.left,
                       PRC.top,
                       szBuf,
                       lstrlen(szBuf));
    
             /* If enabled item has the input focus, call
                DrawFocusRect to set or clear the focus
                rectangle */
             if ((pDIS->itemState) & (ODS_FOCUS))
                DrawFocusRect (PHDC, &PRC);
          }
    
          return TRUE;
    
    
Strings that start with "!" are displayed dimmed. The exclamation mark character is not displayed.

Preventing Selection

To prevent a dimmed string from being selected, create the list box with the LBS_NOTIFY style. Then use the following code in the list box's parent window procedure to process the LBN_SELCHANGE notification:

  case WM_COMMAND:

    switch (wParam)
      {

       ...

      case IDD_LISTBOX:
        if (LBN_SELCHANGE == HIWORD(lParam))
          {
          idx = (int)SendDlgItemMessage(hDlg, wParam,
                        LB_GETCURSEL, 0, 0L);
          SendDlgItemMessage(hDlg, wParam, LB_GETTEXT, idx,
                        (LONG)(LPSTR)szBuf);
          if ('!' == *szBuf)
            {
            // Calculate an alternate index here
            // (not shown in this example).

            // Then set the index.
            SendDlgItemMessage(hDlg, wParam, LB_SETCURSEL, idx, 0L);
            }
          }
        break;

       ...

      }
   break;

When the user attempts to select a dimmed item, the alternate index calculation moves the selection to an available item.


Additional reference words: 3.00 3.10 3.50 4.00 95 listbox
KBCategory: kbui
KBSubcategory: UsrCtl


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: November 2, 1995
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.