home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / COMBOBOX.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  7.9 KB  |  331 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // (C) Copyright 1991, 1994 by Borland International, All Rights Reserved
  4. //
  5. //   Implementation of TComboBox & TComboBoxData.
  6. //----------------------------------------------------------------------------
  7. #pragma hdrignore SECTION
  8. #include <owl/owlpch.h>
  9. #include <owl/combobox.h>
  10. #include <cstring.h>
  11.  
  12. #if !defined(SECTION) || SECTION == 1
  13.  
  14. //
  15. // constructor for a TComboBoxData object
  16. //
  17. TComboBoxData::TComboBoxData()
  18. :
  19.   Strings(10, 0, 10),
  20.   ItemDatas(10, 0, 10)
  21. {
  22.   SelIndex = 0;
  23. }
  24.  
  25. //
  26. // destructor for TComboBoxData
  27. //
  28. TComboBoxData::~TComboBoxData()
  29. {
  30. }
  31.  
  32. //
  33. // adds the supplied string to the "Strings" array and copies it into
  34. // "Selection" if "isSelected" is true
  35. //
  36. void
  37. TComboBoxData::AddString(const char* str, bool isSelected)
  38. {
  39.   Strings.Add(str);
  40.   if (isSelected)
  41.     Select(Strings.GetItemsInContainer()-1);
  42. }
  43.  
  44. void
  45. TComboBoxData::AddStringItem(const char* str, uint32 itemData, bool isSelected)
  46. {
  47.   ItemDatas.Add(itemData);
  48.   AddString(str, isSelected);
  49. }
  50.  
  51. //
  52. // selects an item at a given index.
  53. //
  54. void
  55. TComboBoxData::Select(int index)
  56. {
  57.   if (index != CB_ERR) {
  58.     SelIndex = index;
  59.     if (index < Strings.GetItemsInContainer())
  60.       Selection = Strings[index];
  61.   }
  62. }
  63.  
  64. //
  65. // selects "str", marking the matching String entry (if any) as selected
  66. //
  67. void
  68. TComboBoxData::SelectString(const char far* str)
  69. {
  70.   int numStrings = Strings.GetItemsInContainer();
  71.   SelIndex = CB_ERR;
  72.   for (int i = 0; i < numStrings; i++)
  73.     if (strcmp(Strings[i].c_str(), str) == 0) {
  74.       SelIndex = i;
  75.       break;
  76.     }
  77.   if (Selection != str)
  78.     Selection = str;
  79. }
  80.  
  81. //
  82. // returns the length of the selection string excluding the terminating 0
  83. //
  84. int
  85. TComboBoxData::GetSelStringLength() const
  86. {
  87.   return Selection.length();
  88. }
  89.  
  90. //
  91. // copies the selected string into Buffer. BufferSize includes the terminating 0
  92. //
  93. void
  94. TComboBoxData::GetSelString(char far* buffer, int bufferSize) const
  95. {
  96.   if (bufferSize > 0) {
  97.     strncpy(buffer, Selection.c_str(), bufferSize-1);
  98.     buffer[bufferSize - 1] = 0;
  99.   }
  100. }
  101.  
  102. //----------------------------------------------------------------------------
  103.  
  104. //
  105. // constructor for a TComboBox object
  106. //
  107. // by default, an MS-Windows combobox associated with the TComboBox will have
  108. // a vertical scrollbar and will maintain its entries in alphabetical order
  109. //
  110. TComboBox::TComboBox(TWindow*        parent,
  111.                      int             id,
  112.                      int x, int y, int w, int h,
  113.                      uint32           style,
  114.                      uint            textLen,
  115.                      TModule*        module)
  116. :
  117.   TListBox(parent, id, x, y, w, h, module)
  118. {
  119.   TextLen = textLen;
  120.   Attr.Style = WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP |
  121.                CBS_SORT | CBS_AUTOHSCROLL | WS_VSCROLL | style;
  122. }
  123.  
  124. TComboBox::TComboBox(TWindow*   parent,
  125.                      int        resourceId,
  126.                      uint       textLen,
  127.                      TModule*   module)
  128. :
  129.   TListBox(parent, resourceId, module)
  130. {
  131.   TextLen = textLen;
  132. }
  133.  
  134. //
  135. // sets and selects the contents of the associated edit control to the
  136. // supplied string
  137. //
  138. void
  139. TComboBox::SetText(const char far* str)
  140. {
  141.   //
  142.   // if str is 0, then use empty str
  143.   //
  144.   if (!str)
  145.     str = "";
  146.  
  147.   //
  148.   // if not in listbox, then set the edit/static portion
  149.   //
  150.   if (SetSelString(str, -1) < 0) {
  151.     SetWindowText(str);
  152.     SetEditSel(0, strlen(str));
  153.   }
  154. }
  155.  
  156. //
  157. // returns, in the supplied reference parameters, the starting and
  158. // ending positions of the text selected in the associated edit control
  159. //
  160. // returns CB_ERR is the combo box has no edit control
  161. //
  162. int
  163. TComboBox::GetEditSel(int& startPos, int& endPos)
  164. {
  165.   LRESULT  retValue = HandleMessage(CB_GETEDITSEL);
  166.  
  167.   startPos = LOWORD(retValue);
  168.   endPos   = HIWORD(retValue);
  169.  
  170.   return (int)retValue;
  171. }
  172.  
  173. //
  174. // shows or hides the drop-down list
  175. //
  176. void
  177. TComboBox::ShowList(bool show)
  178. {
  179.   if ((GetWindowLong(GWL_STYLE) & CBS_DROPDOWN) == CBS_DROPDOWN)
  180.     HandleMessage(CB_SHOWDROPDOWN, show);
  181. }
  182.  
  183. static void
  184. DoAddStringToCB(string& str, void* comboBox)
  185. {
  186.   ((TListBox*)comboBox)->AddString(str.c_str());
  187. }
  188.  
  189. //
  190. // transfers the items and selection of the combo box to or from a transfer
  191. // buffer if tdSetData or tdGetData, respectively, is passed as the
  192. // direction
  193. //
  194. // buffer should point to a TComboBoxData which points to the data to be
  195. // transferred
  196. //
  197. // Transfer returns the size of TComboBoxData
  198. //
  199. // to retrieve the size without transferring data, pass tdSizeData as the
  200. // direction
  201. //
  202. uint
  203. TComboBox::Transfer(void* buffer, TTransferDirection direction)
  204. {
  205.   TComboBoxData* comboBoxData = (TComboBoxData*)buffer;
  206.  
  207.   if (direction == tdGetData) {
  208.     //
  209.     // Clear out Strings array and fill with contents of list box part
  210.     // Prescan for longest string to allow a single temp allocation
  211.     //
  212.     comboBoxData->Clear();
  213.  
  214.     int  count = GetCount();
  215.     int  maxStringLen = 0;
  216.     for (int i = 0; i < count; i++) {
  217.       int  stringLen = GetStringLen(i);
  218.       if (stringLen > maxStringLen)
  219.         maxStringLen = stringLen;
  220.     }
  221.     char*  tmpString = new char[maxStringLen+1];
  222.     for (i = 0; i < count; i++) {
  223.       GetString(tmpString, i);
  224.       comboBoxData->AddString(tmpString, false);
  225.       comboBoxData->GetItemDatas()[i] = GetItemData(i);
  226.     }
  227.     delete tmpString;
  228.  
  229.     //
  230.     // Get the sel string from the list by index, or if no index from the
  231.     // edit box
  232.     //
  233.     int selIndex = GetSelIndex();
  234.     if (selIndex >= 0) {
  235.       int  stringLen = GetStringLen(selIndex);
  236.       if (stringLen > 0) {
  237.         char* str = new char[stringLen+1];
  238.         GetString(str, selIndex);
  239.         comboBoxData->SelectString(str);
  240.         delete str;
  241.       }
  242.       else
  243.         comboBoxData->SelectString("");
  244.     }
  245.     else {
  246.       int  stringLen = GetWindowTextLength();
  247.       if (stringLen > 0) {
  248.         char* str = new char[stringLen+1];
  249.         GetWindowText(str, stringLen+1);
  250.         comboBoxData->SelectString(str);
  251.         delete str;
  252.       }
  253.       else
  254.         comboBoxData->SelectString("");
  255.     }
  256.   }
  257.   else if (direction == tdSetData) {
  258.     ClearList();
  259.     comboBoxData->GetStrings().ForEach(DoAddStringToCB, this);
  260.     for (int i = 0; i < comboBoxData->GetItemDatas().GetItemsInContainer(); i++)
  261.       SetItemData(i, comboBoxData->GetItemDatas()[i]);
  262.  
  263.     SetWindowText(comboBoxData->GetSelection().c_str());
  264.     if (comboBoxData->GetSelIndex() >= 0)
  265.       SetSelString(comboBoxData->GetSelection().c_str(), 0);
  266.   }
  267.  
  268.   return sizeof(TComboBoxData);
  269. }
  270.  
  271. //
  272. // Return name of predefined Windows combobox class
  273. //
  274. char far*
  275. TComboBox::GetClassName()
  276. {
  277.   return "COMBOBOX";
  278. }
  279.  
  280. //
  281. // limits the amount of text that the user can enter in the combo box's
  282. // edit control to the value of TextLen minus 1
  283. //
  284. // creates aliases for the children in the combo box so that TWindow can
  285. // handle kill focus messages for focus support.
  286. //
  287. void
  288. TComboBox::SetupWindow()
  289. {
  290.   TListBox::SetupWindow();
  291.  
  292.   if (TextLen != 0)
  293.     HandleMessage(CB_LIMITTEXT, TextLen-1);
  294.  
  295.   HWND hWnd = ::GetWindow(HWindow, GW_CHILD);
  296.   while (hWnd) {
  297.     if (!GetWindowPtr(hWnd))
  298.       new TWindow(hWnd);
  299.     hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
  300.   }
  301. }
  302.  
  303. #endif
  304. #if !defined(SECTION) || SECTION == 2
  305.  
  306. IMPLEMENT_STREAMABLE1(TComboBox, TListBox);
  307.  
  308. //
  309. // reads an instance of TComboBox from the supplied ipstream
  310. //
  311. void*
  312. TComboBox::Streamer::Read(ipstream& is, uint32 /*version*/) const
  313. {
  314.   ReadBaseObject((TListBox*)GetObject(), is);
  315.   is >> GetObject()->TextLen;
  316.   return GetObject();
  317. }
  318.  
  319. //
  320. // writes the TComboBox to the supplied opstream
  321. //
  322. void
  323. TComboBox::Streamer::Write(opstream& os) const
  324. {
  325.   WriteBaseObject((TListBox*)GetObject(), os);
  326.   os << GetObject()->TextLen;
  327. }
  328.  
  329. #endif
  330.  
  331.