home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 11.ddi / OWLSRC.PAK / LISTBOX.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  19.8 KB  |  882 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1993 by Borland International
  3. //   source\owl\listbox.cpp
  4. //   Implementation of class TListBox and TlistBoxData.
  5. //----------------------------------------------------------------------------
  6. #pragma hdrignore SECTION
  7. #include <owl\owlpch.h>
  8. #include <owl\listbox.h>
  9. #include <stdlib.h>
  10. #include <cstring.h>
  11.  
  12. #if !defined(SECTION) || SECTION == 1
  13.  
  14. #define MULTIPLESEL    (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)
  15.  
  16. //
  17. // TListBoxData constructor
  18. //
  19. TListBoxData::TListBoxData()
  20.  : Strings(10, 0, 10),
  21.    ItemDatas(10, 0, 10),
  22.    SelIndices(1, 0, 10)
  23. {
  24. }
  25.  
  26. //
  27. // TListBoxData destructor
  28. //
  29. TListBoxData::~TListBoxData()
  30. {
  31. }
  32.  
  33. //
  34. // adds "str" to "Strings"
  35. //
  36. // if "isSelected" is TRUE, marks it as selected
  37. //
  38. void
  39. TListBoxData::AddString(const char* str, BOOL isSelected)
  40. {
  41.   Strings.Add(str);
  42.   if (isSelected)
  43.     Select(Strings.GetItemsInContainer()-1);
  44. }
  45.  
  46. //
  47. // adds str and associated item data to strings and datas
  48. //
  49. void
  50. TListBoxData::AddStringItem(const char* str, DWORD itemData, BOOL isSelected)
  51. {
  52.   ItemDatas.Add(itemData);
  53.   AddString(str, isSelected);
  54. }
  55.  
  56. //
  57. // selects an item at a given index.
  58. //
  59. void
  60. TListBoxData::Select(int index)
  61. {
  62.   if (index != LB_ERR)
  63.     SelIndices.Add(index);
  64. }
  65.  
  66. //
  67. // adds "str" to selection lists if it is in Strings
  68. //
  69. void
  70. TListBoxData::SelectString(const char far* str)
  71. {
  72.   for (int i = 0; i < Strings.GetItemsInContainer(); i++)
  73.     if (strcmp(Strings[i].c_str(), str) == 0) {
  74.       Select(i);
  75.       break;
  76.     }
  77. }
  78.  
  79. //
  80. // returns the length of the string at the passed selection index
  81. // excluding the terminating 0
  82. //
  83. int
  84. TListBoxData::GetSelStringLength(int index) const
  85. {
  86.   if (index >= 0 && index < GetSelCount())
  87.     return Strings[SelIndices[index]].length();
  88.   return -1;
  89. }
  90.  
  91. //
  92. // copies the string at the passed selection index into buffer
  93. //
  94. // bufferSize includes the terminating 0
  95. //
  96. void
  97. TListBoxData::GetSelString(char far* buffer, int bufferSize, int index) const
  98. {
  99.   if (bufferSize > 0) {
  100.     if (index < 0 || index >= GetSelCount())
  101.       *buffer = 0;
  102.  
  103.     else {
  104.       strncpy(buffer, Strings[SelIndices[index]].c_str(), bufferSize-1);
  105.       buffer[bufferSize - 1] = 0;
  106.     }
  107.   }
  108. }
  109.  
  110. //
  111. // copies the string at the passed index in SelStrings into str
  112. //
  113. void
  114. TListBoxData::GetSelString(string& str, int index) const
  115. {
  116.   if (index >= 0 && index < GetSelCount())
  117.     str = Strings[SelIndices[index]];
  118.   else
  119.     str = "";
  120. }
  121.  
  122. TStringArray::TStringArray( int upper, int lower, int delta ) :
  123.     Data( upper, lower, delta )
  124. {
  125. }
  126.  
  127. int TStringArray::LowerBound() const
  128. {
  129.     return Data.LowerBound();
  130. }
  131.  
  132. int TStringArray::UpperBound() const
  133. {
  134.     return Data.UpperBound();
  135. }
  136.  
  137. unsigned TStringArray::ArraySize() const
  138. {
  139.     return Data.ArraySize();
  140. }
  141.  
  142. int TStringArray::IsFull() const
  143. {
  144.     return Data.IsFull();
  145. }
  146.  
  147. int TStringArray::IsEmpty() const
  148. {
  149.     return Data.IsEmpty();
  150. }
  151.  
  152. unsigned TStringArray::GetItemsInContainer() const
  153. {
  154.     return Data.GetItemsInContainer();
  155. }
  156.  
  157. int TStringArray::Add( const string & t )
  158. {
  159.     return Data.Add(t);
  160. }
  161.  
  162. int TStringArray::Detach( const string & t )
  163. {
  164.     return Data.Detach(t);
  165. }
  166.  
  167. int TStringArray::Detach( int loc )
  168. {
  169.     return Data.Detach( loc );
  170. }
  171.  
  172. int TStringArray::Destroy( const string & t )
  173. {
  174.     return Detach(t);
  175. }
  176.  
  177. int TStringArray::Destroy( int loc )
  178. {
  179.     return Detach(loc);
  180. }
  181.  
  182. int TStringArray::HasMember( const string & t ) const
  183. {
  184.     return Data.HasMember(t);
  185. }
  186.  
  187. int TStringArray::Find( const string & t ) const
  188. {
  189.     return Data.Find(t);
  190. }
  191.  
  192. string & TStringArray::operator []( int loc )
  193. {
  194.     return Data[loc];
  195. }
  196.  
  197. string & TStringArray::operator []( int loc ) const
  198. {
  199.     return Data[loc];
  200. }
  201.  
  202. void TStringArray::ForEach( IterFunc iter, void *args )
  203. {
  204.     Data.ForEach( iter, args );
  205. }
  206.  
  207. string *TStringArray::FirstThat( CondFunc cond, void *args ) const
  208. {
  209.     return Data.FirstThat( cond, args );
  210. }
  211.  
  212. string *TStringArray::LastThat( CondFunc cond, void *args ) const
  213. {
  214.     return Data.LastThat( cond, args );
  215. }
  216.  
  217. void TStringArray::Flush()
  218. {
  219.     Data.Flush();
  220. }
  221.  
  222. TIntArray::TIntArray( int upper, int lower, int delta ) :
  223.     Data( upper, lower, delta )
  224. {
  225. }
  226.  
  227. int TIntArray::LowerBound() const
  228. {
  229.     return Data.LowerBound();
  230. }
  231.  
  232. int TIntArray::UpperBound() const
  233. {
  234.     return Data.UpperBound();
  235. }
  236.  
  237. unsigned TIntArray::ArraySize() const
  238. {
  239.     return Data.ArraySize();
  240. }
  241.  
  242. int TIntArray::IsFull() const
  243. {
  244.     return Data.IsFull();
  245. }
  246.  
  247. int TIntArray::IsEmpty() const
  248. {
  249.     return Data.IsEmpty();
  250. }
  251.  
  252. unsigned TIntArray::GetItemsInContainer() const
  253. {
  254.     return Data.GetItemsInContainer();
  255. }
  256.  
  257. int TIntArray::Add( const TInt & t )
  258. {
  259.     return Data.Add(t);
  260. }
  261.  
  262. int TIntArray::Detach( const TInt & t )
  263. {
  264.     return Data.Detach(t);
  265. }
  266.  
  267. int TIntArray::Detach( int loc )
  268. {
  269.     return Data.Detach( loc );
  270. }
  271.  
  272. int TIntArray::Destroy( const TInt & t )
  273. {
  274.     return Detach(t);
  275. }
  276.  
  277. int TIntArray::Destroy( int loc )
  278. {
  279.     return Detach(loc);
  280. }
  281.  
  282. int TIntArray::HasMember( const TInt & t ) const
  283. {
  284.     return Data.HasMember(t);
  285. }
  286.  
  287. int TIntArray::Find( const TInt & t ) const
  288. {
  289.     return Data.Find(t);
  290. }
  291.  
  292. TInt & TIntArray::operator []( int loc )
  293. {
  294.     return Data[loc];
  295. }
  296.  
  297. TInt & TIntArray::operator []( int loc ) const
  298. {
  299.     return Data[loc];
  300. }
  301.  
  302. void TIntArray::ForEach( IterFunc iter, void *args )
  303. {
  304.     Data.ForEach( iter, args );
  305. }
  306.  
  307. TInt *TIntArray::FirstThat( CondFunc cond, void *args ) const
  308. {
  309.     return Data.FirstThat( cond, args );
  310. }
  311.  
  312. TInt *TIntArray::LastThat( CondFunc cond, void *args ) const
  313. {
  314.     return Data.LastThat( cond, args );
  315. }
  316.  
  317. void TIntArray::Flush()
  318. {
  319.     Data.Flush();
  320. }
  321.  
  322. TDwordArray::TDwordArray( int upper, int lower, int delta ) :
  323.     Data( upper, lower, delta )
  324. {
  325. }
  326.  
  327. int TDwordArray::LowerBound() const
  328. {
  329.     return Data.LowerBound();
  330. }
  331.  
  332. int TDwordArray::UpperBound() const
  333. {
  334.     return Data.UpperBound();
  335. }
  336.  
  337. unsigned TDwordArray::ArraySize() const
  338. {
  339.     return Data.ArraySize();
  340. }
  341.  
  342. int TDwordArray::IsFull() const
  343. {
  344.     return Data.IsFull();
  345. }
  346.  
  347. int TDwordArray::IsEmpty() const
  348. {
  349.     return Data.IsEmpty();
  350. }
  351.  
  352. unsigned TDwordArray::GetItemsInContainer() const
  353. {
  354.     return Data.GetItemsInContainer();
  355. }
  356.  
  357. int TDwordArray::Add( const DWORD & t )
  358. {
  359.     return Data.Add(t);
  360. }
  361.  
  362. int TDwordArray::Detach( const DWORD & t )
  363. {
  364.     return Data.Detach(t);
  365. }
  366.  
  367. int TDwordArray::Detach( int loc )
  368. {
  369.     return Data.Detach( loc );
  370. }
  371.  
  372. int TDwordArray::Destroy( const DWORD & t )
  373. {
  374.     return Detach(t);
  375. }
  376.  
  377. int TDwordArray::Destroy( int loc )
  378. {
  379.     return Detach(loc);
  380. }
  381.  
  382. int TDwordArray::HasMember( const DWORD & t ) const
  383. {
  384.     return Data.HasMember(t);
  385. }
  386.  
  387. int TDwordArray::Find( const DWORD & t ) const
  388. {
  389.     return Data.Find(t);
  390. }
  391.  
  392. DWORD & TDwordArray::operator []( int loc )
  393. {
  394.     return Data[loc];
  395. }
  396.  
  397. DWORD & TDwordArray::operator []( int loc ) const
  398. {
  399.     return Data[loc];
  400. }
  401.  
  402. void TDwordArray::ForEach( IterFunc iter, void *args )
  403. {
  404.     Data.ForEach( iter, args );
  405. }
  406.  
  407. DWORD *TDwordArray::FirstThat( CondFunc cond, void *args ) const
  408. {
  409.     return Data.FirstThat( cond, args );
  410. }
  411.  
  412. DWORD *TDwordArray::LastThat( CondFunc cond, void *args ) const
  413. {
  414.     return Data.LastThat( cond, args );
  415. }
  416.  
  417. void TDwordArray::Flush()
  418. {
  419.     Data.Flush();
  420. }
  421.  
  422. //----------------------------------------------------------------------------
  423.  
  424. //
  425. // constructor for TListBox
  426. //
  427. // initializes its data fields using parameters passed and default values
  428. //
  429. // by default, an MS-Windows listbox associated with the TListBox will:
  430. //   - be visible upon creation
  431. //   - have a border and a vertical scrollbar
  432. //   - maintain entries in alphabetical order
  433. //   - notify its parent when a selection is made
  434. //
  435. TListBox::TListBox(TWindow*   parent,
  436.                    int        id,
  437.                    int x, int y, int w, int h,
  438.                    TModule*   module)
  439.   : TControl(parent, id, 0, x, y, w, h, module)
  440. {
  441.   Attr.Style |= LBS_STANDARD;
  442. }
  443.  
  444. TListBox::TListBox(TWindow*   parent,
  445.                    int        resourceId,
  446.                    TModule*   module)
  447.   : TControl(parent, resourceId, module)
  448. {
  449. }
  450.  
  451. char far*
  452. TListBox::GetClassName()
  453. {
  454.   return "LISTBOX";
  455. }
  456.  
  457. //
  458. // transfers state information for a TListBox
  459. //
  460. // transfers the items and selection of the list to or from a transfer
  461. // buffer if tdSetData or tdGetData, respectively, is passed as the
  462. // direction
  463. //
  464. // buffer should point to a TListBoxData which points to the data to be
  465. // transferred
  466. //
  467. // Transfer returns the size of TListBoxData
  468. //
  469. // to retrieve the size without transferring data, pass tdSizeData as the
  470. // direction
  471. //
  472. UINT
  473. TListBox::Transfer(void* buffer, TTransferDirection direction)
  474. {
  475.   long           style = GetWindowLong(GWL_STYLE);
  476.   TListBoxData*  listBoxData = (TListBoxData*)buffer;
  477.  
  478.   if (direction == tdGetData) {
  479.     //
  480.     // first, clear out Strings array and fill with contents of list box
  481.     //
  482.     listBoxData->Clear();
  483.  
  484.     //
  485.     // pre-calculate max string length so that one big buffer can be used
  486.     //
  487.     int  count = GetCount();
  488.     int  maxStrLen = 0;
  489.     for (int i = 0; i < count; i++) {
  490.       int  strLen = GetStringLen(i);
  491.       if (strLen > maxStrLen)
  492.         maxStrLen = strLen;
  493.     }
  494.     //
  495.     // Get each string and item data in the listbox & add to listboxdata
  496.     //
  497.     char*  tmpStr = new char[maxStrLen+1];
  498.     for (i = 0; i < GetCount(); i++) {
  499.       GetString(tmpStr, i);
  500.       listBoxData->AddStringItem(tmpStr, GetItemData(i), FALSE);
  501.     }
  502.     delete tmpStr;
  503.  
  504.     //
  505.     // update transfer data with new selected item(s)
  506.     //
  507.     listBoxData->ResetSelections();
  508.  
  509.     if (!(style & MULTIPLESEL)) {
  510.       //
  511.       // single selection
  512.       //
  513.       listBoxData->Select(GetSelIndex());
  514.  
  515.     } else {
  516.       //
  517.       // multiple selection
  518.       //
  519.       int  selCount = GetSelCount();
  520.       if (selCount > 0) {
  521.         int*  selections = new int[selCount];
  522.  
  523.         GetSelIndexes(selections, selCount);
  524.  
  525.         // Select each item by index
  526.         //
  527.         for (int selIndex = 0; selIndex < selCount; selIndex++)
  528.           listBoxData->Select(selections[selIndex]);
  529.  
  530.         delete selections;
  531.       }
  532.     }
  533.  
  534.   } else if (direction == tdSetData) {
  535.     ClearList();
  536.  
  537.     //
  538.     // add each string, item data and selections in listBoxData to list box
  539.     //
  540.     int  selCount = listBoxData->GetSelCount();  // for multi selection
  541.     int  selIndex;                               // for single selection
  542.     for (int i = 0; i < listBoxData->GetStrings().GetItemsInContainer(); i++) {
  543.       int index = AddString(listBoxData->GetStrings()[i].c_str());
  544.       SetItemData(index, listBoxData->GetItemDatas()[i]);
  545.       if (style & MULTIPLESEL) {
  546.         for (int j = 0; j < selCount; j++)
  547.           if (listBoxData->GetSelIndices()[j] == i) {
  548.             SetSel(index, TRUE);
  549.             break;
  550.           }
  551.       } else {
  552.         if (listBoxData->GetSelIndices()[0] == i)
  553.           selIndex = index;
  554.         else
  555.           if (index <= selIndex)
  556.             selIndex++;
  557.       }
  558.     }
  559.     if (!(style & MULTIPLESEL))
  560.       SetSelIndex(selIndex);
  561.   }
  562.   
  563.   return sizeof(TListBoxData);
  564. }
  565.  
  566. //
  567. // returns the index of the first string in the associated listbox
  568. // which is the same as the passed string
  569. //
  570. // searches for a match beginning at the passed indexStart
  571. //
  572. // if a match is not found after the last string has been compared,
  573. // the search continues from the beginning of the list until a match
  574. // is found or until the list has been completely traversed
  575. //
  576. // searches from beginning of list when -1 is passed as the index
  577. //
  578. // returns the index of the selected string; a negative value is returned
  579. // if an error occurs
  580. //
  581. // for single or multiple-selection list boxes
  582. //
  583. int
  584. TListBox::FindExactString(const char far* findStr, int indexStart) const
  585. {
  586.   BOOL  found = FALSE;
  587.   int   firstMatch = indexStart = FindString(findStr, indexStart);
  588.   do {
  589.     if (indexStart > -1) {
  590.       char*  tmpStr = new char[GetStringLen(indexStart) + 1];
  591.  
  592.       GetString(tmpStr, indexStart);
  593.  
  594.       if (strcmp(tmpStr, findStr) == 0)
  595.         found = TRUE;
  596.  
  597.       else
  598.         indexStart = FindString(findStr, indexStart);
  599.  
  600.       delete tmpStr;
  601.     }
  602.   } while (!found && indexStart != firstMatch);
  603.  
  604.   return found ? indexStart : -1;
  605. }
  606.  
  607. //
  608. // for use with single-selection list boxes (and combo boxes)
  609. //
  610. // retrieves the text of the string which is selected in the associated
  611. // listbox
  612. //
  613. // returns the number of characters copied; -1 is returned if no string
  614. // is selected or this is a multiple-selection list box
  615. //
  616. // since the Windows function is not passed a size parameter, we have to
  617. // allocate a string to hold the largest string (gotten from a query), and
  618. // copy a part of it
  619. //
  620. int
  621. TListBox::GetSelString(char far* str, int maxChars) const
  622. {
  623.   int  index = GetSelIndex();
  624.  
  625.   if (index > -1) {
  626.     int  length = GetStringLen(index);
  627.  
  628.     if (maxChars >= length)
  629.       return GetString(str, index);
  630.  
  631.     else {
  632.       char*  tmpStr = new char[length + 1];
  633.  
  634.       if (tmpStr) {
  635.         GetString(tmpStr, index);
  636.         strncpy(str, tmpStr, maxChars);
  637.         delete tmpStr;
  638.         return maxChars;
  639.       }
  640.     }
  641.   }
  642.   return -1;
  643. }
  644.  
  645. //
  646. // returns the number of selected items in the list box. For
  647. // multiple-selection list boxes only
  648. //
  649. int
  650. TListBox::GetSelCount() const
  651. {
  652.   if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
  653.     return GetSelIndex() < 0 ? 0 : 1;
  654.  
  655.   //
  656.   // multiple-selection list box
  657.   //
  658.   return (int)CONST_CAST(TListBox*,this)->HandleMessage(LB_GETSELCOUNT);
  659. }
  660.  
  661. //
  662. // retrieves the text of the strings which are selected in the
  663. // associated listbox
  664. //
  665. // returns the number of items put into Strings.  -1 is returned if this is
  666. // not a multiple-selection list box
  667. //
  668. // since the Windows function is not passed a size parameter, we have to
  669. // allocate a string to hold the largest string (gotten from a query), and
  670. // copy a part of it
  671. //
  672. // only for use with multiple-selection list boxes
  673. //
  674. int
  675. TListBox::GetSelStrings(char far** strs, int maxCount, int maxChars) const
  676. {
  677.   if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
  678.     return -1;
  679.  
  680.   int i = GetSelCount();
  681.  
  682.   if (i < maxCount)
  683.     maxCount = i;
  684.  
  685.   if (maxCount > 0) {
  686.     int*  selections = new int[maxCount];
  687.  
  688.     GetSelIndexes(selections, maxCount);
  689.  
  690.     for (int selIndex = 0; selIndex < maxCount; selIndex++) {
  691.       int  tmpStrLen = GetStringLen(selections[selIndex]);
  692.  
  693.       if (maxChars >= tmpStrLen)
  694.         GetString(strs[selIndex], selections[selIndex]);
  695.  
  696.       else {
  697.         char*  tmpStr = new char[tmpStrLen+1];
  698.  
  699.         if (tmpStr) {
  700.           GetString(tmpStr, selections[selIndex]);
  701.           strncpy(strs[selIndex], tmpStr, maxChars);
  702.           delete tmpStr;
  703.         }
  704.       }
  705.     }
  706.     delete selections;
  707.   }
  708.   return maxCount;
  709. }
  710.  
  711. //
  712. // selects the first string in the associated listbox following the
  713. // passed index which begins with the passed string
  714. //
  715. // searches for a match beginning at the passed Index. if a match is not
  716. // found after the last string has been compared, the search continues
  717. // from the beginning of the list until a match is found or until the list
  718. // has been completely traversed
  719. //
  720. // searches from beginning of list when -1 is passed as the index
  721. //
  722. // returns the index of the selected string. a negative value is returned
  723. // if an error occurs
  724. //
  725. // only for single-selection list boxes
  726. //
  727. int
  728. TListBox::SetSelString(const char far* findStr, int indexStart)
  729. {
  730.   if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
  731.     return (int)HandleMessage(LB_SELECTSTRING, indexStart, (LPARAM)findStr);
  732.   return -1;
  733. }
  734.  
  735. //
  736. // selects the strings in the associated list box which begin with
  737. // the passed prefixes
  738. //
  739. // for each string the search begins at the beginning of the list
  740. // and continues until a match is found or until the list has been
  741. // completely traversed
  742. //
  743. // if ShouldSet is TRUE, the matched strings are selected and highlighted;
  744. // otherwise the highlight is removed from the matched strings and they
  745. // are no longer selected
  746. //
  747. // returns the number of strings successfully selected or deselected
  748. //
  749. // if NumSelections is less than zero, all strings are selected or deselected
  750. // and a negative value is returned on failure
  751. //
  752. // only for multiple-selection list boxes (-1 is returned if this is not
  753. // a multiple-selection list box)
  754. //
  755. int
  756. TListBox::SetSelStrings(const char far** strs, int numSelections, BOOL shouldSet)
  757. {
  758.   if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
  759.     return -1;
  760.  
  761.   if (numSelections < 0)
  762.     return SetSel(-1, shouldSet);
  763.  
  764.   int  successes = 0;
  765.   for (int i = 0; i < numSelections; i++) {
  766.     int  selIndex;
  767.     if ((selIndex = FindString(strs[i], -1)) > -1)
  768.       if (SetSel(selIndex, shouldSet) > -1)
  769.         successes++;
  770.   }
  771.   return successes;
  772. }
  773.  
  774. //
  775. // returns the index of the selected string in the associated listbox
  776. //
  777. // a negative value is returned if no string is selected or this
  778. // is a multiple-selection list box
  779. //
  780. // only for single-selection list boxes
  781. //
  782. int
  783. TListBox::GetSelIndex() const
  784. {
  785.   if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
  786.     return (int)CONST_CAST(TListBox*,this)->HandleMessage(LB_GETCURSEL);
  787.   return -1;
  788. }
  789.  
  790. //
  791. // fills indexes with the indexes of up to maxCount selected strings
  792. //
  793. // returns number of items put in the array(-1 for single-selection
  794. // list boxes)
  795. //
  796. int
  797. TListBox::GetSelIndexes(int* indexes, int maxCount) const
  798. {
  799.   if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
  800.     return -1;
  801.   return (int)CONST_CAST(TListBox*,this)->HandleMessage(LB_GETSELITEMS,
  802.                                                         maxCount,
  803.                                                         (LPARAM)indexes);
  804. }
  805.  
  806. // selects the string at passed index in the associated listbox and
  807. // forces the string into view
  808. //
  809. // clears selection when -1 is passed as the index. a negative value is
  810. // returned if an error occurs
  811. //
  812. // only for single-selection list boxes
  813. //
  814. int
  815. TListBox::SetSelIndex(int index)
  816. {
  817.   if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
  818.     return (int)HandleMessage(LB_SETCURSEL, index);
  819.   return -1;
  820. }
  821.  
  822. //
  823. // selects/deselects the strings in the associated list box at the
  824. // passed indexes
  825. //
  826. // if ShouldSet is TRUE, the indexed strings are selected and highlighted;
  827. // otherwise the highlight is removed and they are no longer selected
  828. //
  829. // returns the number of strings successfully selected or deselected(-1
  830. // if not a multiple-selection list box)
  831. //
  832. // if NumSelections is less than zero, all strings are selected or deselected
  833. // and a negative value is returned on failure
  834. //
  835. // only for multiple-selection list boxes
  836. //
  837. int
  838. TListBox::SetSelIndexes(int* indexes, int numSelections, BOOL shouldSet)
  839. {
  840.   int  successes = 0;
  841.  
  842.   if (!(GetWindowLong(GWL_STYLE) & MULTIPLESEL))
  843.     return -1;  // including if it's a combobox
  844.  
  845.   if (numSelections < 0)
  846.     return (int)HandleMessage(LB_SETSEL, shouldSet, -1);
  847.  
  848.   else {
  849.     for (int i = 0; i < numSelections; i++)
  850.       if ((int)HandleMessage(LB_SETSEL, shouldSet, indexes[i]) > -1)
  851.         successes++;
  852.   }
  853.   return successes;
  854. }
  855.  
  856. #endif
  857. #if !defined(SECTION) || SECTION == 2
  858.  
  859. IMPLEMENT_STREAMABLE1(TListBox, TControl);
  860.  
  861. //
  862. // reads an instance of TListBox from the supplied ipstream
  863. //
  864. void*
  865. TListBox::Streamer::Read(ipstream& is, uint32 /*version*/) const
  866. {
  867.   ReadBaseObject((TControl*)GetObject(), is);
  868.   return GetObject();
  869. }
  870.  
  871. //
  872. // writes the TListBox to the supplied opstream
  873. //
  874. void
  875. TListBox::Streamer::Write(opstream& os) const
  876. {
  877.   WriteBaseObject((TControl*)GetObject(), os);
  878. }
  879.  
  880. #endif
  881.  
  882.