WTL Controls
Back to the WTL Controls Home Page.
ODComboBox.cpp
Go to the documentation of this file.
1 #include "stdafx.h"
2 //--------------------------------------------------------------------------------------
3 //--------------------------------------------------------------------------------------
4 //
5 //
6 // WTL Control Library
7 // by
8 // Bright Ideas Software®
9 // Copyright © 2018 by Bright Ideas Software.
10 //
11 //
12 //
13 //--------------------------------------------------------------------------------------
14 //--------------------------------------------------------------------------------------
15 
16 
17 namespace BIS_WTL_CONTROLS
18 {
19 
21  //----------------------------------------------------------------------------------------------
22  CODComboBox::CODComboItem::CODComboItem() noexcept
23  {
24  m_Text = "";
25  m_BackColor = ::GetSysColor(COLOR_WINDOW);
26  m_TextColor = ::GetSysColor(COLOR_WINDOWTEXT);
27  m_Font = NULL;
28  m_iItemHeight = DEFAULT_COMBO_ITEM_HEIGHT;
29 
30  m_VertAlign = CVertAlignment::vaMiddle;
31  m_HorzAlign = CHorzAlignment::haLeft;
32 
33  m_bWrap = false;
34  m_bUseEllipsis = true;
35 
36  m_Brush = NULL;
37  UpdateBrush();
38  };
39  //----------------------------------------------------------------------------------------------
40  CODComboBox::CODComboItem::CODComboItem(std::basic_string<TCHAR> text, COLORREF text_color,
41  COLORREF back_color, HFONT font, int height,
42  CHorzAlignment horz, CVertAlignment vert,
43  bool wrap, bool use_ellipsis)
44  {
45 
46  m_Text = text.c_str();
47  m_BackColor = back_color;
48  m_TextColor = text_color;
49  m_Font = font;
50  m_iItemHeight = height;
51 
52  m_VertAlign = vert;
53  m_HorzAlign = horz;
54 
55  m_bWrap = wrap;
56  m_bUseEllipsis = use_ellipsis;
57 
58  m_Brush = NULL;
59  UpdateBrush();
60  };
61  //----------------------------------------------------------------------------------------------
62  CODComboBox::CODComboItem::~CODComboItem()
63  {
64  if (m_Brush != NULL)
65  {
66  ::DeleteObject(m_Brush);
67  m_Brush = NULL;
68  }
69  }
70  //----------------------------------------------------------------------------------------------
71  void CODComboBox::CODComboItem::UpdateBrush()
72  {
73  if (m_Brush != NULL)
74  ::DeleteObject(m_Brush);
75 
76  m_Brush = ::CreateSolidBrush(m_BackColor);
77 
78  }
79  //----------------------------------------------------------------------------------------------
80  //----------------------------------------------------------------------------------------------
82 
83 
84 
85 
86 
87 
88  //----------------------------------------------------------------------------------------------
89  //----------------------------------------------------------------------------------------------
91  {
92 
93  m_bAutoAdjustDropWidth = true;
94  m_iMaxDropDownWidth = 400;
95 
96  m_wndControl = NULL;
97  m_wndListBox = NULL;
98 
99  m_bMsgHandled = FALSE;
100 
101  }
102  //----------------------------------------------------------------------------------------------
104  {
105  ATLASSERT(m_hWnd == NULL);
106  }
107  //----------------------------------------------------------------------------------------------
108  //----------------------------------------------------------------------------------------------
122  {
123 
124  CWindowImpl<CODComboBox, CComboBox>::SubclassWindow(hWnd);
125 
126  COMBOBOXINFO info;
127  info.cbSize = sizeof(COMBOBOXINFO);
128 
129  GetComboBoxInfo(&info);
130 
131  m_wndControl = info.hwndItem;
132  m_wndListBox = info.hwndList;
133 
134  if (::IsWindow(m_wndListBox))
135  m_ListBox.Attach(m_wndListBox);
136 
137  if (::IsWindow(m_wndControl))
138  m_ControlWnd.Attach(m_wndControl);
139 
140 
141  }
142  //----------------------------------------------------------------------------------------------
149  {
150  if (m_ListBox.IsWindow())
151  m_ListBox.Detach();
152 
153  if (m_ControlWnd.IsWindow())
154  m_ControlWnd.Detach();
155 
156  int items = GetCount();
157 
158  for (int i = items - 1; i >= 0; i--)
159  ODRemoveItem(i);
160 
161  UnsubclassWindow();
162  }
163  //----------------------------------------------------------------------------------------------
164  //----------------------------------------------------------------------------------------------
176  {
177  return(m_bAutoAdjustDropWidth);
178  }
179  //----------------------------------------------------------------------------------------------
191  {
192  m_bAutoAdjustDropWidth = value;
194  }
195  //----------------------------------------------------------------------------------------------
196  //----------------------------------------------------------------------------------------------
206  {
207  return(m_iMaxDropDownWidth);
208  }
209  //----------------------------------------------------------------------------------------------
220  {
221  m_iMaxDropDownWidth = value;
223  }
224  //----------------------------------------------------------------------------------------------
225  //----------------------------------------------------------------------------------------------
236  {
237 
238  CODComboItem* item = new CODComboItem();
239 
240  item->m_Font = GetFont();
241  item->m_iItemHeight = GetItemHeight(-1);
242 
243  long result = AddString((LPCTSTR)item);
244 
247 
248  return((result != CB_ERR)&&(result != CB_ERRSPACE));
249 
250  }
251  //----------------------------------------------------------------------------------------------
270  bool CODComboBox::ODAddItem(std::basic_string<TCHAR> text, COLORREF text_color, COLORREF back_color,
271  HFONT font, int height, CHorzAlignment horz, CVertAlignment vert,
272  bool wrap, bool use_ellipsis)
273  {
274 
275  CODComboItem* item = new CODComboItem();
276 
277  item->m_Text = text.c_str();
278  item->m_BackColor = back_color;
279  item->m_TextColor = text_color;
280  item->m_Font = font;
281  item->m_iItemHeight = height;
282  item->m_HorzAlign = horz;
283  item->m_VertAlign = vert;
284  item->m_bWrap = wrap;
285  item->m_bUseEllipsis = use_ellipsis;
286 
287  item->UpdateBrush();
288 
289  long result = AddString((LPCTSTR)item);
290 
293 
294  return((result != CB_ERR)&&(result != CB_ERRSPACE));
295 
296  }
297  //----------------------------------------------------------------------------------------------
298  //----------------------------------------------------------------------------------------------
312  {
313 
314  CODComboItem* item = new CODComboItem();
315 
316  item->m_Font = GetFont();
317  item->m_iItemHeight = DEFAULT_COMBO_ITEM_HEIGHT;// m_iControlHeight;
318 
319  long result = InsertString(index, (LPCTSTR)item);
320 
323 
324  return((result != CB_ERR)&&(result != CB_ERRSPACE));
325 
326  }
327  //----------------------------------------------------------------------------------------------
348  bool CODComboBox::ODInsertItem(int index, std::basic_string<TCHAR> text, COLORREF text_color, COLORREF back_color,
349  HFONT font, int height, CHorzAlignment horz, CVertAlignment vert,
350  bool wrap, bool use_ellipsis)
351  {
352 
353  CODComboItem* item = new CODComboItem();
354 
355  item->m_Text = text.c_str();
356  item->m_BackColor = back_color;
357  item->m_TextColor = text_color;
358  item->m_Font = font;
359  item->m_iItemHeight = height;
360  item->m_HorzAlign = horz;
361  item->m_VertAlign = vert;
362  item->m_bWrap = wrap;
363  item->m_bUseEllipsis = use_ellipsis;
364 
365  item->UpdateBrush();
366 
367  long result = InsertString(index, (LPCTSTR) item);
368 
371 
372  return((result != CB_ERR)&&(result != CB_ERRSPACE));
373 
374  }
375  //----------------------------------------------------------------------------------------------
376  //----------------------------------------------------------------------------------------------
390  {
391  LRESULT result = DeleteString(index);
392 
393  return(result != CB_ERR);
394  }
395  //----------------------------------------------------------------------------------------------
396  //----------------------------------------------------------------------------------------------
407  std::basic_string<TCHAR> CODComboBox::GetODItemText(int index) const
408  {
409  CODComboItem* item = GetAndVerifyItemData(index);
410  CString result = item->m_Text;
411 
412  return((LPCTSTR)result);
413  }
414  //----------------------------------------------------------------------------------------------
426  void CODComboBox::SetODItemText(int index, std::basic_string<TCHAR> text)
427  {
428  CODComboItem* item = GetAndVerifyItemData(index);
429  item->m_Text = text.c_str();
430 
432  }
433  //----------------------------------------------------------------------------------------------
434  //----------------------------------------------------------------------------------------------
445  COLORREF CODComboBox::GetODItemBackColor(int index) const
446  {
447  CODComboItem* item = GetAndVerifyItemData(index);
448  COLORREF result = item->m_BackColor;
449 
450  return(result);
451  }
452  //----------------------------------------------------------------------------------------------
464  void CODComboBox::SetODItemBackColor(int index, COLORREF color)
465  {
466  CODComboItem* item = GetAndVerifyItemData(index);
467  item->m_BackColor = color;
468  item->UpdateBrush();
469  }
470  //----------------------------------------------------------------------------------------------
471  //----------------------------------------------------------------------------------------------
482  COLORREF CODComboBox::GetODItemTextColor(int index) const
483  {
484  CODComboItem* item = GetAndVerifyItemData(index);
485  COLORREF result = item->m_TextColor;
486 
487  return(result);
488  }
489  //----------------------------------------------------------------------------------------------
501  void CODComboBox::SetODItemTextColor(int index, COLORREF color)
502  {
503  CODComboItem* item = GetAndVerifyItemData(index);
504  item->m_TextColor = color;
505  }
506  //----------------------------------------------------------------------------------------------
507  //----------------------------------------------------------------------------------------------
518  HFONT CODComboBox::GetODItemFont(int index) const
519  {
520  CODComboItem* item = GetAndVerifyItemData(index);
521  HFONT result = item->m_Font;
522 
523  return(result);
524  }
525  //----------------------------------------------------------------------------------------------
537  void CODComboBox::SetODItemFont(int index, HFONT font)
538  {
539  CODComboItem* item = GetAndVerifyItemData(index);
540  item->m_Font = font;
542  }
543  //----------------------------------------------------------------------------------------------
544  //----------------------------------------------------------------------------------------------
556  int CODComboBox::GetODItemHeight(int index) const
557  {
558  CODComboItem* item = GetAndVerifyItemData(index);
559  int result = item->m_iItemHeight;
560 
561  return(result);
562  }
563  //----------------------------------------------------------------------------------------------
575  void CODComboBox::SetODItemHeight(int index, int height)
576  {
577  CODComboItem* item = GetAndVerifyItemData(index);
578  item->m_iItemHeight = height;
579  }
580  //----------------------------------------------------------------------------------------------
581  //----------------------------------------------------------------------------------------------
593  {
594  CODComboItem* item = GetAndVerifyItemData(index);
595  CHorzAlignment result = item->m_HorzAlign;
596 
597  return(result);
598  }
599  //----------------------------------------------------------------------------------------------
612  {
613  CODComboItem* item = GetAndVerifyItemData(index);
614  item->m_HorzAlign = value;
615  }
616  //----------------------------------------------------------------------------------------------
617  //----------------------------------------------------------------------------------------------
629  {
630  CODComboItem* item = GetAndVerifyItemData(index);
631  CVertAlignment result = item->m_VertAlign;
632 
633  return(result);
634  }
635  //----------------------------------------------------------------------------------------------
648  {
649  CODComboItem* item = GetAndVerifyItemData(index);
650  item->m_VertAlign = value;
651  }
652  //----------------------------------------------------------------------------------------------
653  //----------------------------------------------------------------------------------------------
664  bool CODComboBox::GetODItemWordWrap(int index) const
665  {
666  CODComboItem* item = GetAndVerifyItemData(index);
667  bool result = item->m_bWrap;
668 
669  return(result);
670  }
671  //----------------------------------------------------------------------------------------------
685  void CODComboBox::SetODItemWordWrap(int index, bool wrap)
686  {
687  CODComboItem* item = GetAndVerifyItemData(index);
688  item->m_bWrap = wrap;
689  }
690  //----------------------------------------------------------------------------------------------
691  //----------------------------------------------------------------------------------------------
702  bool CODComboBox::GetODItemUseEllipsis(int index) const
703  {
704  CODComboItem* item = GetAndVerifyItemData(index);
705  bool result = item->m_bUseEllipsis;
706 
707  return(result);
708  }
709  //----------------------------------------------------------------------------------------------
722  void CODComboBox::SetODItemUseEllipsis(int index, bool ellipsis)
723  {
724  CODComboItem* item = GetAndVerifyItemData(index);
725  item->m_bUseEllipsis = ellipsis;
726  }
727  //----------------------------------------------------------------------------------------------
742  {
743 
744  if (IsWindow())
745  {
746  if (m_bAutoAdjustDropWidth == true)
747  {
748 
749  int max = 0;
750  for (int i = 0; i < GetCount(); i++)
751  {
752  CODComboItem* item = (CODComboItem*)GetItemDataPtr(i);
753 
754  int w = GetTextLength( item->m_Text, item->m_Font);
755 
756  if (w > max)
757  max = w;
758  }
759 
760  if (max > m_iMaxDropDownWidth)
761  max = m_iMaxDropDownWidth;
762 
763  RECT window_rect;
764  GetWindowRect(&window_rect);
765  int w_w = window_rect.right - window_rect.left;
766 
767  if (max < w_w)
768  max = w_w;
769 
770  SetDroppedWidth(max);
771  }
772  }
773  }
774  //----------------------------------------------------------------------------------------------
785  {
786 
787  if (IsWindow())
788  {
789  int total_height = 0;
790 
791  for (int i = 0; i < GetCount(); i++)
792  {
793  CODComboItem* item = (CODComboItem*)GetItemDataPtr(i);
794  total_height += item->m_iItemHeight;
795  }
796 
797  RECT control_client_rect;
798  RECT control_rect;
799  RECT parent_rect;
800  RECT list_rect;
801 
802  GetWindowRect(&parent_rect);
803  m_ListBox.GetWindowRect(&list_rect);
804 
805  m_ControlWnd.GetWindowRect(&control_rect);
806  m_ControlWnd.GetClientRect(&control_client_rect);
807 
808  total_height += (control_client_rect.bottom - control_client_rect.top); // add the static or edit control's client height
809 
810  total_height += (control_rect.bottom - control_rect.top) // add the diff between window rect and client rect
811  - (control_client_rect.bottom - control_client_rect.top);
812 
813  total_height += 2 * (control_rect.top - parent_rect.top); // add double the diff between the parent top and the
814  // top of the edit or static
815  int edge = GetSystemMetrics(SM_CXBORDER) * 2;
816  total_height += edge;
817 
818  parent_rect.bottom = parent_rect.top + total_height;
819 
820  SetWindowPos(GetParent(), &parent_rect, SWP_NOMOVE | SWP_NOZORDER);
821 
822  }
823  }
824  //----------------------------------------------------------------------------------------------
825  //----------------------------------------------------------------------------------------------
826  //
827  // Private Methods
828  //
829  //----------------------------------------------------------------------------------------------
830  //----------------------------------------------------------------------------------------------
831  CODComboBox::CODComboItem* CODComboBox::GetAndVerifyItemData(int index) const
832  {
833  LRESULT lr = GetItemData(index);
834 
835  ATLASSERT (lr != CB_ERR);
836 
837  CODComboItem* item = (CODComboItem*) lr;
838 
839  return(item);
840  }
841  //----------------------------------------------------------------------------------------------
842  UINT CODComboBox::GetTextFormat(CODComboItem* item)
843  {
844  UINT format = DT_EDITCONTROL;
845 
846  if (item->m_bWrap == true)
847  format |= DT_WORDBREAK;
848  else
849  format |= DT_SINGLELINE;
850 
851  if (item->m_bUseEllipsis == true)
852  format |= DT_END_ELLIPSIS;
853 
854  switch(item->m_HorzAlign)
855  {
857  format |= DT_LEFT;
858  break;
859 
861  format |= DT_CENTER;
862  break;
863 
865  format |= DT_RIGHT;
866  break;
867  };
868 
869  switch (item->m_VertAlign)
870  {
872  format |= DT_TOP;
873  break;
874 
876  format |= DT_VCENTER;
877  break;
878 
880  format |= DT_BOTTOM;
881  break;
882 
883  };
884 
885  return(format);
886  }
887  //----------------------------------------------------------------------------------------------
888  //----------------------------------------------------------------------------------------------
889  //
890  // Message Handlers
891  //
892  //----------------------------------------------------------------------------------------------
893  //----------------------------------------------------------------------------------------------
895  void CODComboBox::DeleteItem(LPDELETEITEMSTRUCT lpDeleteItemStruct)
896  {
897 
898  CODComboItem* item = (CODComboItem*) lpDeleteItemStruct->itemData;
899  delete item;
900 
901  }
902  //----------------------------------------------------------------------------------------------
903  int CODComboBox::CompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct)
904  {
905  int result = 0; // items are the same!
906 
907  CODComboItem* item1 = (CODComboItem*)lpCompareItemStruct->itemData1;
908  CODComboItem* item2 = (CODComboItem*)lpCompareItemStruct->itemData2;
909 
910  int comp = item1->m_Text.Compare(item2->m_Text);
911 
912  if (comp < 0)
913  result = -1;
914  else if (comp > 0)
915  result = 1;
916 
917  return(result);
918  }
919  //----------------------------------------------------------------------------------------------
920  void CODComboBox::MeasureItem(LPMEASUREITEMSTRUCT lpStruct)
921  {
922  int index = lpStruct->itemID;
923 
924  if ((index == -1) || (index == ((UINT)-1)))
925  lpStruct->itemHeight = GetItemHeight(-1);
926  else
927  lpStruct->itemHeight = ((CODComboItem*)lpStruct->itemData)->m_iItemHeight;
928 
929  SetMsgHandled(TRUE);
930  }
931  //----------------------------------------------------------------------------------------------
932  void CODComboBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
933  {
934 
935  HDC dc = lpDrawItemStruct->hDC;
936  CODComboItem* item = (CODComboItem*)lpDrawItemStruct->itemData;
937 
938  HFONT old_font = (HFONT)::SelectObject(dc, item->m_Font);
939 
940  UINT format = GetTextFormat(item);
941 
942 
943  if ((lpDrawItemStruct->itemAction | ODA_SELECT) &&
944  (lpDrawItemStruct->itemState & ODS_SELECTED)&&
945  ( ! (lpDrawItemStruct->itemState & ODS_COMBOBOXEDIT)))
946  {
947  ::FillRect(dc, &lpDrawItemStruct->rcItem, ::GetSysColorBrush(COLOR_HIGHLIGHT));
948 
949  ::SetTextColor(dc, ::GetSysColor(COLOR_HIGHLIGHTTEXT));
950  ::SetBkColor(dc, ::GetSysColor(COLOR_HIGHLIGHT));
951  }
952  else
953  {
954 
955  FillRect(dc, &lpDrawItemStruct->rcItem, item->m_Brush);
956 
957  ::SetTextColor(dc, item->m_TextColor);
958  ::SetBkColor(dc, item->m_BackColor);
959  }
960 
961 
962  ::SetBkMode(dc, TRANSPARENT);
963 
964  ::DrawText(dc, item->m_Text, item->m_Text.GetLength(), &lpDrawItemStruct->rcItem, format);
965 
966  ::SelectObject(dc, old_font);
967 
968  if (lpDrawItemStruct->itemState & ODS_FOCUS)
969  ::DrawFocusRect(dc, &lpDrawItemStruct->rcItem);
970 
971 
972  }
973  //----------------------------------------------------------------------------------------------
975 };
976 
bool GetAutoAdjustDropRectWidth() const
Default: true.
Definition: ODComboBox.cpp:175
int GetODItemHeight(int index) const
Default: The height of the control portion of the combobox at the time the CODComboItem is instantiat...
Definition: ODComboBox.cpp:556
void SetODItemUseEllipsis(int index, bool ellipsis)
Modify the UseEllipsis state of the selected combobox item.
Definition: ODComboBox.cpp:722
CVertAlignment GetODItemVertAlignment(int index) const
DefaultL: vaMiddle.
Definition: ODComboBox.cpp:628
void SetODItemBackColor(int index, COLORREF color)
Modify the background color of the selected combobox item.
Definition: ODComboBox.cpp:464
HFONT GetODItemFont(int index) const
Default: The font assigned to the combo box when the CODComboItem object is instantiated.
Definition: ODComboBox.cpp:518
void SetMaxDropDownWidth(int value)
Sets the upper limit to the width of the dropdown list, if it is being automatically adjusted...
Definition: ODComboBox.cpp:219
CHorzAlignment GetODItemHorzAlignment(int index) const
Default: haLeft.
Definition: ODComboBox.cpp:592
CVertAlignment
Control vertical placement of text in control window.
Definition: WTL_Controls.h:47
int GetTextLength(CString str, HFONT font)
Measure the length, in pixels, of a string using a given font.
void SetODItemHeight(int index, int height)
Modify the height of the selected combobox item.
Definition: ODComboBox.cpp:575
bool ODAddItem()
Add new item to the end of the list box.
Definition: ODComboBox.cpp:235
bool GetODItemWordWrap(int index) const
Default: false.
Definition: ODComboBox.cpp:664
void SubclassComboBox(HWND wnd)
Subclass a combobox control.
Definition: ODComboBox.cpp:121
void SetODItemFont(int index, HFONT font)
Modify the font assigned to the selected combobox item.
Definition: ODComboBox.cpp:537
COLORREF GetODItemBackColor(int index) const
Default: COLOR_WINDOW.
Definition: ODComboBox.cpp:445
void UpdateDropDownWidth()
Force an update of the width of the drop down list.
Definition: ODComboBox.cpp:741
void SetODItemVertAlignment(int index, CVertAlignment value)
Modify the vertical text aligment of the selected combobox item.
Definition: ODComboBox.cpp:647
bool ODInsertItem(int index)
Insert an item.
Definition: ODComboBox.cpp:311
void SetODItemText(int index, std::basic_string< TCHAR > text)
Modify the text associated with a combobox item.
Definition: ODComboBox.cpp:426
int GetMaxDropDownWidth() const
Default: 400 pixels.
Definition: ODComboBox.cpp:205
void SetODItemHorzAlignment(int index, CHorzAlignment value)
Modify the horizontal text alignment of the selected combobox item.
Definition: ODComboBox.cpp:611
CHorzAlignment
Control horizontal placement of text in control window.
Definition: WTL_Controls.h:42
void UnSubclassComboBox()
Un-subclass main and component windows; free GDI resources.
Definition: ODComboBox.cpp:148
void SetODItemWordWrap(int index, bool wrap)
Modify the WordWrap state of the selected combobox item.
Definition: ODComboBox.cpp:685
COLORREF GetODItemTextColor(int index) const
Default: COLOR_WINDOWTEXT.
Definition: ODComboBox.cpp:482
std::basic_string< TCHAR > GetODItemText(int index) const
Default: "".
Definition: ODComboBox.cpp:407
bool ODRemoveItem(int index)
Deletes an item from the drop-down list.
Definition: ODComboBox.cpp:389
bool GetODItemUseEllipsis(int index) const
Default: true.
Definition: ODComboBox.cpp:702
void UpdateControlHeight()
Update the combobox height to accomodate all content.
Definition: ODComboBox.cpp:784
void SetAutoAdjustDropRectWidth(bool value)
Change the AutoAdjustRectWidth state.
Definition: ODComboBox.cpp:190
void SetODItemTextColor(int index, COLORREF color)
Modify the text color of the selected combobox item.
Definition: ODComboBox.cpp:501