home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winui / owncombo / owncombo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  36.0 KB  |  863 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1993 - 1997 Microsoft Corp.
  5. *       All rights reserved. 
  6. *       This source code is only intended as a supplement to 
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the 
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. /***************************************************************************
  13.  *                                                                         *
  14.  *  PROGRAM     : OwnCombo.c                                               *
  15.  *                                                                         *
  16.  *  PURPOSE     : Illustrates the use of functions and messages for        *
  17.  *                combo boxes and owner-draw control styles.               *
  18.  *                                                                         *
  19.  *  FUNCTIONS   : WinMain                - Creates the app. window and     *
  20.  *                                         enters the message loop.        *
  21.  *                                                                         *
  22.  *                OwnComboInit           - Registers the main window class *
  23.  *                                                                         *
  24.  *                About                  - Dialog function for the About   *
  25.  *                                         dialog.                         *
  26.  *                                                                         *
  27.  *                OwnComboWndProc        - Window function for app. It     *
  28.  *                                         handles the menu selections     *
  29.  *                                         and processes the other window  *
  30.  *                                         messages.                       *
  31.  *                                                                         *
  32.  *                DrawEntireItem         - Handles the drawing of a list   *
  33.  *                                         list box or combo box item.     *
  34.  *                                                                         *
  35.  *                HandleSelectionState   - Handles the selecting/deselect- *
  36.  *                                         ing of a list box or combo box  *
  37.  *                                         item.                           *
  38.  *                                                                         *
  39.  *                HandleFocusState       - Handles the getting/losing of   *
  40.  *                                         the input focus by a list box   *
  41.  *                                                                         *
  42.  *                ListBoxExample         - Dialog function for the         *
  43.  *                                         owner-draw list box example.    *
  44.  *                                                                         *
  45.  *                ComboBoxExample        - Dialog function for the text    *
  46.  *                                         combo dialog.                   *
  47.  *                                                                         *
  48.  *                OwnerComboBoxExample   - Dialog fubction for the drop-   *
  49.  *                                         down-list combobox with         *
  50.  *                                         ownerdraw.                      *
  51.  *                                                                         *
  52.  ***************************************************************************/
  53. #include "windows.h"
  54. #include "owncombo.h"
  55.  
  56. HANDLE  hInst;
  57.  
  58. /****************************************************************************
  59.  *                                                                          *
  60.  *  FUNCTION   : WinMain(HANDLE, HANDLE, LPSTR, int)                        *
  61.  *                                                                          *
  62.  *  PURPOSE    : Creates the app. window and enters the message loop.       *
  63.  *                                                                          *
  64.  ****************************************************************************/
  65.  
  66. int APIENTRY WinMain(
  67.     HINSTANCE hInstance,
  68.     HINSTANCE hPrevInstance,
  69.     LPSTR lpCmdLine,
  70.     int nCmdShow
  71.     )
  72. {
  73.  
  74.     HWND  hWnd;
  75.     MSG   msg;
  76.  
  77.     UNREFERENCED_PARAMETER( lpCmdLine );
  78.  
  79.     if (!hPrevInstance)
  80.         if (!OwnComboInit (hInstance))
  81.             return (0);
  82.  
  83.     hInst = hInstance;
  84.  
  85.     /* Create the app. window */
  86.     hWnd = CreateWindow ("owncombo",
  87.                          "Owner-draw & Combo Box Example",
  88.                          WS_OVERLAPPEDWINDOW,
  89.                          CW_USEDEFAULT,
  90.                          CW_USEDEFAULT,
  91.                          CW_USEDEFAULT,
  92.                          CW_USEDEFAULT,
  93.                          (HWND) NULL,
  94.                          NULL,
  95.                          hInstance,
  96.                          (LPSTR) NULL);
  97.  
  98.     if (!hWnd)
  99.         return (0);
  100.  
  101.     ShowWindow (hWnd, nCmdShow);
  102.  
  103.     while (GetMessage (&msg, NULL, 0, 0)){
  104.         TranslateMessage (&msg);
  105.         DispatchMessage (&msg);
  106.     }
  107.  
  108.     return(msg.wParam);
  109. }
  110.  
  111.  
  112. /****************************************************************************
  113.  *                                                                          *
  114.  *  FUNCTION   : OwnComboInit (hInstance)                                   *
  115.  *                                                                          *
  116.  *  PURPOSE    : Registers the main window class.                           *
  117.  *                                                                          *
  118.  *  RETURNS    : TRUE  - if RegisterClass () succeeds.                      *
  119.  *               FALSE - if RegisterClass () fails.                         *
  120.  *                                                                          *
  121.  ****************************************************************************/
  122. BOOL NEAR PASCAL OwnComboInit (HANDLE hInstance)
  123. {
  124.     HANDLE     hMemory;
  125.     PWNDCLASS  pWndClass;
  126.     BOOL       bSuccess;
  127.  
  128.     /* Allocate for and fill class structure. */
  129.     hMemory = LocalAlloc (LPTR, sizeof (WNDCLASS));
  130.     if(!hMemory){
  131.         MessageBox(NULL, "<OwnComboInit> Not enough memory.", NULL, MB_OK | MB_ICONHAND);
  132.         return(FALSE);
  133.     }
  134.  
  135.     pWndClass = (PWNDCLASS) LocalLock (hMemory);
  136.  
  137.     pWndClass->style         = 0;
  138.     pWndClass->lpfnWndProc   = (WNDPROC) OwnComboWndProc;
  139.     pWndClass->hInstance    = hInstance;
  140.     pWndClass->hIcon         = LoadIcon (hInstance, "owncombo");
  141.     pWndClass->hCursor       = LoadCursor (NULL, IDC_ARROW);
  142.     pWndClass->hbrBackground = GetStockObject (WHITE_BRUSH);
  143.     pWndClass->lpszMenuName  = (LPSTR) "OwnComboMenu",
  144.     pWndClass->lpszClassName = (LPSTR) "owncombo";
  145.  
  146.     bSuccess = RegisterClass (pWndClass);
  147.     LocalUnlock (hMemory);
  148.     LocalFree (hMemory);
  149.  
  150.     return (bSuccess);
  151. }
  152.  
  153. /****************************************************************************
  154.  *                                                                          *
  155.  *  FUNCTION   : About (hDlg,message, wParam, lParam)                       *
  156.  *                                                                          *
  157.  *  PURPOSE    : Dialog function for the About... dialog.                   *
  158.  *                                                                          *
  159.  ****************************************************************************/
  160. BOOL APIENTRY About (
  161.     HWND         hDlg,
  162.     UINT     message,
  163.     UINT         wParam,
  164.     LONG         lParam)
  165. {
  166.  
  167.         UNREFERENCED_PARAMETER(lParam);
  168.     switch (message){
  169.         case WM_INITDIALOG:
  170.             return(TRUE);
  171.  
  172.         case WM_COMMAND:
  173.             if (LOWORD(wParam) == IDOK){
  174.                 EndDialog (hDlg,0);
  175.                 return(FALSE);
  176.             }
  177.             break;
  178.  
  179.         default:
  180.             break;
  181.     }
  182.   return(FALSE);
  183. }
  184.  
  185.  
  186. /****************************************************************************
  187.  *                                                                          *
  188.  *  FUNCTION   : OwnComboWndProc(hWnd, message, wParam, lParam)             *
  189.  *                                                                          *
  190.  *  PURPOSE    : Window function for the app. It handles menu selections    *
  191.  *               and processes window WM_ messages.                         *
  192.  *                                                                          *
  193.  ****************************************************************************/
  194. LONG APIENTRY OwnComboWndProc (
  195.     HWND         hWnd,
  196.     UINT     message,
  197.     UINT         wParam,
  198.     LONG         lParam)
  199. {
  200.     switch (message){
  201.         case WM_COMMAND:
  202.             switch (LOWORD(wParam)){
  203.                 case IDM_EXIT:
  204.                     DestroyWindow (hWnd);
  205.                     break;
  206.  
  207.                 case IDM_ABOUT:
  208.                     /* Bring up the about box */
  209.                     DialogBox (hInst,
  210.                                "AboutBox",
  211.                                hWnd,
  212.                                About);
  213.  
  214.                     break;
  215.  
  216.                 case IDM_LISTBOX:
  217.                     /* Bring up the list box example */
  218.                     DialogBox (hInst,
  219.                                "ListBoxDialog",
  220.                                hWnd,
  221.                                About);
  222.                     break;
  223.  
  224.                 case IDM_MULTILISTBOX:
  225.                     /* Bring up the multiple selection list box example */
  226.                     DialogBox (hInst,
  227.                                "MultiListBoxDialog",
  228.                                hWnd,
  229.                                About);
  230.                     break;
  231.  
  232.                 case IDM_COMBOBOX:
  233.                     /* Bring up the combo box example */
  234.                     DialogBox (hInst,
  235.                                "ComboBoxDialog",
  236.                                hWnd,
  237.                                About);
  238.                     break;
  239.  
  240.                 case IDM_OWNERCOMBOBOX:
  241.                     /* Bring up the owner-draw dropdown list box example */
  242.                     DialogBox (hInst,
  243.                                "OwnerComboBoxDialog",
  244.                                hWnd,
  245.                                About);
  246.                     break;
  247.             }
  248.             break;
  249.  
  250.         case WM_DESTROY:
  251.             PostQuitMessage (0);
  252.             break;
  253.  
  254.         default:
  255.             return(DefWindowProc(hWnd, message, wParam, lParam));
  256.     }
  257.     return(0);
  258. }
  259.  
  260. /****************************************************************************
  261.  *                                                                          *
  262.  *  FUNCTION   : HandleSelectionState(LPDRAWITEMSTRUCT, int)                *
  263.  *                                                                          *
  264.  *  PURPOSE    : Handles a change in an item selection state. If an item is *
  265.  *               selected, a black rectangular frame is drawn around that   *
  266.  *               item; if an item is de-selected, the frame is removed.     *
  267.  *                                                                          *
  268.  *  COMMENT    : The black selection frame is slightly larger than the gray *
  269.  *               focus frame so they won't paint over each other.           *
  270.  *                                                                          *
  271.  ****************************************************************************/
  272. VOID APIENTRY HandleSelectionState(
  273.         LPDRAWITEMSTRUCT        lpdis,
  274.         INT                     inflate)
  275. {
  276.         RECT    rc;
  277.         HBRUSH  hbr;
  278.  
  279.         /* Resize rectangle to place selection frame outside of the focus
  280.          * frame and the item.
  281.          */
  282.         CopyRect ((LPRECT)&rc, (LPRECT)&lpdis->rcItem);
  283.         InflateRect ((LPRECT)&rc, inflate, inflate);
  284.  
  285.         if (lpdis->itemState & ODS_SELECTED)
  286.         {
  287.                 /* selecting item -- paint a black frame */
  288.                 hbr = GetStockObject(BLACK_BRUSH);
  289.         }
  290.         else
  291.         {
  292.                 /* de-selecting item -- remove frame */
  293.                 hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  294.         }
  295.         FrameRect(lpdis->hDC, (LPRECT)&rc, hbr);
  296.         DeleteObject (hbr);
  297. }
  298.  
  299. /****************************************************************************
  300.  *                                                                          *
  301.  *  FUNCTION   : HandleFocusState(LPDRAWITEMSTRUCT, int)                    *
  302.  *                                                                          *
  303.  *  PURPOSE    : Handle a change in item focus state. If an item gains the  *
  304.  *               input focus, a gray rectangular frame is drawn around that *
  305.  *               item; if an item loses the input focus, the gray frame is  *
  306.  *               removed.                                                   *
  307.  *                                                                          *
  308.  *  COMMENT    : The gray focus frame is slightly smaller than the black    *
  309.  *               selection frame so they won't paint over each other.       *
  310.  *                                                                          *
  311.  ****************************************************************************/
  312. VOID APIENTRY HandleFocusState(
  313.         LPDRAWITEMSTRUCT        lpdis,
  314.         INT                     inflate)
  315. {
  316.         RECT    rc;
  317.         HBRUSH  hbr;
  318.  
  319.         /* Resize rectangle to place focus frame between the selection
  320.          * frame and the item.
  321.          */
  322.         CopyRect ((LPRECT)&rc, (LPRECT)&lpdis->rcItem);
  323.         InflateRect ((LPRECT)&rc, inflate, inflate);
  324.  
  325.         if (lpdis->itemState & ODS_FOCUS)
  326.         {
  327.                 /* gaining input focus -- paint a gray frame */
  328.                 hbr = GetStockObject(GRAY_BRUSH);
  329.         }
  330.         else
  331.         {
  332.                 /* losing input focus -- remove (paint over) frame */
  333.                 hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  334.         }
  335.         FrameRect(lpdis->hDC, (LPRECT)&rc, hbr);
  336.         DeleteObject (hbr);
  337. }
  338.  
  339. /****************************************************************************
  340.  *                                                                          *
  341.  *  FUNCTION   : DrawEntireItem(LPDRAWITEMSTRUCT, int)                      *
  342.  *                                                                          *
  343.  *  PURPOSE    : Draws an item and frames it with a selection frame and/or  *
  344.  *               a focus frame when appropriate.                            *
  345.  *                                                                          *
  346.  ****************************************************************************/
  347. VOID APIENTRY DrawEntireItem(
  348.         LPDRAWITEMSTRUCT        lpdis,
  349.         INT                     inflate)
  350. {
  351.         RECT    rc;
  352.         HBRUSH  hbr;
  353.  
  354.         /* Resize rectangle to leave space for frames */
  355.         CopyRect ((LPRECT)&rc, (LPRECT)&lpdis->rcItem);
  356.         InflateRect ((LPRECT)&rc, inflate, inflate);
  357.  
  358.         /* Create a brush using the value in the item data field (this value
  359.          * was initialized when we added the item to the list/combo box using
  360.          * LB_ADDSTRING/CB_ADDSTRING) and draw the color in the list/combo box.
  361.          */
  362.         hbr = CreateSolidBrush (lpdis->itemData);
  363.         FillRect (lpdis->hDC, (LPRECT)&rc, hbr);
  364.         DeleteObject (hbr);
  365.  
  366.         /* Draw or erase appropriate frames */
  367.         HandleSelectionState(lpdis, inflate + 4);
  368.         HandleFocusState(lpdis, inflate + 2);
  369. }
  370.  
  371. /****************************************************************************
  372.  *                                                                          *
  373.  *  FUNCTION   : ListBoxExample (hDlg, message, wParam, lParam)             *
  374.  *                                                                          *
  375.  *  PURPOSE    : Dialog function for the owner-draw list box example.       *
  376.  *               It sets up the example dialog with the owner-draw list box,*
  377.  *               adds the colors to the list box, and handles setting the   *
  378.  *               selection and focus for the items.                         *
  379.  *                                                                          *
  380.  ****************************************************************************/
  381. BOOL APIENTRY ListBoxExample (
  382.     HWND hDlg,
  383.     UINT message,
  384.     UINT wParam,
  385.     LONG lParam)
  386. {
  387.     LPDRAWITEMSTRUCT    lpdis;
  388.     LPMEASUREITEMSTRUCT lpmis;
  389.  
  390.     /* Vars for WM_DRAWITEM */
  391.  
  392.     switch (message){
  393.         case WM_COMMAND:
  394.             switch (LOWORD(wParam)){
  395.                 case IDOK:
  396.                    EndDialog (hDlg, 0);
  397.                    return (TRUE);
  398.                    break;
  399.  
  400.                 /* Clicking any of these buttons adds the corresponding color
  401.                  * to the list box. The application-supplied data is the RGB
  402.                  * value for the color to be drawn in the listbox.
  403.                  */
  404.                 case ID_BLACK:
  405.                     SendMessage (GetDlgItem (hDlg, ID_LISTBOX),
  406.                                  LB_ADDSTRING,
  407.                                  0,
  408.                                  RGB (0,0,0));
  409.                     return(TRUE);
  410.                     break;
  411.                 case ID_RED:
  412.                     SendMessage (GetDlgItem (hDlg, ID_LISTBOX),
  413.                                  LB_ADDSTRING,
  414.                                  0,
  415.                                  RGB (255,0,0));
  416.                     return(TRUE);
  417.                     break;
  418.  
  419.                 case ID_BLUE:
  420.                     SendMessage (GetDlgItem (hDlg, ID_LISTBOX),
  421.                                  LB_ADDSTRING,
  422.                                  0,
  423.                                  RGB (0,0,255));
  424.                     return(TRUE);
  425.                     break;
  426.  
  427.                 case ID_GREEN:
  428.                     SendMessage (GetDlgItem (hDlg, ID_LISTBOX),
  429.                                  LB_ADDSTRING,
  430.                                  0,
  431.                                  RGB (0,255,0));
  432.                     return(TRUE);
  433.                     break;
  434.  
  435.                 default:
  436.                     return(FALSE);
  437.                     break;
  438.             }
  439.  
  440.         case WM_DRAWITEM:
  441.             /* Get pointer to the DRAWITEMSTRUCT */
  442.             lpdis = (LPDRAWITEMSTRUCT)lParam;
  443.  
  444.             if (lpdis->itemID == -1)
  445.             {
  446.                 /* We have a request to draw an item in the list box, yet there
  447.                  * are no list box items. This is sent when the user TABS into
  448.                  * an empty list box or an empty list box gets the focus. We
  449.                  * have to indicate (somehow) that this owner-draw list box has
  450.                  * the focus. We do it in response to this message. Note that
  451.                  * lpdis->itemData field would be invalid in this instance so
  452.                  * we can't allow it to fall into our standard routines.
  453.                  */
  454.                 HandleFocusState(lpdis, -5);
  455.             }
  456.             else
  457.             {
  458.                 switch (lpdis->itemAction)
  459.                 {
  460.                         case ODA_DRAWENTIRE:
  461.                                 DrawEntireItem(lpdis, -7);
  462.                                 break;
  463.  
  464.                         case ODA_SELECT:
  465.                                 HandleSelectionState(lpdis, -3);
  466.                                 break;
  467.  
  468.                         case ODA_FOCUS:
  469.                                 HandleFocusState(lpdis, -5);
  470.                                 break;
  471.                 }
  472.             }
  473.  
  474.             /* Return TRUE meaning that we processed this message. */
  475.             return(TRUE);
  476.             break;
  477.  
  478.         case WM_MEASUREITEM:
  479.             lpmis = (LPMEASUREITEMSTRUCT)lParam;
  480.  
  481.             /* All the items are the same height since the list box style is
  482.              * LBS_OWNERDRAWFIXED
  483.              */
  484.             lpmis->itemHeight = 30;
  485.             break;
  486.  
  487.         case WM_CLOSE:
  488.             EndDialog(hDlg, 0);
  489.             return(TRUE);
  490.             break;
  491.  
  492.         default:
  493.             return(FALSE);
  494.     }
  495.  
  496.     return(TRUE);
  497. }
  498.  
  499. /****************************************************************************
  500.  *                                                                          *
  501.  *  FUNCTION   : ComboBoxExample(hWnd, message, wParam, lParam)             *
  502.  *                                                                          *
  503.  *  PURPOSE    : Dialog function for the text combo dialog. The push buttons*
  504.  *               send various messages to the combo box and the edit control*
  505.  *               when selected. They allow the user to vary data sent with  *
  506.  *               each message.                                              *
  507.  *                                                                          *
  508.  ****************************************************************************/
  509. BOOL APIENTRY ComboBoxExample(
  510.     HWND hDlg,
  511.     UINT message,
  512.     UINT wParam,
  513.     LONG lParam)
  514. {
  515.  
  516.     HWND hWndCombo;                  /* Handle to the combo box control */
  517.                                      /* in the dialog box window        */
  518.     HWND hWndCheckBox;               /* Handle to the Auto Check Box    */
  519.     CHAR strSingleEditLine[255];     /* Single line edit control input  */
  520.     INT  wIndex, wCount;
  521.  
  522.     /* Get handles to the Combo box and the Check box */
  523.     hWndCombo     = GetDlgItem(hDlg, ID_COMBOBOX);
  524.     hWndCheckBox  = GetDlgItem(hDlg, ID_STEPSBOX);
  525.  
  526.     switch (message){
  527.         case WM_COMMAND:
  528.             switch (LOWORD(wParam)){
  529.                 case IDOK:
  530.                     EndDialog (hDlg,0);
  531.                     return(TRUE);
  532.  
  533.                 case ID_UNSLBUTTON:
  534.                     /* Selecting this button unselects any selection in the
  535.                      * combo box.
  536.                      */
  537.                     SetDlgItemText (hDlg, ID_TEXT1, "");
  538.                     SetDlgItemText (hDlg, ID_TEXT2, "");
  539.                     wIndex = (WORD) SendMessage( hWndCombo, CB_GETCURSEL, 0, 0L);
  540.                     if (wIndex == CB_ERR)
  541.                         MessageBox (hDlg, (LPSTR)"No Selection", NULL, MB_OK);
  542.                     else
  543.                         SendMessage (hWndCombo, CB_SETCURSEL, (WPARAM)-1, 0L);
  544.                     SetFocus (GetDlgItem (hDlg, ID_SINGLEEDIT));
  545.                     break;
  546.  
  547.                 case ID_NUMSELBUTTON:
  548.                     /* An integer value is taken from the edit control and an
  549.                      * attempt is made to select a combo box entry having this
  550.                      * index.
  551.                      */
  552.                     SetDlgItemText (hDlg, ID_TEXT1, "");
  553.                     SetDlgItemText (hDlg, ID_TEXT2, "");
  554.                     wCount = (WORD) SendMessage (hWndCombo, CB_GETCOUNT, 0, 0L);
  555.                     wIndex = (INT) GetDlgItemInt (hDlg, ID_SINGLEEDIT, NULL, TRUE);
  556.                     if (wIndex >= wCount)
  557.                         MessageBox (hDlg, (LPSTR)"Bad Selection", NULL, MB_OK);
  558.                     else
  559.                         SendMessage(hWndCombo, CB_SETCURSEL, wIndex, 0L);
  560.                     SetFocus (GetDlgItem (hDlg, ID_SINGLEEDIT));
  561.                     break;
  562.  
  563.                 case ID_TXTSELBUTTON:
  564.                     /* A text string is taken from the edit control and an
  565.                      * attempt is made to select a combo box entry having the
  566.                      * string as a prefix.
  567.                      */
  568.                     SetDlgItemText (hDlg, ID_TEXT1, "");
  569.                     SetDlgItemText (hDlg, ID_TEXT2, "");
  570.                     GetDlgItemText (hDlg, ID_SINGLEEDIT,
  571.                                  (LPSTR)strSingleEditLine, 255);
  572.                     wIndex = (WORD) SendMessage (hWndCombo,
  573.                                                 CB_SELECTSTRING,
  574.                                                 (WPARAM)-1,
  575.                                                 (LONG)(LPSTR)strSingleEditLine);
  576.                     if (wIndex == CB_ERR)
  577.                       MessageBox (hDlg, (LPSTR)"Bad Selection", NULL, MB_OK);
  578.                     SetFocus (GetDlgItem (hDlg, ID_SINGLEEDIT));
  579.                     break;
  580.  
  581.                 case ID_FNDSELBUTTON:
  582.                     /* Searches for the text specified in the list of combo
  583.                      * entries and returns the index (in combo box) of the
  584.                      * first match. The index is displayed in the "Text1"
  585.                      * field of the dialog.
  586.                      */
  587.                     SetDlgItemText (hDlg, ID_TEXT1, "");
  588.                     SetDlgItemText (hDlg, ID_TEXT2, "");
  589.                     GetDlgItemText (hDlg,
  590.                                     ID_SINGLEEDIT,
  591.                                     (LPSTR)strSingleEditLine,
  592.                                     255);
  593.                     wIndex = (WORD)SendMessage (hWndCombo,
  594.                                                CB_FINDSTRING,(WPARAM)-1,
  595.                                                (LONG)(LPSTR)strSingleEditLine);
  596.                     if (wIndex == CB_ERR)
  597.                         MessageBox (hDlg, (LPSTR)"Bad Selection", NULL, MB_OK);
  598.                     else
  599.                         SetDlgItemInt (hDlg, ID_TEXT1, wIndex, FALSE);
  600.                     SetFocus (GetDlgItem (hDlg, ID_SINGLEEDIT));
  601.                     break;
  602.  
  603.                 case ID_CLRBUTTON:
  604.                     /* Clears the combo box of all it's entries */
  605.                     SetDlgItemText (hDlg, ID_TEXT1, "");
  606.                     SetDlgItemText (hDlg, ID_TEXT2, "");
  607.                     wCount = (WORD) SendMessage (hWndCombo, CB_GETCOUNT, 0, 0L);
  608.                     if (!wCount)
  609.                         MessageBox (hDlg, (LPSTR)"Already clear", NULL, MB_OK);
  610.                     else{
  611.                         SetDlgItemInt (hDlg, ID_TEXT1, wCount, TRUE);
  612.                         SetDlgItemText (hDlg, ID_TEXT2, "Items cleared");
  613.                         SendMessage (hWndCombo,CB_RESETCONTENT, 0, 0L);
  614.                     }
  615.                     SetFocus (GetDlgItem (hDlg,ID_SINGLEEDIT));
  616.                     break;
  617.  
  618.                 case ID_ADDBUTTON:
  619.                     /* Takes the string specified in the edit control and
  620.                      * adds it to the combo box.
  621.                      */
  622.                     SetDlgItemText (hDlg, ID_TEXT1, "");
  623.                     SetDlgItemText (hDlg, ID_TEXT2, "");
  624.                     GetDlgItemText (hDlg, ID_SINGLEEDIT, strSingleEditLine, 255);
  625.                     SendMessage (hWndCombo,
  626.                                  CB_ADDSTRING,
  627.                                  0,
  628.                                  (LONG)(LPSTR) strSingleEditLine);
  629.                     SetFocus (GetDlgItem (hDlg, ID_SINGLEEDIT));
  630.                     break;
  631.  
  632.                 case ID_DELETEBUTTON:
  633.                     /* Delete the currently selected item from the combo box. */
  634.                     SetDlgItemText (hDlg, ID_TEXT1, "");
  635.                     SetDlgItemText (hDlg, ID_TEXT2, "");
  636.                     wIndex = (WORD) SendMessage (hWndCombo, CB_GETCURSEL, 0, 0L);
  637.                     if (SendMessage (hWndCombo, CB_DELETESTRING, wIndex, 0L) == CB_ERR)
  638.                         MessageBox (hDlg, (LPSTR)"No Selection", NULL, MB_OK);
  639.                     else{
  640.                         SetDlgItemText (hDlg, ID_TEXT1, "deleted index #");
  641.                         SetDlgItemInt  (hDlg, ID_TEXT2, wIndex, TRUE);
  642.                     }
  643.                     SetFocus (GetDlgItem (hDlg, ID_SINGLEEDIT));
  644.                     break;
  645.  
  646.                 case ID_CBDIRBUTTON:
  647.                     /* Appends a directory listing of the current directory
  648.                      * to the combo box entries.
  649.                      */
  650.                     SetDlgItemText (hDlg, ID_TEXT1, "");
  651.                     SetDlgItemText (hDlg, ID_TEXT2, "");
  652.                     wIndex = (WORD)SendMessage (hWndCombo,
  653.                                                CB_DIR,
  654.                                                0x10|0x4000,
  655.                                                (LONG)(LPSTR)"*.*");
  656.                     SetFocus (GetDlgItem (hDlg, ID_SINGLEEDIT));
  657.                     break;
  658.  
  659.  
  660.                 case ID_CPYBUTTON:
  661.                     /* Copies the currently selected item in the combo box to
  662.                      * the edit control.
  663.                      */
  664.                     SetDlgItemText (hDlg, ID_TEXT1, "");
  665.                     SetDlgItemText (hDlg, ID_TEXT2, "");
  666.                     wIndex = (WORD) SendMessage (hWndCombo, CB_GETCURSEL, 0, 0L);
  667.                     if (wIndex == CB_ERR)
  668.                         MessageBox(hDlg, (LPSTR)"No Selection", NULL, MB_OK);
  669.                     else{
  670.                         wCount = SendMessage (hWndCombo, CB_GETLBTEXTLEN, wIndex, 0L);
  671.                         SendMessage (hWndCombo,
  672.                                      CB_GETLBTEXT,
  673.                                      wIndex,
  674.                                      (LONG)(LPSTR)strSingleEditLine);
  675.                         SetDlgItemText(hDlg, ID_SINGLEEDIT,
  676.                                        (LPSTR)strSingleEditLine);
  677.                         SetDlgItemText(hDlg, ID_TEXT1, "copied index #");
  678.                         SetDlgItemInt(hDlg, ID_TEXT2, wIndex, TRUE);
  679.                     }
  680.                     SetFocus (GetDlgItem (hDlg, ID_SINGLEEDIT));
  681.                     break;
  682.  
  683.                 /* When the combo notification box is checked, a message box
  684.                  * is flashed showing what notification codes the combo box is
  685.                  * returning to the app. in response to the messages sent by
  686.                  * the buttons.
  687.                  */
  688.                 case ID_COMBOBOX:
  689.                     if (SendMessage (hWndCheckBox, BM_GETCHECK, 0, 0L)){
  690.                         switch (HIWORD(lParam)){
  691.                             case (WORD)CBN_ERRSPACE:
  692.                               MessageBox (hDlg, (LPSTR)"CB Out of Space",
  693.                                          "CB MSG", MB_OK);
  694.                               break;
  695.  
  696.                             case CBN_SELCHANGE:
  697.                               MessageBox (hDlg, (LPSTR)"CB Sel Change",
  698.                                          "CB MSG", MB_OK);
  699.                               break;
  700.  
  701.                             case CBN_DBLCLK:
  702.                               MessageBox(hDlg, (LPSTR)"CB Double Click",
  703.                                          "CB MSG", MB_OK);
  704.                               break;
  705.  
  706.                             case CBN_SETFOCUS:
  707.                               SetDlgItemText(hDlg, ID_TEXT1, "CB SetFocus");
  708.                               break;
  709.  
  710.                             case CBN_KILLFOCUS:
  711.                               SetDlgItemText(hDlg, ID_TEXT1, "CB KillFocus");
  712.                               break;
  713.                         }
  714.                     }
  715.                     break;
  716.  
  717.                 default:
  718.                     return(FALSE);
  719.             }
  720.             break;
  721.  
  722.         case WM_CLOSE:
  723.             EndDialog(hDlg, 0);
  724.             return(TRUE);
  725.             break;
  726.  
  727.         default:
  728.             return(FALSE);
  729.     }
  730.     return(TRUE);
  731. }
  732.  
  733.  
  734. /****************************************************************************
  735.  *                                                                          *
  736.  *  FUNCTION   : OwnerComboBoxExample(hWnd, message, wParam, lParam)        *
  737.  *                                                                          *
  738.  *  PURPOSE    : Dialog function for the dropdown list combo box with       *
  739.  *               owner-draw.                                                *
  740.  *                                                                          *
  741.  ****************************************************************************/
  742. BOOL APIENTRY OwnerComboBoxExample (
  743.     HWND hDlg,
  744.     UINT message,
  745.     UINT wParam,
  746.     LONG lParam)
  747. {
  748.     LPDRAWITEMSTRUCT    lpdis;
  749.     LPMEASUREITEMSTRUCT lpmis;
  750.  
  751.     switch (message){
  752.         case WM_COMMAND:
  753.             switch (LOWORD(wParam)){
  754.                 case IDOK:
  755.                    EndDialog (hDlg, 0);
  756.                    return(TRUE);
  757.                    break;
  758.  
  759.                 /* Clicking any of these buttons adds the corresponding color
  760.                  * to the combo box. The application-supplied data is the RGB
  761.                  * value for the color to be drawn in the listbox.
  762.                  */
  763.                 case ID_BLACK:
  764.                    SendMessage (GetDlgItem(hDlg, ID_LISTBOX),
  765.                                 CB_ADDSTRING,
  766.                                 0,
  767.                                 RGB (0,0,0));
  768.                    return(TRUE);
  769.                    break;
  770.  
  771.                 case ID_RED:
  772.                    SendMessage (GetDlgItem (hDlg, ID_LISTBOX),
  773.                                 CB_ADDSTRING,
  774.                                 0,
  775.                                 RGB (255,0,0));
  776.                    return(TRUE);
  777.                    break;
  778.  
  779.                 case ID_BLUE:
  780.                    SendMessage (GetDlgItem(hDlg, ID_LISTBOX),
  781.                                 CB_ADDSTRING,
  782.                                 0,
  783.                                 RGB (0,0,255));
  784.                    return(TRUE);
  785.                    break;
  786.  
  787.                 case ID_GREEN:
  788.                    SendMessage (GetDlgItem(hDlg, ID_LISTBOX),
  789.                                 CB_ADDSTRING,
  790.                                 0,
  791.                                 RGB (0,255,0));
  792.                    return(TRUE);
  793.                    break;
  794.  
  795.                 default:
  796.                    return(TRUE);
  797.                    break;
  798.             }
  799.  
  800.         case WM_DRAWITEM:
  801.             /* Get pointer to the DRAWITEMSTRUCT */
  802.             lpdis = (LPDRAWITEMSTRUCT)lParam;
  803.  
  804.             if (lpdis->itemID == -1){
  805.                 /* We have a request to draw an item in the combo box, yet there
  806.                  * are no combo box items. This is sent when the user TABS into
  807.                  * an empty combo box or an empty combo box gets the focus. We
  808.                  * have to indicate (somehow) that this owner-draw combo box has
  809.                  * the focus. We do it in response to this message. Note that
  810.                  * lpdis->itemData field would be invalid in this instance so
  811.                  * we can't allow it to fall into our standard routines.
  812.                  */
  813.                 HandleFocusState(lpdis, -2);
  814.             }
  815.             else
  816.             {
  817.                 switch (lpdis->itemAction)
  818.                 {
  819.                         case ODA_DRAWENTIRE:
  820.                                 DrawEntireItem(lpdis, -4);
  821.                                 break;
  822.  
  823.                         case ODA_SELECT:
  824.                                 HandleSelectionState(lpdis, 0);
  825.                                 break;
  826.  
  827.                         case ODA_FOCUS:
  828.                                 HandleFocusState(lpdis, -2);
  829.                                 break;
  830.                 }
  831.             }
  832.  
  833.             /* Return TRUE meaning that we processed this message. */
  834.             return(TRUE);
  835.             break;
  836.  
  837.         case WM_MEASUREITEM:
  838.             lpmis = (LPMEASUREITEMSTRUCT)lParam;
  839.  
  840.             /* All the items are the same height since the combo box is
  841.              * CBS_OWNERDRAWFIXED
  842.              */
  843.             if (lpmis->itemID == -1){
  844.                 /* If -1 for item, then we are setting the height of the
  845.                  * always visible static item part of the dropdown combo box.
  846.                  */
  847.                 lpmis->itemHeight = 25;
  848.                 return(TRUE);
  849.             }
  850.             lpmis->itemHeight = 30;
  851.             break;
  852.  
  853.         case WM_CLOSE:
  854.             EndDialog(hDlg, 0);
  855.             return(TRUE);
  856.             break;
  857.  
  858.         default:
  859.             return(FALSE);
  860.     }
  861.     return(TRUE);
  862. }
  863.