home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / VISUAL_B / REFERENC / LEARNVBX / OLDMULTI.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-28  |  10.4 KB  |  413 lines

  1. /**
  2. .File
  3.     Multi.c
  4. .Name
  5.     MultiSelect ListBox for Visual Basic
  6. .Author
  7.     Dan Rogers
  8. .What
  9.     custom visual basic control for multi select list box
  10. .How
  11.     Read-On, man...
  12. **/
  13.  
  14. #define  NOCOMM
  15. #include <windows.h>
  16.  
  17. #include <vbapi.h>
  18.  
  19. #define  CTL_DATA           // To declare static data in multi.h
  20. #include "multi.h"
  21.  
  22.  
  23. /*
  24. Standard Error Values
  25. */
  26. #define ERR_None              0
  27. #define ERR_InvPropVal      380     /* Error$(380) = "Invalid property value" */
  28.  
  29.  
  30. /* Local Prototypes */
  31.  
  32.  
  33. /* Event Procedure Parameter Profiles */
  34. typedef struct tagPARAMS3  /* used in fireback */
  35. {
  36.     LPLONG  Value;
  37.     LPINT   Offset;
  38.     HLSTR   ClickString;
  39.     LPVOID  Index;          /* Reserve space for index parameter to array ctl */
  40. } PARAMS3;
  41.  
  42. typedef struct tagPARAMS4    /* used in click */
  43. {
  44.     LPLONG  Value;
  45.     LPINT   Selected;
  46.     LPINT   Offset;
  47.     HLSTR   ClickString;
  48.     LPVOID  Index;          /* Reserve space for index parameter to array ctl */
  49. } PARAMS4;
  50.  
  51.  
  52. /****************************************/
  53. /* MultiSelectListBox Control Procedure */
  54. /****************************************/
  55. LONG FAR PASCAL _export MultiCtlProc
  56. (
  57.     HCTL        hctl,
  58.     HWND        hwnd,
  59.     USHORT      msg,
  60.     USHORT      wp,
  61.     LONG        lp
  62. )
  63. {
  64.     LONG        lResult;
  65.     LPLONG      longer;
  66.     LONG        args;
  67.     LONG        index;
  68.     PARAMS4 params4;
  69.     PARAMS3 params3;
  70.     HSZ         item;
  71.     LPSTR       string;
  72.     LONG        ret;
  73.     int len;
  74.     USHORT newlen;
  75.     ERR    err;
  76.     int i;
  77.     WPARAM offset;
  78.     int selected;
  79.     LONG dataval;
  80.     LPSTR  lpstr;
  81.     int oldindex;
  82.     char buffer[132];
  83.     
  84.  
  85.     /* Message pre-processing */
  86.     switch (msg)
  87.     {
  88.     
  89.     /* simple click processing  */
  90.     case WM_LBUTTONUP:
  91.     case WM_LBUTTONDBLCLK:
  92.  
  93.         /* make sure something is there (empty list box no go)*/
  94.         len = LOWORD(SendMessage(hwnd, LB_GETCOUNT, (WPARAM)0, 0L));
  95.         if ( len <= 0 )
  96.             return(0);
  97.         len = LOWORD(SendMessage(hwnd, LB_GETSELCOUNT, 0, 0L));
  98.         if (len > 1)
  99.             return(0);
  100.             
  101.         /* What is the caret index, just clicked, has to be here */
  102.         offset = LOWORD(SendMessage (hwnd, LB_GETCARETINDEX, (WPARAM) 0,  0L));
  103.         oldindex = offset;
  104.             
  105.         /* determine if the selection is currently selected */
  106.         selected = (int)SendMessage(hwnd, LB_GETSEL, (WPARAM) offset, 0L);
  107.         if (selected > 0)
  108.             selected = -1;
  109.  
  110.         /* how long is it (would like to allocate, but for now 132 limit) */
  111.         len = LOWORD(SendMessage(hwnd, LB_GETTEXTLEN, (WPARAM)offset, 0L));
  112.         if ( len > 131 || len <= 0 )
  113.             return (0);
  114.         lpstr = buffer;
  115.             
  116.         /* go and get it into the buffer */
  117.         len = (int)SendMessage(hwnd, LB_GETTEXT, (WPARAM) offset, (LPARAM)(LPCSTR) lpstr );
  118.         if ( len > 131 || len <= 0)
  119.             return(0);
  120.         dataval = SendMessage(hwnd, LB_GETITEMDATA, (WPARAM)offset, 0L);
  121.         if (dataval == LB_ERR)
  122.             dataval = -1;
  123.         buffer[len] = (char)NULL;
  124.             
  125.         /* make a VB string out of it */
  126.         newlen = (USHORT) len;
  127.         params4.ClickString = VBCreateHlstr((LPVOID)lpstr, (USHORT)newlen);
  128.         if ( params4.ClickString == (HLSTR) NULL)
  129.             return (380);
  130.         params4.Offset = &offset;
  131.         params4.Selected = &selected;
  132.         params4.Value = &dataval;    
  133.             
  134.         err = VBFireEvent(hctl, EVENT_MULTI_CLICK, ¶ms4);
  135.             
  136.         /* user can modify the string, value in the function */
  137.         /* Not allowed to null it out.  */
  138.         if (!err)
  139.         {
  140.             if (params4.ClickString == (HLSTR) NULL)
  141.                 return (380);
  142.             len = VBGetHlstrLen(params4.ClickString);
  143.             if (len > 131)
  144.                 return(380);
  145.             lpstr = VBDerefHlstr(params4.ClickString);
  146.             if (lpstr)
  147.             {       string = buffer;
  148.                 for ( i = 0; i < len; i ++ )
  149.                 {
  150.                     *(string+i) = *(lpstr + i);
  151.                     if ( *(string + i) == (char) NULL)
  152.                         break;
  153.                 }
  154.             }
  155.             else
  156.                 *buffer = (char)NULL;
  157.  
  158.             buffer[len] = (char)NULL;
  159.             SendMessage (hwnd, WM_SETREDRAW, (WPARAM)0, (LPARAM)0);
  160.             SendMessage ( hwnd, LB_DELETESTRING, (WPARAM)oldindex, (LPARAM)0);
  161.             
  162.             if ( *buffer != (char)NULL)
  163.             {        
  164.                 SendMessage( hwnd, LB_INSERTSTRING, (WPARAM) oldindex, (LPARAM) string);
  165.                 SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM) oldindex, (LPARAM) 0);
  166.                 if ( selected )
  167.                     SendMessage(hwnd, LB_SETSEL, (WPARAM)TRUE, MAKELPARAM(oldindex, 0));
  168.             }
  169.             SendMessage(hwnd, WM_SETREDRAW, (WPARAM)1, (LPARAM)0);
  170.         } 
  171.         if ( params4.ClickString != NULL )
  172.             VBDestroyHlstr(params4.ClickString);
  173.     
  174.         break;
  175.  
  176.     case VBM_SETPROPERTY:
  177.         /* add property setting here for the properties that            */
  178.         /* require support of messages (list, sellist, selcnt, listcnt) */
  179.         switch (wp)
  180.         {
  181.             case IPROP_MULTI_SELCOUNT:
  182.             /* may zero the selected list */
  183.             if ( (int)lp )
  184.                 return(380);
  185.             SendMessage(hwnd, LB_SETSEL, 0, MAKELPARAM(-1,0));
  186.             break;
  187.             
  188.             case IPROP_MULTI_LISTCOUNT:
  189.             /* may zero the selected list */
  190.             if ( (int)lp )
  191.                 return(380);
  192.             SendMessage(hwnd, LB_RESETCONTENT, 0, 0L);
  193.             break;
  194.  
  195.             case IPROP_MULTI_FIREBACK:
  196.             /* setting this property causes the SelectDump event */
  197.             /* to be fired for each occurence of selected items  */
  198.             {
  199.             int count;
  200.             long dval;
  201.             int loop;
  202.             int top, len;
  203.             int hunt;                       
  204.             HGLOBAL hg;
  205.  
  206.             count = LOWORD(SendMessage(hwnd, LB_GETSELCOUNT, 0, 0L));
  207.             if ( count == 0 )
  208.                 return(0);
  209.             params3.Value = &dval;
  210.             params3.Offset = &loop;
  211.             for (i = 1; i <= count; i++)
  212.             {
  213.                 top = LOWORD(SendMessage(hwnd, LB_GETCOUNT, 0, 0L));
  214.                 hunt = 0;
  215.                 if (i > top)
  216.                     return(0);
  217.                 for ( loop = 0; loop < top; loop ++)
  218.                 {
  219.                     len = LOWORD(SendMessage(hwnd, LB_GETSEL, (WPARAM)loop, 0L));
  220.                     if ( len > 0 )
  221.                     {
  222.                         hunt ++;
  223.                         if (hunt == i )
  224.                             break;
  225.                     }
  226.                 }
  227.                 if (loop >= top)
  228.                     return(382); 
  229.                 len = LOWORD(SendMessage(hwnd, LB_GETTEXTLEN, (WPARAM)loop, 0L));
  230.                 hg = GlobalAlloc(GMEM_FIXED, (DWORD)(count + 1));
  231.                 if (!hg)
  232.                     return(383);
  233.                 lpstr = (LPSTR) GlobalLock(hg);
  234.                 SendMessage(hwnd, LB_GETTEXT, (WPARAM)loop, (LONG) lpstr);
  235.                 params3.ClickString = VBCreateHlstr((LPVOID)lpstr, (USHORT)len);
  236.                 if (params3.ClickString == NULL)
  237.                     return(384);
  238.                 dval = SendMessage(hwnd, LB_GETITEMDATA, (WPARAM)loop, 0L);
  239.                 err = VBFireEvent(hctl, EVENT_MULTI_SELECTDUMP, ¶ms3);
  240.                 if (params3.ClickString != NULL)
  241.                     VBDestroyHlstr(params3.ClickString);
  242.                 GlobalUnlock(hg);
  243.                 GlobalFree (hg); 
  244.             }
  245.             }
  246.             break;
  247.  
  248.             case IPROP_MULTI_LIST:
  249.             /* can be used as additem alternative */
  250.             /* this string array property uses no actual     */
  251.             /* data, but rather stores items in the list box */
  252.             {
  253.             int count;
  254.             int i;
  255.             LPDATASTRUCT lpDs = (LPDATASTRUCT)lp;
  256.  
  257.             i = (int)lpDs->index[0].data;
  258.             count = LOWORD(SendMessage(hwnd,LB_GETCOUNT, 0, 0L));
  259.             if (i > count || i < 0 )
  260.                 i = -1;
  261.             count = 0;
  262.             i = (int)SendMessage(hwnd, LB_INSERTSTRING, (WPARAM)i, (LONG) (lpDs->data));
  263.             if (i == LB_ERR || i == LB_ERRSPACE)
  264.                 return ( 380 );
  265.             SendMessage(hwnd, LB_SETITEMDATA, (WPARAM)i, (LONG)(LPLONG)&count);
  266.             }
  267.             break;
  268.         }
  269.         break;
  270.  
  271.     case VBM_GETPROPERTY:
  272.         switch(wp)
  273.         {
  274.         case IPROP_MULTI_SELCOUNT:
  275.             *((int far *)lp) = (int)SendMessage(hwnd, LB_GETSELCOUNT, 0, 0L);
  276.             break;
  277.  
  278.         case IPROP_MULTI_LISTCOUNT:
  279.             *((int far *)lp) = (int)SendMessage(hwnd, LB_GETCOUNT, 0, 0L);
  280.             break;
  281.  
  282.         case IPROP_MULTI_LIST:
  283.             {
  284.             long count;
  285.             LONG i;
  286.             HGLOBAL hg;
  287.             LPDATASTRUCT lpDs = (LPDATASTRUCT)lp;
  288.             i = lpDs->index[0].data;
  289.             count = SendMessage(hwnd,LB_GETCOUNT, 0, 0L);
  290.             if (i > count || i < 0 )
  291.                 return(381);
  292.             count = SendMessage(hwnd, LB_GETTEXTLEN, (WPARAM)i, 0L);
  293.             hg = GlobalAlloc(GMEM_FIXED, (DWORD)(count + 1));
  294.             if (!hg)
  295.                 return(380);
  296.             lpstr = (LPSTR) GlobalLock(hg);
  297.             SendMessage(hwnd, LB_GETTEXT, (WPARAM)i, (LONG) lpstr);
  298.             lpDs->data = (LONG)VBCreateHsz((_segment)hctl, lpstr);
  299.             GlobalUnlock(hg);
  300.             GlobalFree (hg); 
  301.             break;
  302.             }
  303.         
  304.         case IPROP_MULTI_SELLIST:
  305.             {
  306.             int count;
  307.             int loop, i;
  308.             int top, len;
  309.             int hunt;                       
  310.             HGLOBAL hg;
  311.             LPDATASTRUCT lpDs = (LPDATASTRUCT)lp;
  312.             i = (int)lpDs->index[0].data;
  313.             count = LOWORD(SendMessage(hwnd,LB_GETSELCOUNT, 0, 0L));
  314.             if (i > count || i < 1 )
  315.                 return(381);
  316.             top = LOWORD(SendMessage(hwnd, LB_GETCOUNT, 0, 0L));
  317.             hunt = 0;
  318.             for ( loop = 0; loop < top; loop ++)
  319.             {
  320.                 len = LOWORD(SendMessage(hwnd, LB_GETSEL, (WPARAM)loop, 0L));
  321.                 if ( len )
  322.                 {
  323.                     hunt ++;
  324.                     if (hunt == i )
  325.                         break;
  326.                 }
  327.             }
  328.             if (loop == top)
  329.                 return(381); 
  330.             len = LOWORD(SendMessage(hwnd, LB_GETTEXTLEN, (WPARAM)loop, 0L));
  331.             hg = GlobalAlloc(GMEM_FIXED, (DWORD)(count + 1));
  332.             if (!hg)
  333.                 return(380);
  334.             lpstr = (LPSTR) GlobalLock(hg);
  335.             SendMessage(hwnd, LB_GETTEXT, (WPARAM)loop, (LONG) lpstr);
  336.             lpDs->data = (LONG)VBCreateHsz((_segment)hctl, lpstr);
  337.             GlobalUnlock(hg);
  338.             GlobalFree (hg); 
  339.             break;
  340.             }
  341.         }
  342.         break;
  343.  
  344.     /* code to handle the optional methods for controls... */
  345.     case VBM_METHOD:
  346.         switch ( wp )
  347.         {
  348.         /* AddItem method: add item to list */
  349.         case METH_ADDITEM:
  350.             longer = (LPLONG )lp;
  351.             args = longer[0];
  352.             item = (HSZ)longer[1];
  353.             if (args > 2 )
  354.                 index = longer[2];
  355.             else
  356.                 index = -1;
  357.             string = VBDerefHsz(item);
  358.             
  359.             /* later on, if sorted property is set, use      */
  360.             /* the addstring method - honors sorted property */
  361.             ret = SendMessage ( hwnd, LB_INSERTSTRING, (WPARAM)index, (LPARAM)(LPCSTR)string);
  362.             if ( ret == LB_ERR || ret == LB_ERRSPACE )
  363.                 return (ret);
  364.             index = ret;
  365.             ret = SendMessage( hwnd, LB_SETITEMDATA, (WPARAM)index, 0L);
  366.             return (0);
  367.             
  368.         /* Method to remove specific item from the list */
  369.         case METH_REMOVEITEM:
  370.             longer = (LPLONG )lp;
  371.             args = longer[0];
  372.             index = longer[1];
  373.             ret = SendMessage ( hwnd, LB_DELETESTRING, (WPARAM)index, (LPARAM)0);
  374.             return (0);
  375.             
  376.             default:
  377.             break;
  378.         }
  379.         break;
  380.  
  381.     case VBN_DRAWITEM:
  382.         return 0;
  383.     
  384.     }
  385.  
  386.     /* Default processing: Pass thru to let VB handle it - talks to control */
  387.     lResult = VBDefControlProc(hctl, hwnd, msg, wp, lp);
  388.  
  389.     /* could not get VBN_COMMAND: case VBN_CLICKED   */
  390.     /* to work properly as reflection of WM_COMMAND  */
  391.     /* sent by control.  Implemented click as a post */
  392.     /* control class processing job based upon the   */
  393.     /* value of the original message (somehow the    */
  394.     /* msg arg is altered after the default p call   */
  395.     /*switch(oldmsg)
  396.     {
  397.  
  398.         default:
  399.         break;
  400.     
  401.     } */
  402.     /*Message post-processing:*/
  403.     
  404.     switch (msg)
  405.     {
  406.     case WM_DESTROY:
  407.         break;
  408.  
  409.     }
  410.  
  411.     return lResult;
  412. }
  413.