home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / v / vlistbox.zip / VLIST.C < prev    next >
C/C++ Source or Header  |  1993-01-26  |  37KB  |  1,254 lines

  1. #include "vlistint.h"
  2. #include "string.h"
  3.  
  4. #define _LB_MOUSESCROLL         0x0118
  5.  
  6. BOOL WINAPI RegisterVListBox(HINSTANCE hInstance)
  7. {
  8. static BOOL     bRegistered=FALSE;
  9. WNDCLASS        wndcls;
  10.  
  11.    if (!bRegistered) {
  12.  
  13.        wndcls.style         = CS_DBLCLKS| CS_GLOBALCLASS|CS_PARENTDC;
  14.        wndcls.lpfnWndProc   = VListBoxWndProc;
  15.        wndcls.cbClsExtra    = 0;
  16.        wndcls.cbWndExtra    = sizeof(HANDLE);
  17.        wndcls.hInstance     = hInstance;
  18.        wndcls.hIcon         = NULL;
  19.        wndcls.hCursor       = LoadCursor(NULL, IDC_ARROW);
  20.        wndcls.hbrBackground =  (HBRUSH)(COLOR_WINDOW+1);
  21.        wndcls.lpszMenuName  = NULL;
  22.        wndcls.lpszClassName = (LPSTR)VLIST_CLASSNAME;
  23.  
  24.        bRegistered=RegisterClass(&wndcls);
  25.  
  26.    }
  27.  
  28.    return bRegistered;
  29. }
  30.  
  31. LRESULT _export CALLBACK VListBoxWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  32. {
  33.   PVLBOX pVLBox;
  34.   LONG lRetVal;
  35.  
  36.   /* Get the pVLBox for the given window now since we will use it a lot in
  37.    * various handlers. This was stored using SetWindowWord(hwnd,0,pVLBox) when
  38.    * we initially created the Virtual List Box control.
  39.    */
  40. #ifdef WIN32
  41.    pVLBox = (PVLBOX) GetWindowLong(hwnd,0);
  42.    if (message != WM_NCCREATE && (DWORD)pVLBox == (DWORD)-1)
  43. #else
  44.    pVLBox = (PVLBOX) GetWindowWord(hwnd,0);
  45.    if (message != WM_NCCREATE && (WORD)pVLBox == (WORD)-1)
  46. #endif
  47.        // The pVLBox was destroyed and this is a rogue message to be ignored.
  48.        return(0L);
  49.  
  50.   /* Dispatch the various messages we can receive */
  51.   switch (message)
  52.   {
  53.     case VLB_INITIALIZE:
  54.       SetScrollRange(pVLBox->hwndList, SB_VERT, 0, 100, TRUE);
  55.       pVLBox->vlbStruct.nCtlID = pVLBox->nId;
  56.       SendMessage(pVLBox->hwndParent, VLB_RANGE, 0, (LPARAM)(LPVLBSTRUCT)&(pVLBox->vlbStruct));
  57.       if ( pVLBox->vlbStruct.nStatus == VLB_OK ) {
  58.          pVLBox->lNumLogicalRecs = pVLBox->vlbStruct.lIndex;
  59.       }
  60.       else {
  61.          pVLBox->lNumLogicalRecs = -1L;
  62.          pVLBox->wFlags = pVLBox->wFlags | USEDATAVALUES;
  63.       }
  64.  
  65.       if ( pVLBox->styleSave & VLBS_USEDATAVALUES )
  66.          pVLBox->wFlags |= USEDATAVALUES;
  67.  
  68.       VLBFirstPage(pVLBox);
  69.       return VLB_OK;
  70.  
  71.       break;
  72.  
  73.     case WM_VSCROLL:
  74. #ifdef WIN32
  75.        switch(LOWORD(wParam)) {
  76. #else
  77.        switch(wParam) {
  78. #endif
  79.           case SB_LINEDOWN:
  80.               VLBScrollDownLine(pVLBox);
  81.               SetSelectedItem(pVLBox);
  82.           break;
  83.  
  84.           case SB_PAGEDOWN:
  85.               VLBScrollDownPage(pVLBox, 0);
  86.               SetSelectedItem(pVLBox);
  87.           break;
  88.  
  89.           case SB_LINEUP:
  90.               VLBScrollUpLine(pVLBox);
  91.               SetSelectedItem(pVLBox);
  92.           break;
  93.  
  94.           case SB_PAGEUP:
  95.               VLBScrollUpPage(pVLBox, 0);
  96.               SetSelectedItem(pVLBox);
  97.           break;
  98.  
  99.           case SB_TOP:
  100.               VLBFirstPage(pVLBox);
  101.               SetSelectedItem(pVLBox);
  102.           break;
  103.  
  104.           case SB_BOTTOM:
  105.               VLBLastPage(pVLBox);
  106.               SetSelectedItem(pVLBox);
  107.           break;
  108.  
  109.           case SB_THUMBPOSITION:
  110.             {
  111.               int nPos;
  112. #ifdef WIN32
  113.               nPos = HIWORD(wParam);
  114. #else
  115.               nPos = LOWORD(lParam);
  116. #endif
  117.               if ( nPos == 0 ) {
  118.                  VLBFirstPage(pVLBox);
  119.                  break;
  120.               }
  121.               else if ( nPos == 100 ) {
  122.                  VLBLastPage(pVLBox);
  123.                  break;
  124.               }
  125.  
  126.               if ( pVLBox->wFlags & USEDATAVALUES ) {
  127.                     if ( VLBFindPos(pVLBox, nPos) )
  128.                         return VLB_ERR;
  129.                     else
  130.                         SetSelectedItem(pVLBox);
  131.               }
  132.               else {
  133.                  if ( VLBFindPage(pVLBox,
  134. #ifdef WIN32
  135.                  (((LONG)HIWORD(wParam)
  136. #else
  137.                  (((LONG)LOWORD(lParam)
  138. #endif
  139.                    *(pVLBox->lNumLogicalRecs-pVLBox->nLines+1))/100L), TRUE) )
  140.                     return VLB_ERR;
  141.                  else
  142.                     SetSelectedItem(pVLBox);
  143.               }
  144.             }
  145.           break;
  146.  
  147.        }
  148.        return((LONG)TRUE);
  149.        break;
  150.  
  151.     case WM_COMMAND:
  152.       /* So that we can handle notification messages from the listbox.
  153.        */
  154. #ifdef WIN32
  155.       if ( HIWORD(wParam) == LBN_SELCHANGE ) {
  156. #else
  157.       if ( HIWORD(lParam) == LBN_SELCHANGE ) {
  158. #endif
  159.          SetSelectedItem(pVLBox);
  160.       }
  161. #ifdef WIN32
  162.       else if (HIWORD(wParam) == LBN_SELCANCEL) {
  163. #else
  164.       else if (HIWORD(lParam) == LBN_SELCANCEL) {
  165. #endif
  166.          pVLBox->lSelItem = -1L;
  167.       }
  168.       if (pVLBox->styleSave & VLBS_NOTIFY ) {
  169. #ifdef WIN32
  170.          return(VLBParentMessageHandler(pVLBox, message, (WPARAM)pVLBox->nId, lParam));
  171. #else
  172.          return(VLBParentMessageHandler(pVLBox, message, (WPARAM)(WORD)pVLBox->nId, lParam));
  173. #endif
  174.       }
  175.       else {
  176.          return TRUE;
  177.       }
  178.       break;
  179.  
  180.     case WM_CHARTOITEM: {
  181.            long lRet;
  182.  
  183.            if (pVLBox->styleSave & VLBS_WANTKEYBOARDINPUT ) {
  184.               lRet = VLBParentMessageHandler(pVLBox, WM_CHARTOITEM, wParam, lParam);
  185.            }
  186.            else {
  187.               lRet = -1;
  188.            }
  189.  
  190.            return lRet;
  191.         }
  192.         break;
  193.  
  194.     case WM_VKEYTOITEM: {
  195.            long lRet;
  196.  
  197.            if (pVLBox->styleSave & VLBS_WANTKEYBOARDINPUT ) {
  198.               lRet = VLBParentMessageHandler(pVLBox, WM_VKEYTOITEM, wParam, lParam);
  199.            }
  200.            else {
  201.               lRet = -1;
  202.            }
  203.  
  204.            if ( lRet == -1 ) {
  205. #ifdef WIN32
  206.        switch(LOWORD(wParam)) {
  207. #else
  208.        switch(wParam) {
  209. #endif
  210.                  case VK_DOWN:
  211.                     vlbLineDn(pVLBox);
  212.                  break;
  213.  
  214.                  case VK_UP:
  215.                     vlbLineUp(pVLBox);
  216.                  break;
  217.  
  218.                  case VK_PRIOR:
  219.                      vlbPGUP(pVLBox);
  220.                  break;
  221.  
  222.                  case VK_NEXT:
  223.                      vlbPGDN(pVLBox);
  224.                  break;
  225.  
  226.                  case VK_HOME:
  227.                      VLBFirstPage(pVLBox);
  228.                      SendMessage(pVLBox->hwndList, LB_SETCURSEL, 0, 0L);
  229.                      SetSelectedItem(pVLBox);
  230.                  break;
  231.  
  232.                  case VK_END:
  233.                   {
  234.                      int nLastLine;
  235.  
  236.                      if ( (pVLBox->nLines-1) < pVLBox->nCountInBox )
  237.                         nLastLine = pVLBox->nLines-1;
  238.                      else
  239.                         nLastLine = pVLBox->nCountInBox-1;
  240.  
  241.                      VLBLastPage(pVLBox);
  242.                      SendMessage(pVLBox->hwndList, LB_SETCURSEL, nLastLine, 0L);
  243.                      SetSelectedItem(pVLBox);
  244.                   }
  245.                  break;
  246.  
  247.                  default:
  248.                     return lRet;
  249.               }
  250.               SendMessage(pVLBox->hwndParent, WM_COMMAND,
  251.                           pVLBox->nId, MAKELPARAM(hwnd, LBN_SELCHANGE));
  252.            }
  253.            return lRet;
  254.         }
  255.         break;
  256.  
  257.     case _LB_MOUSESCROLL:
  258.        {
  259.          //
  260.          // The user is holding the mouse down outside the LB....
  261.          // Scroll the VLB as needed.
  262.          //
  263.          // Dont need to LB_SETCURSEL since the LB is going to do this for us.
  264.          //
  265.          int nSelected;
  266.  
  267.          nSelected = (int)SendMessage(pVLBox->hwndList, LB_GETCURSEL, 0, 0L);
  268.          if ( nSelected == pVLBox->nLines-1 ) {
  269.             VLBScrollDownLine(pVLBox);
  270.             SetSelectedItem(pVLBox);
  271.          }
  272.          else if ( nSelected == 0 ) {
  273.             VLBScrollUpLine(pVLBox);
  274.             SetSelectedItem(pVLBox);
  275.          }
  276.          //
  277.          // Values doesn't mean much since this messsage is passed back to
  278.          // original LB proc
  279.          //
  280.          return 0L;
  281.       }
  282.       break;
  283.  
  284.     case WM_CREATE:
  285.       /* wParam - not used
  286.          lParam - Points to the CREATESTRUCT data structure for the window.
  287.        */
  288.       return(VLBCreateHandler(pVLBox, hwnd, (LPCREATESTRUCT)lParam));
  289.       break;
  290.  
  291.     case WM_ERASEBKGND:
  292.       /* Just return 1L so that the background isn't erased */
  293.       return((LONG)TRUE);
  294.       break;
  295.  
  296.     case WM_GETFONT:
  297.        return((LONG)(pVLBox->hFont));
  298.        break;
  299.  
  300.     case WM_GETDLGCODE:
  301.       /* wParam - not used
  302.          lParam - not used */
  303.       return((LONG)(DLGC_WANTCHARS | DLGC_WANTARROWS));
  304.       break;
  305.  
  306.     case WM_SETFONT:
  307. #ifdef WIN32
  308.       VLBSetFontHandler(pVLBox, (HANDLE)wParam, wParam);
  309. #else
  310.       VLBSetFontHandler(pVLBox, (HANDLE)wParam, LOWORD(lParam));
  311. #endif
  312.       break;
  313.  
  314.     case WM_LBUTTONDOWN:
  315.     case WM_MBUTTONDOWN:
  316.     case WM_RBUTTONDOWN:
  317.     case WM_KEYDOWN:
  318.        // Set the focus to the Virtual List Box if we get a mouse click
  319.        // or key press on the parent window.
  320.        SetFocus(pVLBox->hwndList);
  321.        SendMessage(pVLBox->hwndList, message, wParam, lParam);
  322.       break;
  323.  
  324.     case WM_NCDESTROY:
  325.       /* wParam - used by DefWndProc called within VLBNcDestroyHandler
  326.          lParam - used by DefWndProc called within VLBNcDestroyHandler */
  327.       VLBNcDestroyHandler(hwnd, pVLBox, wParam, lParam);
  328.       break;
  329.  
  330.     case WM_KILLFOCUS:
  331.           if ( (HWND) wParam != pVLBox->hwndList )
  332.               pVLBox->wFlags  &= ~HASFOCUS;
  333.  
  334.       break;
  335.  
  336.     case WM_SETFOCUS:
  337.         {
  338.           int i;
  339.  
  340.           pVLBox->wFlags  |= HASFOCUS;
  341.  
  342.           if ( ! (pVLBox->wFlags & PARENTFOCUS) ) {
  343.              if ( (i=vlbInVLB(pVLBox, pVLBox->lSelItem)) >= 0 ) {
  344.                 pVLBox->wFlags &= ~PARENTFOCUS;
  345.                 SetFocus(pVLBox->hwndList);
  346.              }
  347.              else {
  348.                 pVLBox->wFlags |= PARENTFOCUS;
  349.              }
  350.           }
  351.         }
  352.       break;
  353.  
  354.     case WM_SETREDRAW:
  355.       /* wParam - specifies state of the redraw flag. nonzero = redraw
  356.          lParam - not used */
  357.       if ( wParam) {
  358.          vlbRedrawOn(pVLBox);
  359.       }
  360.       else {
  361.          vlbRedrawOff(pVLBox);
  362.       }
  363.       return TRUE;
  364.       break;
  365.  
  366.     case WM_ENABLE:
  367.       /* Invalidate the rect to cause it to be drawn in grey for its disabled
  368.        * view or ungreyed for non-disabled view.
  369.        */
  370.       InvalidateRect(pVLBox->hwnd, NULL, FALSE);
  371.       /* Enable/disable the listbox window
  372.        */
  373.       EnableWindow(pVLBox->hwndList, wParam);
  374.       // EnableWindow(pVLBox->hwndScroll, wParam);
  375.       break;
  376.  
  377.     case WM_SIZE:
  378.       /* wParam - defines the type of resizing fullscreen, sizeiconic,
  379.                   sizenormal etc.
  380.          lParam - new width in LOWORD, new height in HIGHWORD of client area */
  381.       if (!LOWORD(lParam) || !HIWORD(lParam) || !pVLBox->hwndList)
  382.           /* If being sized to a zero width or to a zero height or we aren't
  383.         * fully initialized, just return.
  384.         */
  385.           return(0);
  386.       VLBSizeHandler(pVLBox, 0);
  387.       break;
  388.  
  389.     case VLB_FINDSTRING:
  390.     case VLB_FINDSTRINGEXACT:
  391.     case VLB_SELECTSTRING:
  392.        {
  393.           VLBSTRUCT FAR *lpvlbInStruct;
  394.           UINT  ReturnMsg;
  395.  
  396.           switch (message)
  397.           {
  398.             case VLB_FINDSTRING:
  399.                 ReturnMsg = VLBR_FINDSTRING;
  400.                 break;
  401.  
  402.             case VLB_FINDSTRINGEXACT:
  403.                 ReturnMsg = VLBR_FINDSTRINGEXACT;
  404.                 break;
  405.  
  406.             case VLB_SELECTSTRING:
  407.                 ReturnMsg = VLBR_FINDSTRINGEXACT;
  408.                 break;
  409.           }
  410.  
  411.           lpvlbInStruct = (LPVLBSTRUCT)lParam;
  412.  
  413.           pVLBox->vlbStruct.lIndex        = lpvlbInStruct->lIndex;
  414.           pVLBox->vlbStruct.lData         = lpvlbInStruct->lData;
  415.           pVLBox->vlbStruct.lpFindString  = lpvlbInStruct->lpFindString;
  416.           pVLBox->vlbStruct.lpTextPointer = NULL;
  417.  
  418.           pVLBox->vlbStruct.nCtlID = pVLBox->nId;
  419.           SendMessage(pVLBox->hwndParent, ReturnMsg, 0,  (LPARAM)(LPVLBSTRUCT)&(pVLBox->vlbStruct));
  420.           if ( pVLBox->vlbStruct.nStatus == VLB_OK ) {
  421.              if ( pVLBox->wFlags & USEDATAVALUES )
  422.                 lRetVal = pVLBox->vlbStruct.lData;
  423.              else
  424.                 lRetVal = pVLBox->vlbStruct.lIndex;
  425.  
  426.              if ( message != VLB_SELECTSTRING ) {
  427.                 return lRetVal;
  428.              }
  429.  
  430.              if ( pVLBox->wFlags & USEDATAVALUES ) {
  431.                 //
  432.                 // Strings or search for data
  433.                 //
  434.                 int i;
  435.                 if ( (i=vlbFindData(pVLBox, pVLBox->vlbStruct.lData)) != LB_ERR ) {
  436.                     SendMessage(pVLBox->hwndList, LB_SETCURSEL, i, 0L);
  437.                     SetSelectedItem(pVLBox);
  438.                     return lRetVal;
  439.                 }
  440.                 else {
  441.                    if ( VLBFindPage(pVLBox, pVLBox->vlbStruct.lData, TRUE) )
  442.                         return VLB_ERR;
  443.  
  444.                    SendMessage(pVLBox->hwndList, LB_SETCURSEL, 0, 0L);
  445.                    SetSelectedItem(pVLBox);
  446.                    return lRetVal;
  447.                 }
  448.              }
  449.              else {
  450.                 //
  451.                 // Is this item in the list box now ??
  452.                 //
  453.                 if ( pVLBox->vlbStruct.lIndex >= pVLBox->lToplIndex &&
  454.                      pVLBox->vlbStruct.lIndex <= (pVLBox->lToplIndex+(LONG)(pVLBox->nCountInBox)-1)) {
  455.                      int nItemNum;
  456.  
  457.                      nItemNum = (int) (pVLBox->vlbStruct.lIndex-pVLBox->lToplIndex);
  458.                      SendMessage(pVLBox->hwndList, LB_SETCURSEL, nItemNum, 0L);
  459.                      SetSelectedItem(pVLBox);
  460.                      return lRetVal;
  461.                 }
  462.                 //
  463.                 // OK Adjust to show item
  464.                 //
  465.                 if ( VLBFindPage(pVLBox, pVLBox->vlbStruct.lIndex, TRUE) )
  466.                     return VLB_ERR;
  467.  
  468.                 SendMessage(pVLBox->hwndList, LB_SETCURSEL, 0, 0L);
  469.                 SetSelectedItem(pVLBox);
  470.                 return lRetVal;
  471.              }
  472.           }
  473.           else
  474.              return VLB_ERR;
  475.        }
  476.       break;
  477.  
  478.     case VLB_RESETCONTENT:
  479.       SendMessage(pVLBox->hwndList, LB_RESETCONTENT, 0, 0L);
  480.       SendMessage(pVLBox->hwndParent, VLBN_FREEALL, pVLBox->nId, 0L);
  481.       pVLBox->vlbStruct.nCtlID = pVLBox->nId;
  482.       SendMessage(pVLBox->hwndParent, VLB_RANGE, 0, (LPARAM)(LPVLBSTRUCT)&(pVLBox->vlbStruct));
  483.       if ( pVLBox->vlbStruct.nStatus == VLB_OK )
  484.          pVLBox->lNumLogicalRecs = pVLBox->vlbStruct.lIndex;
  485.       else {
  486.          pVLBox->lNumLogicalRecs = -1L;
  487.          pVLBox->wFlags |= USEDATAVALUES;
  488.       }
  489.  
  490.       VLBFirstPage(pVLBox);
  491.       return VLB_OK;
  492.       break;
  493.  
  494.     case VLB_SETCURSEL:
  495.        // wParam Has Set Option:
  496.        //   VLBC_FIRST
  497.        //   VLBC_PREV
  498.        //   VLBC_NEXT
  499.        //   VLBC_LAST
  500.        //   VLBC_FINDITEM
  501.        //
  502.        //  lParam has the item number or item data
  503.        return ( vlbSetCurSel(pVLBox, wParam, lParam) );
  504.        break;
  505.  
  506.     case VLB_UPDATEPAGE:
  507.          pVLBox->vlbStruct.nCtlID = pVLBox->nId;
  508.          SendMessage(pVLBox->hwndParent, VLB_RANGE, 0, (LPARAM)(LPVLBSTRUCT)&(pVLBox->vlbStruct));
  509.          if ( pVLBox->vlbStruct.nStatus == VLB_OK ) {
  510.             pVLBox->lNumLogicalRecs = pVLBox->vlbStruct.lIndex;
  511.          }
  512.          else {
  513.             pVLBox->lNumLogicalRecs = -1L;
  514.             pVLBox->wFlags |= USEDATAVALUES;
  515.          }
  516.  
  517.          if ( pVLBox->lNumLogicalRecs <= pVLBox->nLines ) {
  518.             VLBFirstPage(pVLBox);
  519.          }
  520.          else if ( pVLBox->wFlags & USEDATAVALUES ) {
  521.              if ( VLBFindPage(pVLBox, SendMessage(pVLBox->hwndList, LB_GETITEMDATA, 0, 0L), FALSE ) )
  522.                 return VLB_ERR;
  523.          }
  524.          else {
  525.              if ( VLBFindPage(pVLBox, pVLBox->lToplIndex, FALSE) )
  526.                 return VLB_ERR;
  527.          }
  528.        break;
  529.  
  530.     case VLB_PAGEUP:
  531.          VLBScrollUpPage(pVLBox, wParam);
  532.          break;
  533.  
  534.     case VLB_PAGEDOWN:
  535.          VLBScrollDownPage(pVLBox, wParam);
  536.          break;
  537.  
  538.     case VLB_GETCURSEL:
  539.          return pVLBox->lSelItem;
  540.          break;
  541.  
  542.     case VLB_GETLINES:
  543.          return (LONG)pVLBox->nLines;
  544.          break;
  545.  
  546.     case VLB_GETITEMDATA:
  547.         {
  548.           LPVLBSTRUCT lpvlbInStruct;
  549.           int i;
  550.           LPARAM SendlParam;
  551.  
  552.  
  553.           lpvlbInStruct = (LPVLBSTRUCT)lParam;
  554.  
  555.           if (pVLBox->wFlags & USEDATAVALUES) {
  556.              SendlParam = lpvlbInStruct->lIndex;
  557.           }
  558.           else {
  559.              SendlParam = lpvlbInStruct->lData;
  560.           }
  561.  
  562.           if ( (i=vlbInVLB(pVLBox, SendlParam)) >= 0 ) {
  563.              return(SendMessage(pVLBox->hwndList, LB_GETITEMDATA, i, 0L));
  564.           }
  565.           else {
  566.              pVLBox->vlbStruct.lData = pVLBox->vlbStruct.lIndex = lParam;
  567.              pVLBox->vlbStruct.nCtlID = pVLBox->nId;
  568.              SendMessage(pVLBox->hwndParent, VLBR_GETITEMDATA, 0, (LPARAM)(LPVLBSTRUCT)&(pVLBox->vlbStruct));
  569.              if ( pVLBox->vlbStruct.nStatus == VLB_OK )
  570.                 return pVLBox->vlbStruct.lData;
  571.              else
  572.                 return VLB_ERR;
  573.           }
  574.         }
  575.         break;
  576.  
  577.     case VLB_GETCOUNT:
  578.       return pVLBox->lNumLogicalRecs;
  579.  
  580.     case VLB_GETTEXT:
  581.         {
  582.           LPVLBSTRUCT lpvlbInStruct;
  583.           int i;
  584.           LPARAM SendlParam;
  585.  
  586.           lpvlbInStruct = (LPVLBSTRUCT)lParam;
  587.  
  588.           if (pVLBox->wFlags & USEDATAVALUES) {
  589.              SendlParam = lpvlbInStruct->lData;
  590.           }
  591.           else {
  592.              SendlParam = lpvlbInStruct->lIndex;
  593.           }
  594.  
  595.           if ( (i=vlbInVLB(pVLBox, SendlParam)) >= 0 ) {
  596.              return(SendMessage(pVLBox->hwndList, LB_GETTEXT, i, (LPARAM)lpvlbInStruct->lpTextPointer));
  597.           }
  598.           else {
  599.              pVLBox->vlbStruct.lData = pVLBox->vlbStruct.lIndex = SendlParam;
  600.              pVLBox->vlbStruct.nCtlID = pVLBox->nId;
  601.              SendMessage(pVLBox->hwndParent, VLBR_GETTEXT, 0, (LPARAM)(LPVLBSTRUCT)&(pVLBox->vlbStruct));
  602.              if ( pVLBox->vlbStruct.nStatus == VLB_OK ) {
  603.                 _fstrcpy(lpvlbInStruct->lpTextPointer, pVLBox->vlbStruct.lpTextPointer);
  604.                 return _fstrlen(pVLBox->vlbStruct.lpTextPointer);
  605.              }
  606.              else
  607.                 return VLB_ERR;
  608.           }
  609.         }
  610.         break;
  611.  
  612.     case VLB_GETTEXTLEN:
  613.         {
  614.           LPVLBSTRUCT lpvlbInStruct;
  615.           int i;
  616.           LPARAM SendlParam;
  617.  
  618.           lpvlbInStruct = (LPVLBSTRUCT)lParam;
  619.  
  620.           if (pVLBox->wFlags & USEDATAVALUES) {
  621.              SendlParam = lpvlbInStruct->lData;
  622.           }
  623.           else {
  624.              SendlParam = lpvlbInStruct->lIndex;
  625.           }
  626.  
  627.           if ( (i=vlbInVLB(pVLBox, SendlParam)) >= 0 ) {
  628.              return(SendMessage(pVLBox->hwndList, LB_GETTEXTLEN, i, 0L));
  629.           }
  630.           else {
  631.              pVLBox->vlbStruct.lData = pVLBox->vlbStruct.lIndex = SendlParam;
  632.              pVLBox->vlbStruct.nCtlID = pVLBox->nId;
  633.              return SendMessage(pVLBox->hwndParent, VLBR_GETTEXTLEN, 0, (LPARAM)(LPVLBSTRUCT)&(pVLBox->vlbStruct));
  634.           }
  635.         }
  636.         break;
  637.  
  638.     case VLB_SETITEMDATA:
  639.         {
  640.           LPVLBSTRUCT lpvlbInStruct;
  641.           int i;
  642.           LPARAM SendlParam;
  643.  
  644.           lpvlbInStruct = (LPVLBSTRUCT)lParam;
  645.  
  646.           if (pVLBox->wFlags & USEDATAVALUES) {
  647.              SendlParam = lpvlbInStruct->lIndex;
  648.           }
  649.           else {
  650.              SendlParam = lpvlbInStruct->lData;
  651.           }
  652.  
  653.           if ( (i=vlbInVLB(pVLBox, SendlParam)) >= 0 ) {
  654.              return(SendMessage(pVLBox->hwndList, LB_SETITEMDATA, i, (LPARAM)lpvlbInStruct->lIndex));
  655.           }
  656.           else return VLB_ERR;
  657.         }
  658.         break;
  659.  
  660.     case VLB_SETITEMHEIGHT:
  661.           return SendMessage(pVLBox->hwndList, LB_SETITEMHEIGHT, 0, lParam);
  662.         break;
  663.  
  664.     case VLB_GETITEMHEIGHT:
  665.           return SendMessage(pVLBox->hwndList, LB_GETITEMHEIGHT, 0, 0L);
  666.         break;
  667.  
  668.     case VLB_GETITEMRECT:
  669.         {
  670.           LPVLBSTRUCT lpvlbInStruct;
  671.           int i;
  672.           LPARAM SendlParam;
  673.  
  674.           lpvlbInStruct = (LPVLBSTRUCT)lParam;
  675.  
  676.           if (pVLBox->wFlags & USEDATAVALUES) {
  677.              SendlParam = lpvlbInStruct->lIndex;
  678.           }
  679.           else {
  680.              SendlParam = lpvlbInStruct->lData;
  681.           }
  682.  
  683.           if ( (i=vlbInVLB(pVLBox, SendlParam)) >= 0 ) {
  684.              return(SendMessage(pVLBox->hwndList, LB_GETITEMRECT, i, (LPARAM)lpvlbInStruct->lpTextPointer));
  685.           }
  686.           else return VLB_ERR;
  687.         }
  688.         break;
  689.  
  690.     case VLB_GETHORIZONTALEXTENT:
  691.           return SendMessage(pVLBox->hwndList, LB_GETHORIZONTALEXTENT, 0, 0L);
  692.         break;
  693.  
  694.     case VLB_SETHORIZONTALEXTENT:
  695.         {
  696.           int nOrigin;
  697.           RECT rc;
  698.           int  nScrollBar;
  699.  
  700.           SendMessage(pVLBox->hwndList, LB_GETITEMRECT, 0,(LPARAM)(LPRECT)&rc);
  701.           nOrigin = rc.left;
  702.           GetClientRect(pVLBox->hwndList, &rc);
  703.           nScrollBar = max((int)wParam - (rc.right - rc.left),0);
  704.           if (nOrigin || nScrollBar) {
  705.              if ( pVLBox->styleSave & VLBS_DISABLENOSCROLL )
  706.                    EnableScrollBar(pVLBox->hwndList, SB_HORZ, ESB_ENABLE_BOTH);
  707.              else {
  708.              if (!pVLBox->bHScrollBar) {
  709.                    pVLBox->bHScrollBar = TRUE;
  710.                    ShowScrollBar(pVLBox->hwndList, SB_HORZ, TRUE);
  711.                    VLBCountLines(pVLBox);
  712.                 }
  713.              }
  714.           }
  715.           else {
  716.              if ( pVLBox->styleSave & VLBS_DISABLENOSCROLL )
  717.                    EnableScrollBar(pVLBox->hwndList, SB_HORZ, ESB_DISABLE_BOTH);
  718.              else {
  719.                 if (pVLBox->bHScrollBar) {
  720.                    pVLBox->bHScrollBar = FALSE;
  721.                    ShowScrollBar(pVLBox->hwndList, SB_HORZ, FALSE);
  722.                    VLBCountLines(pVLBox);
  723.                 }
  724.              }
  725.           }
  726.           return SendMessage(pVLBox->hwndList, LB_SETHORIZONTALEXTENT, wParam, 0L);
  727.         }
  728.         break;
  729.  
  730.     case VLB_SETTOPINDEX:
  731.         {
  732.           int i, nScroll;
  733.  
  734.           if ( (i=vlbInVLB(pVLBox, lParam)) > 0 ) {
  735.              nScroll = (int)(-1*(pVLBox->nLines-i));
  736.              VLBScrollDownPage(pVLBox, nScroll);
  737.           }
  738.           else if ( pVLBox->wFlags & USEDATAVALUES ) {
  739.              if ( VLBFindPage(pVLBox, lParam, TRUE ))
  740.                 return VLB_ERR;
  741.           }
  742.           else {
  743.              if ( VLBFindPage(pVLBox, lParam, TRUE) )
  744.                 return VLB_ERR;
  745.           }
  746.  
  747.         }
  748.         break;
  749.  
  750.     case VLB_GETTOPINDEX:
  751.           return pVLBox->lToplIndex;
  752.         break;
  753.  
  754.     case WM_MEASUREITEM:
  755.     case WM_DELETEITEM:
  756.     case WM_DRAWITEM:
  757.     case WM_COMPAREITEM:
  758.       return(VLBMessageItemHandler(pVLBox, message, (LPSTR)lParam));
  759.       break;
  760.  
  761.     case WM_NCCREATE:
  762.       /* wParam - Contains a handle to the window being created
  763.          lParam - Points to the CREATESTRUCT data structure for the window.
  764.        */
  765.       return(VLBNcCreateHandler(hwnd, (LPCREATESTRUCT)lParam));
  766.       break;
  767.  
  768.     default:
  769.       if ( message >= WM_USER )
  770.          return(SendMessage(pVLBox->hwndList, message, wParam, lParam));
  771.       else
  772.          return DefWindowProc(hwnd, message, wParam, lParam);
  773.       break;
  774.  
  775.   } /* switch (message) */
  776.  
  777.   return((LONG)(LONG)TRUE);
  778. } /* VListBoxWndProc */
  779.  
  780.  
  781. LONG VLBMessageItemHandler( PVLBOX pVLBox,  UINT message, LPSTR lpfoo)
  782. /*
  783.  * effects: Handles WM_DRAWITEM,WM_MEASUREITEM,WM_DELETEITEM,WM_COMPAREITEM
  784.  * messages from the listbox.
  785.  */
  786. {
  787.   /*
  788.    * Send the <foo>item message back to the application after changing some
  789.    * parameters to their Virtual List Box specific versions.
  790.    */
  791.   long lRetVal;
  792.  
  793.   ((LPMEASUREITEMSTRUCT)lpfoo)->CtlType = ODT_LISTBOX;
  794. #ifdef WIN32
  795.   ((LPMEASUREITEMSTRUCT)lpfoo)->CtlID   = (DWORD)pVLBox->nId;
  796. #else
  797.   ((LPMEASUREITEMSTRUCT)lpfoo)->CtlID   = (WORD)pVLBox->nId;
  798. #endif
  799.  
  800.   if (message == WM_DRAWITEM)
  801.       ((LPDRAWITEMSTRUCT)lpfoo)->hwndItem    = pVLBox->hwnd;
  802.   else if (message == WM_DELETEITEM)
  803.       ((LPDELETEITEMSTRUCT)lpfoo)->hwndItem  = pVLBox->hwnd;
  804.   else if (message == WM_COMPAREITEM)
  805.       ((LPCOMPAREITEMSTRUCT)lpfoo)->hwndItem  = pVLBox->hwnd;
  806.  
  807.   lRetVal = SendMessage(pVLBox->hwndParent, message,
  808.                     (WPARAM)pVLBox->nId, (LPARAM)lpfoo);
  809.  
  810.   if (message == WM_MEASUREITEM ) {
  811.      // Size the list box based on height in message
  812.      VLBSizeHandler( pVLBox , ((LPMEASUREITEMSTRUCT)lpfoo)->itemHeight);
  813.   }
  814.  
  815.   return lRetVal;
  816.  
  817. }
  818.  
  819.  
  820. LONG VLBParentMessageHandler( PVLBOX pVLBox, UINT message, WPARAM wParam, LPARAM lParam)
  821. {
  822.   return SendMessage(pVLBox->hwndParent,
  823.               message,
  824.               wParam,
  825.               MAKELPARAM(pVLBox->hwnd, HIWORD(lParam) ) );
  826.  
  827. }
  828.  
  829.  
  830.  
  831. int vlbInVLB( PVLBOX pVLBox, LONG lData)
  832. {
  833.    int i;
  834.  
  835.    if ( pVLBox->wFlags & USEDATAVALUES ) {
  836.       if ( (i=vlbFindData(pVLBox, lData)) != LB_ERR ) {
  837.         return i;
  838.       }
  839.       else {
  840.         return  VLB_ERR;
  841.       }
  842.    }
  843.    else {
  844.       if ( lData >= pVLBox->lToplIndex &&
  845.            lData <= (pVLBox->lToplIndex+(LONG)(pVLBox->nCountInBox)-1)) {
  846.         return (int) (lData - pVLBox->lToplIndex);
  847.       }
  848.       else {
  849.         return  VLB_ERR;
  850.       }
  851.    }
  852. }
  853.  
  854. int vlbFindData( PVLBOX pVLBox, LONG lData)
  855. {
  856.    int i;
  857.  
  858.    i = 0;
  859.    while ( i < pVLBox->nCountInBox ) {
  860.       if ( SendMessage(pVLBox->hwndList, LB_GETITEMDATA, i, 0L) == lData )
  861.          return i;
  862.       i++;
  863.    }
  864.  
  865.    return VLB_ERR;
  866.  
  867. }
  868.  
  869. void vlbRedrawOff(PVLBOX pVLBox)
  870. {
  871.      pVLBox->nvlbRedrawState--;
  872.      if ( pVLBox->nvlbRedrawState == 0 ) {
  873.         SendMessage(pVLBox->hwndList, WM_SETREDRAW, 0, 0L);
  874.      }
  875. }
  876.  
  877. void vlbRedrawOn(PVLBOX pVLBox)
  878. {
  879.      pVLBox->nvlbRedrawState++;
  880.      if ( pVLBox->nvlbRedrawState == 1 ) {
  881.         SendMessage(pVLBox->hwndList, WM_SETREDRAW, 1, 0L);
  882.         InvalidateRect(pVLBox->hwnd, NULL, FALSE);
  883.      }
  884. }
  885.  
  886.  
  887. //
  888. // List Box subclass function
  889. //
  890.  
  891. LRESULT  CALLBACK _loadds LBSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  892. {
  893.     PVLBOX pVLBox;
  894.  
  895.     switch (message) {
  896.     case WM_VSCROLL:
  897.         //
  898.         // Handle all the scrolling in the Vlist proc
  899.         //
  900.         return SendMessage(GetParent(hwnd), message, wParam, lParam);
  901.  
  902.     case _LB_MOUSESCROLL:
  903.         //
  904.         // Check for scroll then pass message on the the LB
  905.         //
  906.         SendMessage(GetParent(hwnd), message, wParam, lParam);
  907.       break;
  908.  
  909.     default:
  910.         break;
  911.     }
  912.  
  913.     //
  914.     // call the old window proc
  915.     //
  916. #ifdef WIN32
  917.    pVLBox = (PVLBOX) GetWindowLong(GetParent(hwnd),0);
  918. #else
  919.    pVLBox = (PVLBOX) GetWindowWord(GetParent(hwnd),0);
  920. #endif
  921.  
  922.     if ( message == WM_SETFOCUS ) {
  923.           pVLBox->wFlags  |= HASFOCUS;
  924.     }
  925.  
  926.     return CallWindowProc((WNDPROC)(pVLBox->lpfnLBWndProc) , hwnd, message,
  927.                           (WPARAM) wParam, (LPARAM)lParam);
  928.  
  929. }
  930.  
  931.  
  932. BOOL TestSelectedItem(PVLBOX pVLBox, VLBSTRUCT vlbStruct)
  933. {
  934.     if ( pVLBox->wFlags & USEDATAVALUES ) {
  935.        if ( pVLBox->lSelItem == vlbStruct.lData )
  936.          return TRUE;
  937.        else
  938.          return FALSE;
  939.     }
  940.     else {
  941.        if ( pVLBox->lSelItem == vlbStruct.lIndex )
  942.          return TRUE;
  943.        else
  944.          return FALSE;
  945.     }
  946. }
  947.  
  948. void SetSelectedItem(PVLBOX pVLBox)
  949. {
  950.     int nSelected;
  951.  
  952.     nSelected = (int)SendMessage(pVLBox->hwndList, LB_GETCURSEL, 0, 0L);
  953.  
  954.     if ( nSelected == LB_ERR )
  955.        return;
  956.  
  957.     if ( pVLBox->wFlags & USEDATAVALUES ) {
  958.        pVLBox->lSelItem =
  959.             SendMessage(pVLBox->hwndList, LB_GETITEMDATA, nSelected, 0L);
  960.     }
  961.     else {
  962.        pVLBox->lSelItem = (LONG)nSelected + pVLBox->lToplIndex;
  963.     }
  964. }
  965.  
  966. void vlbLineDn(PVLBOX pVLBox)
  967. {
  968.     //
  969.     // Do we have a selected item ???
  970.     //
  971.     if ( pVLBox->lSelItem != -1L )
  972.     {
  973.         long lSelected;
  974.         if ( (lSelected = SendMessage(pVLBox->hwndList, LB_GETCURSEL,
  975.              0, 0L)) == -1L ) {
  976.                //
  977.                // Current selction is visible....NOT
  978.                //
  979.                vlbRedrawOff(pVLBox);
  980.  
  981.                //
  982.                // Put selected item at top of LB
  983.                //
  984.                VLBFindPage(pVLBox, pVLBox->lSelItem, TRUE);
  985.  
  986.                //
  987.                // Scroll the LB down a line
  988.                //
  989.                VLBScrollDownLine(pVLBox);
  990.                SendMessage(pVLBox->hwndList, LB_SETCURSEL, 0, 0L);
  991.                SetFocus(pVLBox->hwndList);
  992.                SetSelectedItem(pVLBox);
  993.  
  994.                //
  995.                // Update the Screen
  996.                //
  997.                vlbRedrawOn(pVLBox);
  998.         }
  999.         else {
  1000.                //
  1001.                // Current selection is visible
  1002.                //
  1003.  
  1004.                //
  1005.                // Where is it ????
  1006.                //
  1007.                if ( (int)lSelected == (pVLBox->nLines-1) ) {
  1008.                   //
  1009.                   // At the Bottom... Scroll down 1 page less 1 line
  1010.                   //                  Put selection at bottom
  1011.                   //
  1012.                   VLBScrollDownLine(pVLBox);
  1013.                   SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  1014.                               pVLBox->nLines-1, 0L);
  1015.                   SetFocus(pVLBox->hwndList);
  1016.                   SetSelectedItem(pVLBox);
  1017.                }
  1018.                else {
  1019.                    SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  1020.                                (int)(lSelected)+1, 0L);
  1021.                    SetFocus(pVLBox->hwndList);
  1022.                    SetSelectedItem(pVLBox);
  1023.                }
  1024.         }
  1025.     }
  1026. }
  1027.  
  1028. void vlbLineUp(PVLBOX pVLBox)
  1029. {
  1030.     //
  1031.     // Do we have a selected item ???
  1032.     //
  1033.     if ( pVLBox->lSelItem != -1L )
  1034.     {
  1035.         long lSelected;
  1036.         if ( (lSelected = SendMessage(pVLBox->hwndList, LB_GETCURSEL,
  1037.              0, 0L)) == -1L ) {
  1038.                //
  1039.                // Current selction is visible....NOT
  1040.                //
  1041.                vlbRedrawOff(pVLBox);
  1042.  
  1043.                //
  1044.                // Put selected item at top of LB
  1045.                //
  1046.                VLBFindPage(pVLBox, pVLBox->lSelItem, TRUE);
  1047.  
  1048.                //
  1049.                // Scroll the LB down a line
  1050.                //
  1051.                VLBScrollUpLine(pVLBox);
  1052.                SendMessage(pVLBox->hwndList, LB_SETCURSEL, 0, 0L);
  1053.                SetFocus(pVLBox->hwndList);
  1054.                SetSelectedItem(pVLBox);
  1055.  
  1056.                //
  1057.                // Update the Screen
  1058.                //
  1059.                vlbRedrawOn(pVLBox);
  1060.         }
  1061.         else {
  1062.                //
  1063.                // Current selection is visible
  1064.                //
  1065.  
  1066.                //
  1067.                // Where is it ????
  1068.                //
  1069.                if ( (int)lSelected == 0 ) {
  1070.                   //
  1071.                   // At the Bottom... Scroll up 1 page less 1 line
  1072.                   //                  Put selection at bottom
  1073.                   //
  1074.                   VLBScrollUpLine(pVLBox);
  1075.                   SendMessage(pVLBox->hwndList, LB_SETCURSEL, 0, 0L);
  1076.                   SetFocus(pVLBox->hwndList);
  1077.                   SetSelectedItem(pVLBox);
  1078.                }
  1079.                else {
  1080.                    SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  1081.                                (int)(lSelected)-1, 0L);
  1082.                    SetFocus(pVLBox->hwndList);
  1083.                    SetSelectedItem(pVLBox);
  1084.                }
  1085.         }
  1086.     }
  1087. }
  1088.  
  1089.  
  1090. void vlbPGDN(PVLBOX pVLBox)
  1091. {
  1092.     //
  1093.     // Do we have a selected item ???
  1094.     //
  1095.     if ( pVLBox->lSelItem != -1L )
  1096.     {
  1097.         long lSelected;
  1098.         if ( (lSelected = SendMessage(pVLBox->hwndList, LB_GETCURSEL,
  1099.              0, 0L)) == -1L ) {
  1100.                //
  1101.                // Current selction is visible....NOT
  1102.                //
  1103.                vlbRedrawOff(pVLBox);
  1104.  
  1105.                //
  1106.                // Put selected item at top of LB
  1107.                //
  1108.                VLBFindPage(pVLBox, pVLBox->lSelItem, TRUE);
  1109.  
  1110.                //
  1111.                // Scroll the LB down a page
  1112.                //
  1113.                VLBScrollDownPage(pVLBox, -1);
  1114.                SendMessage(pVLBox->hwndList, LB_SETCURSEL, 0, 0L);
  1115.                SetFocus(pVLBox->hwndList);
  1116.                SetSelectedItem(pVLBox);
  1117.  
  1118.                //
  1119.                // Update the Screen
  1120.                //
  1121.                vlbRedrawOn(pVLBox);
  1122.         }
  1123.         else {
  1124.                //
  1125.                // Current selection is visible
  1126.                //
  1127.  
  1128.                //
  1129.                // Where is it ????
  1130.                //
  1131.                if ( lSelected == 0L ) {
  1132.                   //
  1133.                   // At the top... put selection at bottom
  1134.                   //
  1135.                   SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  1136.                               pVLBox->nLines-1, 0L);
  1137.                   SetFocus(pVLBox->hwndList);
  1138.                   SetSelectedItem(pVLBox);
  1139.                }
  1140.                else if ( (int)lSelected == (pVLBox->nLines-1) ) {
  1141.                   //
  1142.                   // At the Bottom... Scroll down 1 page less 1 line
  1143.                   //                  Put selection at bottom
  1144.                   //
  1145.                   VLBScrollDownPage(pVLBox, -1);
  1146.                   SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  1147.                               pVLBox->nLines-1, 0L);
  1148.                   SetFocus(pVLBox->hwndList);
  1149.                   SetSelectedItem(pVLBox);
  1150.                }
  1151.                else {
  1152.                    //
  1153.                    // In the middle ... scroll down 1 page less
  1154.                    //                   the number of lines
  1155.                    //                   the selection is away
  1156.                    //                   from the bottom
  1157.                    //
  1158.                    //                   Put selection at bottom
  1159.                    //
  1160.                    int nAdjust;
  1161.                    nAdjust = -1 * (pVLBox->nLines-(int)lSelected);
  1162.                    VLBScrollDownPage(pVLBox, nAdjust);
  1163.                    SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  1164.                                pVLBox->nLines-1, 0L);
  1165.                    SetFocus(pVLBox->hwndList);
  1166.                    SetSelectedItem(pVLBox);
  1167.                }
  1168.         }
  1169.     }
  1170. }
  1171.  
  1172.  
  1173. void vlbPGUP(PVLBOX pVLBox)
  1174. {
  1175.     //
  1176.     // Do we have a selected item ???
  1177.     //
  1178.     if ( pVLBox->lSelItem != -1L )
  1179.     {
  1180.         long lSelected;
  1181.         if ( (lSelected = SendMessage(pVLBox->hwndList, LB_GETCURSEL,
  1182.              0, 0L)) == -1L ) {
  1183.                //
  1184.                // Current selction is visible....NOT
  1185.                //
  1186.                vlbRedrawOff(pVLBox);
  1187.  
  1188.                //
  1189.                // Put selected item at top of LB
  1190.                //
  1191.                VLBFindPage(pVLBox, pVLBox->lSelItem, TRUE);
  1192.  
  1193.                //
  1194.                // Scroll the LB UP a page less 1 line
  1195.                //
  1196.                VLBScrollUpPage(pVLBox, -1);
  1197.                SendMessage(pVLBox->hwndList, LB_SETCURSEL, 0, 0L);
  1198.                SetFocus(pVLBox->hwndList);
  1199.                SetSelectedItem(pVLBox);
  1200.  
  1201.                //
  1202.                // Update the Screen
  1203.                //
  1204.                vlbRedrawOn(pVLBox);
  1205.         }
  1206.         else {
  1207.                //
  1208.                // Current selction is visible
  1209.                //
  1210.  
  1211.                //
  1212.                // Where is it ????
  1213.                //
  1214.                if ( lSelected == (pVLBox->nLines-1) ) {
  1215.                   //
  1216.                   // At the bottom... put selection at top
  1217.                   //
  1218.                   SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  1219.                               0, 0L);
  1220.                   SetFocus(pVLBox->hwndList);
  1221.                   SetSelectedItem(pVLBox);
  1222.                }
  1223.                else if ( (int)lSelected ==  0L) {
  1224.                   //
  1225.                   // At the TOP ... Scroll up 1 page less 1 line
  1226.                   //                  Put selection at top
  1227.                   //
  1228.                   VLBScrollUpPage(pVLBox, -1);
  1229.                   SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  1230.                               0, 0L);
  1231.                   SetFocus(pVLBox->hwndList);
  1232.                   SetSelectedItem(pVLBox);
  1233.                }
  1234.                else {
  1235.                    //
  1236.                    // In the middle ... scroll up 1 page less
  1237.                    //                   the number of lines
  1238.                    //                   the selection is away
  1239.                    //                   from the top
  1240.                    //
  1241.                    //                   Put selection at top
  1242.                    //
  1243.                    int nAdjust;
  1244.                    nAdjust = -1 * ((int)lSelected + 1 );
  1245.                    VLBScrollUpPage(pVLBox, nAdjust);
  1246.                    SendMessage(pVLBox->hwndList, LB_SETCURSEL,
  1247.                                0, 0L);
  1248.                    SetFocus(pVLBox->hwndList);
  1249.                    SetSelectedItem(pVLBox);
  1250.                }
  1251.         }
  1252.     }
  1253. }
  1254.