home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_03_04 / 3n04052a < prev    next >
Text File  |  1992-02-11  |  19KB  |  630 lines

  1. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=Begin Listing4-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2. /*****************************************************/
  3. /* listmenu.c                                        */
  4. /* -- Implements a popup menu with a scrollable      */
  5. /*    ListBox.                                       */
  6. /*****************************************************/
  7.  
  8. /*****************************************************/
  9. /* Header files.                                     */
  10. /*****************************************************/
  11. #include <windows.h>
  12. #include "listmenu.h"
  13.  
  14. /*****************************************************/
  15. /* Constants.                                        */
  16. /*****************************************************/
  17. #define imdsNil     -1  /* Undefined menu index. */
  18. #define cbMenuMax   256 /* Max. length of MenuItem. */
  19. #define szMenuClass "#32768"    /* Menu classname. */
  20. #define szListClass "ListBox"   /* LBox classname. */
  21. #define szFilter    "LFilter"   /* Filter classname. */
  22.  
  23. /*****************************************************/
  24. /* Types.                                            */
  25. /*****************************************************/
  26. typedef struct
  27.     {
  28.     int     cidm;           /* # items in menu. */
  29.     int     dx, dy;         /* Size of menu. */
  30.     int     idm;            /* Index in MenuBar. */
  31.     HMENU   hmnu;           /* Original popup menu. */
  32.     HWND    hwnd;           /* ListBox window. */
  33.     WORD    rgidm[1];       /* MenuItem id array */
  34.     } MDS;                  /* Menu DeScriptor. */
  35. typedef MDS FAR *   LPMDS;
  36. typedef HANDLE      HMDS;
  37. typedef HMDS FAR *  LRGHMDS;
  38.  
  39. /*****************************************************/
  40. /* Globals.                                          */
  41. /*****************************************************/
  42.  
  43. HANDLE  hrghmds;        /* Handle to array of menus. */
  44. int     cmds;           /* Number of menus. */
  45. int     imdsDown;       /* Dropped popup menu. */
  46. HWND    hwndMenu;       /* Popup menu window. */
  47. HWND    hwndMain;       /* App's main window. */
  48. HMENU   hmnuTop;        /* App's MenuBar. */
  49. FARPROC lpfnMenuFilter; /* Popup menu subclasser. */
  50. FARPROC lpfnMenu;       /* Popup menu window proc. */
  51. FARPROC lpfnMain;       /* App's main window proc. */
  52. FARPROC lpfnMainFilter; /* Subclasser for above. */
  53. FARPROC lpfnListFilter; /* Subclasser for ListBox. */
  54. FARPROC lpfnList;
  55. BOOL    fButtonDown;    /* Buttoned down in list? */
  56.  
  57. /*****************************************************/
  58. /* Private Prototypes.                               */
  59. /*****************************************************/
  60. void                CloseListMenu(void);
  61. void                DestroyMenuImds(int);
  62. BOOL FAR  PASCAL    FEnumWnd(HWND, LONG);
  63. void                GetMdsImds(MDS *, int);
  64. WORD                IdmFromIidmImds(int, int);
  65. int                 ImdsFromIdm(WORD);
  66. LONG FAR  PASCAL    ListFilter(HWND, WORD, WORD, LONG);
  67. LONG FAR  PASCAL    MainFilter(HWND, WORD, WORD, LONG);
  68. LONG FAR  PASCAL    MenuFilter(HWND, WORD, WORD, LONG);
  69. void                RemoveListMenu(BOOL);
  70.  
  71. /*****************************************************/
  72. /* Routines.                                         */
  73. /*****************************************************/
  74.  
  75. BOOL
  76. FInitListMenu(BOOL fFirst, HWND hwnd)
  77. /*****************************************************/
  78. /* -- Initialize the list menu module.               */
  79. /* -- hwnd       : Window containing MenuBar.        */
  80. /* -- szMenuList : Name of menu list of popups.      */
  81. /*****************************************************/
  82.     {
  83.     FARPROC     lpfn;   /* EnumWindows() callback. */
  84.     HANDLE      hins;   /* App's instance. */
  85.     WNDCLASS    wcs;    /* Our own ListBox class. */
  86.  
  87.     hwndMain = hwnd;
  88.     if ((hmnuTop = GetMenu(hwnd)) == NULL)
  89.         return FALSE;
  90.  
  91.     /* Get the popup menu handle so we can subclass */
  92.     /* it at will. */
  93.     hins = GetWindowWord(hwnd, GWW_HINSTANCE);
  94.     if ((lpfn = MakeProcInstance(FEnumWnd, hins)) ==
  95.       NULL)
  96.         return FALSE;
  97.  
  98.     EnumWindows(lpfn, 0L);
  99.     FreeProcInstance(lpfn);
  100.     if (hwndMenu == NULL)
  101.         return FALSE;
  102.  
  103.     lpfnMenu =
  104.       (FARPROC)GetWindowLong(hwndMenu, GWL_WNDPROC);
  105.     if ((lpfnMenuFilter = MakeProcInstance(
  106.       (FARPROC)MenuFilter, hins)) == NULL)
  107.         return FALSE;
  108.  
  109.     /* Subclass the app's main window. */
  110.     lpfnMain =
  111.       (FARPROC)GetWindowLong(hwndMain, GWL_WNDPROC);
  112.     if ((lpfnMainFilter = MakeProcInstance(
  113.       (FARPROC)MainFilter, hins)) == NULL)
  114.         return FALSE;
  115.     SetWindowLong(hwndMain, GWL_WNDPROC,
  116.       (LONG)lpfnMainFilter);
  117.  
  118.     /* Create a our version of the ListBox class. */
  119.     if (!GetClassInfo(NULL, szListClass, &wcs))
  120.         return FALSE;
  121.     lpfnList = (FARPROC)wcs.lpfnWndProc;
  122.  
  123.     if (fFirst)
  124.         {
  125.         wcs.lpfnWndProc = ListFilter;
  126.         wcs.hInstance = hins;
  127.         wcs.lpszClassName = szFilter;
  128.         if (!RegisterClass(&wcs))
  129.             return FALSE;
  130.         }
  131.  
  132.     imdsDown = imdsNil;
  133.     return TRUE;
  134.     }
  135.  
  136. BOOL FAR PASCAL
  137. FEnumWnd(HWND hwnd, LONG lwp)
  138. /*****************************************************/
  139. /* -- EnumWindows() callback to get popup menu       */
  140. /*    window handle.                                 */
  141. /*****************************************************/
  142.     {
  143.     char    szBuf[40];
  144.  
  145.     GetClassName(hwnd, szBuf, sizeof szBuf);
  146.     if (!lstrcmp(szBuf, szMenuClass))
  147.         {
  148.         hwndMenu = hwnd;
  149.         return FALSE;
  150.         }
  151.     return TRUE;
  152.     }
  153.  
  154. void
  155. CloseListMenu(void)
  156. /*****************************************************/
  157. /* -- Close the list menu module.                    */
  158. /*****************************************************/
  159.     {
  160.     int     imds;
  161.  
  162.     if (cmds == 0)
  163.         return; /* Nothing to do. */
  164.  
  165.     /* Destroy all list menus. */
  166.     for (imds = 0; imds < cmds; imds++)
  167.         DestroyMenuImds(imds);
  168.  
  169.     /* Remove filters. */
  170.     if (lpfnMenu != NULL)
  171.         {
  172.         if (IsWindow(hwndMenu))
  173.             SetWindowLong(hwndMenu, GWL_WNDPROC,
  174.               (LONG)lpfnMenu);
  175.         lpfnMenu = NULL;
  176.         }
  177.     if (lpfnMenuFilter != NULL)
  178.         {
  179.         FreeProcInstance(lpfnMenuFilter);
  180.         lpfnMenuFilter = NULL;
  181.         }
  182.  
  183.     if (lpfnMain != NULL && IsWindow(hwndMain))
  184.         SetWindowLong(hwndMain, GWL_WNDPROC,
  185.           (LONG)lpfnMain);
  186.     if (lpfnMainFilter != NULL)
  187.         {
  188.         FreeProcInstance(lpfnMainFilter);
  189.         lpfnMainFilter = NULL;
  190.         }
  191.  
  192.     /* Restore state and free menu table array. */
  193.     hmnuTop = NULL;
  194.     hwndMenu = hwndMain = NULL;
  195.     GlobalFree(hrghmds);
  196.     hrghmds = NULL;
  197.     cmds = 0;
  198.     }
  199.  
  200. BOOL
  201. FAssignMenu(WORD idm, int dy)
  202. /*****************************************************/
  203. /* -- Assign a list menu to the given MenuItem.      */
  204. /* -- The strings and command values for the list    */
  205. /*    menu are extracted from the given popup menu.  */
  206. /* -- Return TRUE for success, FALSE for failure.    */
  207. /* -- idm       : MenuItem id.                       */
  208. /* -- dy        : Height of the menu.                */
  209. /*****************************************************/
  210.     {
  211.     int     imds;
  212.     HMENU   hmnu;
  213.     HMDS    hmds    = NULL;
  214.     LPMDS   lpmds   = NULL;
  215.     HDC     hdc     = NULL;
  216.     int     iidm, cidm;
  217.     BOOL    fVal    = FALSE;
  218.     HANDLE  hins;
  219.  
  220.     /* See if a list menu for this popup already */
  221.     /* exists.  If not, grow (or allocate if for the */
  222.     /* first time) the list menu table array.  If */
  223.     /* a list menu already exists, destroy it, but */
  224.     /* reuse its slot in the array. */
  225.     if ((imds = ImdsFromIdm(idm)) == imdsNil)
  226.         {
  227.         /* Grow menu array. */
  228.         if (cmds == 0)
  229.             {
  230.             if ((hrghmds = GlobalAlloc(
  231.               GMEM_MOVEABLE | GMEM_ZEROINIT,
  232.               sizeof(HMDS))) == NULL)
  233.                 goto FAssignMenuError;
  234.  
  235.             cmds = 1;
  236.             imds = 0;
  237.             }
  238.         else
  239.             {
  240.             HANDLE  hrghmdsNew;
  241.  
  242.             imds = cmds++;
  243.             if ((hrghmdsNew = GlobalReAlloc(hrghmds, 
  244.                 cmds * sizeof(HMDS),
  245.                 GMEM_MOVEABLE | GMEM_ZEROINIT))
  246.               == NULL)
  247.                 goto FAssignMenuError;
  248.  
  249.             hrghmds = hrghmdsNew;
  250.             }
  251.         }
  252.     else
  253.         {
  254.         DestroyMenuImds(imds);
  255.         }
  256.  
  257.     /* Create a new menu.  Clone a ListBox with the */
  258.     /* same MenuItems. */
  259.     hins = GetWindowWord(hwndMain, GWW_HINSTANCE);
  260.     if ((hmnu = GetSubMenu(hmnuTop, idm)) == NULL)
  261.         goto FAssignMenuError;
  262.  
  263.     if ((cidm = GetMenuItemCount(hmnu)) < 0)
  264.         goto FAssignMenuError;
  265.  
  266.     if ((hmds = GlobalAlloc(GMEM_MOVEABLE,
  267.         sizeof(MDS) + (cidm - 1) * sizeof(WORD))) ==
  268.       NULL)
  269.         goto FAssignMenuError;
  270.  
  271.     lpmds = (LPMDS)GlobalLock(hmds);
  272.     lpmds->cidm = cidm;
  273.     lpmds->hmnu = hmnu;
  274.     lpmds->idm = idm;
  275.     if ((lpmds->hwnd = CreateWindow(szFilter, NULL,
  276.       WS_CHILD | WS_BORDER | WS_VSCROLL | WS_VISIBLE,
  277.       0, 0, 0, 0, hwndMain, idm, hins, NULL)) == NULL)
  278.         goto FAssignMenuError;
  279.  
  280.     /* Fill the ListBox with MenuItems.  Get width */
  281.     /* of widest item. */
  282.     lpmds->dx = -1;
  283.     if ((hdc = GetDC(lpmds->hwnd)) == NULL)
  284.         goto FAssignMenuError;
  285.  
  286.     for (iidm = 0; iidm < cidm; iidm++)
  287.         {
  288.         char    sz[cbMenuMax];
  289.         int     dx;
  290.  
  291.         if ((lpmds->rgidm[iidm] =
  292.           GetMenuItemID(hmnu, iidm)) == -1)
  293.             goto FAssignMenuError;
  294.  
  295.         if (GetMenuString(hmnu, iidm, sz, sizeof sz,
  296.           MF_BYPOSITION) <= 0)
  297.             goto FAssignMenuError;
  298.         if (SendMessage(lpmds->hwnd, LB_ADDSTRING, 0,
  299.           (LONG)(LPSTR)sz) == LB_ERR)
  300.             goto FAssignMenuError;
  301.         dx = LOWORD(GetTextExtent(hdc, sz,
  302.           lstrlen(sz)));
  303.         if (dx > lpmds->dx)
  304.             lpmds->dx = dx;
  305.         }
  306.  
  307.     /* Allow for scroll bar and extra whitespace. */
  308.     lpmds->dx += 2 * GetSystemMetrics(SM_CXVSCROLL);
  309.     lpmds->dy = dy;
  310.     ((LRGHMDS)GlobalLock(hrghmds))[imds] = hmds;
  311.     GlobalUnlock(hrghmds);
  312.  
  313.     fVal = TRUE;
  314.     goto FAssignMenuExit;
  315.  
  316. FAssignMenuError:   /* Clean up in case of error. */
  317.     if (lpmds != NULL && lpmds->hwnd != NULL)
  318.         DestroyWindow(lpmds->hwnd);
  319.     if (hmds != NULL)
  320.         GlobalFree(hmds);
  321.  
  322. FAssignMenuExit:    /* Normal cleanup. */
  323.     if (hdc != NULL)
  324.         ReleaseDC(lpmds->hwnd, hdc);
  325.     if (lpmds != NULL)
  326.         GlobalUnlock(hmds);
  327.  
  328.     return fVal;
  329.     }
  330.  
  331. int
  332. ImdsFromIdm(WORD idm)
  333. /*****************************************************/
  334. /* -- Given a top-level MenuItem id, return the      */
  335. /*    associated list menu.                          */
  336. /* -- Return -1 if no such menu.                     */
  337. /*****************************************************/
  338.     {
  339.     int imds;
  340.     MDS mds;
  341.  
  342.     if (cmds == 0)
  343.         return imdsNil;
  344.  
  345.     for (imds = 0; imds < cmds; imds++)
  346.         {
  347.         GetMdsImds(&mds, imds);
  348.         if (mds.hwnd != NULL &&
  349.           GetWindowWord(mds.hwnd, GWW_ID) == idm)
  350.             break;
  351.         }
  352.  
  353.     return imds == cmds ? imdsNil : imds;
  354.     }
  355.  
  356. void
  357. DestroyMenuImds(int imds)
  358. /*****************************************************/
  359. /* -- Destroy the given list menu.                   */
  360. /* -- imds  : Index of menu.                         */
  361. /*****************************************************/
  362.     {
  363.     LRGHMDS lrghmds = (LRGHMDS)GlobalLock(hrghmds);
  364.     HMDS    hmds    = lrghmds[imds];
  365.     LPMDS   lpmds   = (LPMDS)GlobalLock(hmds);
  366.  
  367.     if (IsWindow(lpmds->hwnd))
  368.         DestroyWindow(lpmds->hwnd);
  369.  
  370.     GlobalUnlock(hmds);
  371.     GlobalFree(hmds);
  372.     lrghmds[imds] = NULL;
  373.     GlobalUnlock(hrghmds);
  374.     }
  375.  
  376. LONG FAR PASCAL
  377. MenuFilter(HWND hwnd, WORD wm, WORD wp, LONG lwp)
  378. /*****************************************************/
  379. /* -- Subclasser for menu popup window.              */
  380. /*****************************************************/
  381.     {
  382.     switch (wm)
  383.         {
  384.     default:
  385.         break;
  386.  
  387.     case WM_PAINT:
  388.         {
  389.         PAINTSTRUCT wps;
  390.         RECT        rect;
  391.         MDS         mds;
  392.  
  393.         /* Eat the paint message and remove the */
  394.         /* popup menu and subclasser. */
  395.         BeginPaint(hwnd, &wps);
  396.         EndPaint(hwnd, &wps);
  397.         ShowWindow(hwnd, SW_HIDE);
  398.         SetWindowLong(hwndMenu, GWL_WNDPROC,
  399.           (LONG)lpfnMenu);
  400.  
  401.         /* Position and display the list menu. */
  402.         GetMdsImds(&mds, imdsDown);
  403.         GetWindowRect(hwnd, &rect);
  404.         ScreenToClient(hwndMain, (LPPOINT)&rect);
  405.         MoveWindow(mds.hwnd,
  406.           rect.left, rect.top, mds.dx, mds.dy, TRUE);
  407.         SendMessage(mds.hwnd, LB_SETCURSEL, 0, 0L);
  408.         SetFocus(mds.hwnd);
  409.  
  410.         /* Get out of menu mode. */
  411.         PostMessage(hwnd, WM_KEYDOWN, VK_ESCAPE, 0L);
  412.         PostMessage(hwndMain, WM_KEYDOWN, VK_ESCAPE,
  413.           0L);
  414.  
  415.         /* But highlight the top-level MenuItem to */
  416.         /* look like we are still in it.  Have to do */
  417.         /* this after the menu manager has removed */
  418.         /* it, though!.  So post a message to */
  419.         /* ourself that will arrive after. */
  420.         PostMessage(hwndMain, WM_USER, 0, 0L);
  421.         }
  422.         return 0L;
  423.  
  424.     case WM_ERASEBKGND:
  425.         return 1L;  /* Eat this message too. */
  426.         }   /* End switch wm. */
  427.  
  428.     return CallWindowProc(lpfnMenu, hwnd, wm, wp, lwp);
  429.     }
  430.  
  431. LONG FAR PASCAL
  432. MainFilter(HWND hwnd, WORD wm, WORD wp, LONG lwp)
  433. /*****************************************************/
  434. /* -- Subclasser for app's main window.              */
  435. /*****************************************************/
  436.     {
  437.     switch (wm)
  438.         {
  439.     default:
  440.         break;
  441.  
  442.     case WM_INITMENUPOPUP:
  443.         /* Get rid of any list menu already visible. */
  444.         RemoveListMenu(FALSE);
  445.  
  446.         /* Install the menu filter to start the ball */
  447.         /* rolling. */
  448.         if (HIWORD(lwp) == 0 &&
  449.             (imdsDown = ImdsFromIdm(LOWORD(lwp))) !=
  450.           imdsNil)
  451.             SetWindowLong(hwndMenu, GWL_WNDPROC,
  452.               (LONG)lpfnMenuFilter);
  453.         break;
  454.  
  455.     case WM_COMMAND:
  456.         /* Eat notifications from the menu */
  457.         /* ListBoxes. */
  458.         if (ImdsFromIdm(wp) != imdsNil)
  459.             return 0L;
  460.  
  461.     case WM_ACTIVATE:
  462.     case WM_LBUTTONDOWN:
  463.     case WM_NCLBUTTONDOWN:
  464.         /* If the user button's down elsewhere in */
  465.         /* the app, or activates another app, remove */
  466.         /* any visisble list menu. */
  467.         RemoveListMenu(FALSE);
  468.         break;
  469.  
  470.     case WM_USER:
  471.         if (imdsDown != imdsNil)
  472.             {
  473.             MDS mds;
  474.  
  475.             GetMdsImds(&mds, imdsDown);
  476.             HiliteMenuItem(hwnd, hmnuTop, mds.idm,
  477.               MF_BYPOSITION | MF_HILITE);
  478.             }
  479.         break;
  480.  
  481.     case WM_DESTROY:
  482.         CloseListMenu();    /* Clean up. */
  483.         break;
  484.         }   /* End switch wm. */
  485.  
  486.     return CallWindowProc(lpfnMain, hwnd, wm, wp, lwp);
  487.     }
  488.  
  489. void
  490. RemoveListMenu(BOOL fCommand)
  491. /*****************************************************/
  492. /* -- If a list menu is visible, remove it.          */
  493. /* -- fCommand : Generate a menu-style WM_COMMAND    */
  494. /*               message if set.                     */
  495. /*****************************************************/
  496.     {
  497.     MDS mds;
  498.     int imdsSav;
  499.  
  500.     fButtonDown = FALSE;
  501.     if (imdsDown == imdsNil)
  502.         return;
  503.  
  504.     GetMdsImds(&mds, imdsDown);
  505.     HiliteMenuItem(hwndMain, hmnuTop, mds.idm,
  506.       MF_BYPOSITION | MF_UNHILITE);
  507.     imdsSav = imdsDown;
  508.     imdsDown = imdsNil;
  509.  
  510.     /* Remove focus first, so there isn't a ghost */
  511.     /* caret floating around until the parent */
  512.     /* windows gets a change to repaint itself. */
  513.     if (GetFocus() == mds.hwnd)
  514.         SetFocus(hwndMain);
  515.  
  516.     /* Hide the list menu. */
  517.     MoveWindow(mds.hwnd, 0, 0, 0, 0, TRUE);
  518.  
  519.     if (fCommand)   /* Notify the app. */
  520.         {
  521.         int     iidm;
  522.  
  523.         iidm = (int)SendMessage(mds.hwnd, LB_GETCURSEL,
  524.           0, 0L);
  525.         if (iidm != LB_ERR)
  526.             PostMessage(hwndMain, WM_COMMAND,
  527.               IdmFromIidmImds(iidm, imdsSav), 0L);
  528.         }
  529.     }
  530.  
  531. LONG FAR PASCAL
  532. ListFilter(HWND hwnd, WORD wm, WORD wp, LONG lwp)
  533. /*****************************************************/
  534. /* -- Subclasser for ListBox control.                */
  535. /*****************************************************/
  536.     {
  537.     switch (wm)
  538.         {
  539.     default:
  540.         break;
  541.  
  542.     case WM_LBUTTONDOWN:
  543.         fButtonDown = TRUE;
  544.         break;
  545.  
  546.     case WM_LBUTTONUP:
  547.         if (fButtonDown)
  548.             {
  549.             LONG    pt  = GetMessagePos();
  550.             RECT    rect;
  551.  
  552.             /* Do not generate a command if the user */
  553.             /* releases the mouse outside the bounds */
  554.             /* of the ListBox. */
  555.             GetClientRect(hwnd, &rect);
  556.             ScreenToClient(hwnd, (LPPOINT)&pt);
  557.             RemoveListMenu(
  558.               PtInRect(&rect, *(POINT *)&pt));
  559.             }
  560.         break;
  561.  
  562.     case WM_SIZE:
  563.         {
  564.         LONG    lVal;
  565.  
  566.         /* Windows will put a bogus horizontal */
  567.         /* scroll bar style in the window in */
  568.         /* response to this message!  So stomp it */
  569.         /* out. */
  570.         lVal =
  571.           CallWindowProc(lpfnList, hwnd, wm, wp, lwp);
  572.         SetWindowLong(hwnd, GWL_STYLE,
  573.           GetWindowLong(hwnd, GWL_STYLE) & ~WS_HSCROLL);
  574.         return lVal;
  575.         }
  576.  
  577.     case WM_KEYDOWN:
  578.         switch (wp)
  579.             {
  580.         default:
  581.             break;
  582.  
  583.         case VK_RETURN:
  584.             RemoveListMenu(TRUE);
  585.             return 0L;
  586.  
  587.         case VK_ESCAPE:
  588.             RemoveListMenu(FALSE);
  589.             return 0L;
  590.             }   /* End switch wp. */
  591.         break;  /* End case WM_KEYDOWN. */
  592.         }       /* End switch wm. */
  593.  
  594.     return CallWindowProc(lpfnList, hwnd, wm, wp, lwp);
  595.     }
  596.  
  597. void
  598. GetMdsImds(MDS * pmds, int imds)
  599. /*****************************************************/
  600. /* -- Given a list menu id, return its mds data.     */
  601. /* -- pmds : Fill this struct.                       */
  602. /* -- imds : Index of list menu in array.            */
  603. /*****************************************************/
  604.     {
  605.     LRGHMDS lrghmds = (LRGHMDS)GlobalLock(hrghmds);
  606.  
  607.     *pmds = *(LPMDS)GlobalLock(lrghmds[imds]);
  608.     GlobalUnlock(lrghmds[imds]);
  609.     GlobalUnlock(hrghmds);
  610.     }
  611.  
  612. WORD
  613. IdmFromIidmImds(int iidm, int imds)
  614. /*****************************************************/
  615. /* -- Return the requested MenuItem id.              */
  616. /* -- iidm : Index of MenuItem id in arrar of them.  */
  617. /* -- imds : Index of list menu in array of them.    */
  618. /*****************************************************/
  619.     {
  620.     LRGHMDS lrghmds = (LRGHMDS)GlobalLock(hrghmds);
  621.     WORD    idm;
  622.  
  623.     idm =
  624.       ((LPMDS)GlobalLock(lrghmds[imds]))->rgidm[iidm];
  625.     GlobalUnlock(lrghmds[imds]);
  626.     GlobalUnlock(hrghmds);
  627.     return idm;
  628.     }
  629. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=End Listing4-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  630.