MultiColumnComboBox.cpp
上传用户:hzw123hzw
上传日期:2007-01-01
资源大小:18k
文件大小:9k
源码类别:

组合框控件

开发平台:

Visual C++

  1. // By Xiao Wu Guang
  2. // MultiColumnComboBox.cpp : implementation file
  3. //
  4. #include "stdafx.h"
  5. #include "MultiColumnComboBox.h"
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #undef THIS_FILE
  9. static char THIS_FILE[] = __FILE__;
  10. #endif
  11. /////////////////////////////////////////////////////////////////////////////
  12. // CMultiColumnComboBox
  13. CMultiColumnComboBox::CMultiColumnComboBox()
  14. {
  15. m_TotalColumn = 0;
  16. m_BoundColumn = 0;
  17. m_TextItemHeight = 12;
  18. m_LightGrayPen.CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DLIGHT));
  19. m_ColumnWidth = NULL;
  20. m_ColumnAlignStyle = NULL;
  21. m_ColumnItemList = NULL;
  22. }
  23. CMultiColumnComboBox::~CMultiColumnComboBox()
  24. {
  25. if (m_TotalColumn != 0)
  26. {
  27. delete[] m_ColumnWidth;
  28. delete[] m_ColumnAlignStyle;
  29. delete[] m_ColumnItemList;
  30. }
  31. m_LightGrayPen.DeleteObject();
  32. }
  33. BEGIN_MESSAGE_MAP(CMultiColumnComboBox, CComboBox)
  34. //{{AFX_MSG_MAP(CMultiColumnComboBox)
  35. //}}AFX_MSG_MAP
  36. END_MESSAGE_MAP()
  37. /////////////////////////////////////////////////////////////////////////////
  38. // CMultiColumnComboBox message handlers
  39. void CMultiColumnComboBox::FormatComboBox(UINT TotalColumn, UINT BoundColumn)
  40. {
  41. ASSERT(TotalColumn > 1); //You can use CComboBox class instead of this class
  42. m_TotalColumn = TotalColumn;
  43. m_BoundColumn = BoundColumn;
  44. m_ColumnWidth = new UINT[m_TotalColumn];
  45. m_ColumnAlignStyle = new UINT[m_TotalColumn];
  46. m_ColumnItemList = new CStringList[m_TotalColumn];
  47. if ((GetWindowLong(m_hWnd, GWL_STYLE) & 0x3) != CBS_SIMPLE)
  48. {
  49. UINT ComboBoxWidth = GetDroppedWidth() - LEFTMARGIN_OF_DROPDOWNLIST - SPACE_BETWEEN_COLUMN - 1;
  50. for (UINT Index = 0, TotalColumnWidth = LEFTMARGIN_OF_DROPDOWNLIST + RIGHTMARGIN_OF_DROPDOWNLIST; Index < m_TotalColumn; Index++)
  51. { //Assign default value 
  52. m_ColumnWidth[Index] = ComboBoxWidth;
  53. m_ColumnAlignStyle[Index] = DT_LEFT;
  54. TotalColumnWidth += (ComboBoxWidth + SPACE_BETWEEN_COLUMN);
  55. }
  56. SetDroppedWidth(TotalColumnWidth);
  57. }
  58. CDC * DeviceContextPointer = GetWindowDC();
  59. m_TextItemHeight = (DeviceContextPointer->GetTextExtent(" ", 1)).cy - 1;
  60. SetItemHeight(-1, m_TextItemHeight);
  61. ReleaseDC(DeviceContextPointer);
  62. }
  63. void CMultiColumnComboBox::SetColumnWidth(UINT ColumnWidth0, ...)
  64. {
  65. va_list ColumnWidthPointer;
  66. UINT TotalColumnWidth;
  67. ASSERT(m_TotalColumn > 1); //call FormatComboBox first
  68. m_ColumnWidth[0] = ColumnWidth0;
  69. TotalColumnWidth = ColumnWidth0 + SPACE_BETWEEN_COLUMN + LEFTMARGIN_OF_DROPDOWNLIST + RIGHTMARGIN_OF_DROPDOWNLIST;
  70. va_start(ColumnWidthPointer, ColumnWidth0);
  71. for (UINT Index = 1; Index < m_TotalColumn; Index++)
  72. {
  73. m_ColumnWidth[Index] = va_arg(ColumnWidthPointer, UINT);
  74. if (m_ColumnWidth[Index] > 0)
  75. TotalColumnWidth += (m_ColumnWidth[Index] + SPACE_BETWEEN_COLUMN);
  76. }
  77. va_end(ColumnWidthPointer);
  78. if ((GetWindowLong(m_hWnd, GWL_STYLE) & 0x3) == CBS_SIMPLE)
  79. {
  80. CRect WindowRectangle;
  81. GetWindowRect(WindowRectangle);
  82. SetWindowPos(NULL, 0, 0, TotalColumnWidth, WindowRectangle.bottom - WindowRectangle.top, SWP_NOMOVE | SWP_NOZORDER);
  83. }
  84. else
  85. SetDroppedWidth(TotalColumnWidth);
  86. }
  87. void CMultiColumnComboBox::SetColumnAlignStyle(UINT ColumnAlignStyle0, ...)
  88. {
  89. va_list ColumnAlignStylePointer;
  90. ASSERT(m_TotalColumn > 1); //call FormatComboBox first
  91. m_ColumnAlignStyle[0] = ColumnAlignStyle0;
  92. va_start(ColumnAlignStylePointer, ColumnAlignStyle0);
  93. for (UINT Index = 1; Index < m_TotalColumn; Index++)
  94. m_ColumnAlignStyle[Index] = va_arg(ColumnAlignStylePointer, UINT);
  95. va_end(ColumnAlignStylePointer);
  96. }
  97. int CMultiColumnComboBox::AddRow(LPCTSTR lpszString0, ...)
  98. {
  99. va_list StringPointerPointer;
  100. UINT Index, ItemIndex;
  101. LPCTSTR StringPointer;
  102. ASSERT(m_TotalColumn > 1); //call FormatComboBox first
  103. if (m_BoundColumn == 0)
  104. ItemIndex = CComboBox::AddString(lpszString0);
  105. else
  106. {
  107. va_start(StringPointerPointer, lpszString0);
  108. for (Index = 1; Index < m_TotalColumn; Index++)
  109. {
  110. StringPointer = va_arg(StringPointerPointer, LPCTSTR);
  111. if (m_BoundColumn == Index)
  112. ItemIndex = CComboBox::AddString(StringPointer);
  113. }
  114. }
  115. if (ItemIndex == 0)
  116. m_ColumnItemList[0].AddHead(lpszString0);
  117. else
  118. if (ItemIndex == (UINT) CComboBox::GetCount() - 1)
  119. m_ColumnItemList[0].AddTail(lpszString0);
  120. else
  121. m_ColumnItemList[0].InsertBefore(m_ColumnItemList[0].FindIndex(ItemIndex), lpszString0);
  122. va_start(StringPointerPointer, lpszString0);
  123. for (Index = 1; Index < m_TotalColumn; Index++)
  124. {
  125. StringPointer = va_arg(StringPointerPointer, LPCTSTR);
  126. if (ItemIndex == 0)
  127. m_ColumnItemList[Index].AddHead(StringPointer);
  128. else
  129. if (ItemIndex == (UINT) CComboBox::GetCount() - 1)
  130. m_ColumnItemList[Index].AddTail(StringPointer);
  131. else
  132. m_ColumnItemList[Index].InsertBefore(m_ColumnItemList[Index].FindIndex(ItemIndex), StringPointer);
  133. }
  134. va_end(StringPointerPointer);
  135. return TRUE;
  136. }
  137. void CMultiColumnComboBox::ResetContent()
  138. {
  139. CComboBox::ResetContent();
  140. for (UINT ColumnIndex = 0; ColumnIndex < m_TotalColumn; ColumnIndex++)
  141. m_ColumnItemList[ColumnIndex].RemoveAll();
  142. };
  143. void CMultiColumnComboBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
  144. {
  145. ASSERT(m_TotalColumn > 1); //You can use CComboBox class instead of this class
  146. CPen* OldPenPointer;
  147. CDC* DeviceContextPointer = CDC::FromHandle(lpDrawItemStruct->hDC);
  148. CWnd* DropDownWindowPointer = DeviceContextPointer->GetWindow();
  149. BOOL IsHighLightText = lpDrawItemStruct->itemAction & ODA_FOCUS || lpDrawItemStruct->itemState & ODS_SELECTED;
  150. CRect TextRectangle = lpDrawItemStruct->rcItem;
  151. DeviceContextPointer->SetTextColor(GetSysColor(IsWindowEnabled() ? (IsHighLightText ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT) : COLOR_WINDOWTEXT));
  152. DeviceContextPointer->SetBkColor(GetSysColor(IsWindowEnabled() ? (IsHighLightText ? COLOR_HIGHLIGHT : COLOR_WINDOW) : COLOR_3DFACE));
  153. DeviceContextPointer->FillRect(TextRectangle, &CBrush(DeviceContextPointer->GetBkColor()));
  154. if (IsHighLightText)
  155. DeviceContextPointer->DrawFocusRect(TextRectangle);
  156. if (lpDrawItemStruct->itemID != (UINT)-1)
  157. {
  158. if (DropDownWindowPointer != this) //Draw items in drop down list
  159. {
  160. if (TextRectangle.top == 0 && (GetWindowLong(m_hWnd, GWL_STYLE) & 0x3) != CBS_SIMPLE)
  161. { //Only "dropdwon" & "drop list" combo box can move their drop down window
  162. CRect WindowRectangle;
  163. DropDownWindowPointer->GetWindowRect(WindowRectangle);
  164. if (WindowRectangle.right > GetSystemMetrics(SM_CXSCREEN)) //Move drop down window to left if its left side is out of screen
  165. {
  166. WindowRectangle.OffsetRect(GetSystemMetrics(SM_CXSCREEN) - WindowRectangle.right, 0);
  167. DropDownWindowPointer->MoveWindow(WindowRectangle);
  168.    }
  169. }
  170. if (!IsHighLightText)
  171. {
  172. OldPenPointer = DeviceContextPointer->SelectObject(&m_LightGrayPen);
  173. DeviceContextPointer->MoveTo(TextRectangle.left, TextRectangle.bottom - 1);
  174. DeviceContextPointer->LineTo(TextRectangle.right, TextRectangle.bottom - 1);
  175. }
  176. TextRectangle.left += LEFTMARGIN_OF_DROPDOWNLIST;
  177. TextRectangle.right = TextRectangle.left;
  178. for (UINT ColumnIndex = 0; ColumnIndex < m_TotalColumn; ColumnIndex++)
  179. {
  180. TextRectangle.left = TextRectangle.right;
  181. if (m_ColumnWidth[ColumnIndex] != 0)
  182. {
  183. if (ColumnIndex > 1 || (ColumnIndex == 1 && m_ColumnWidth[0] != 0))
  184. {
  185. TextRectangle.left += SPACE_BETWEEN_COLUMN;
  186. if (!IsHighLightText)
  187. { //draw vertical gray line
  188. DeviceContextPointer->MoveTo(TextRectangle.left - SPACE_BETWEEN_COLUMN / 2, TextRectangle.top);
  189. DeviceContextPointer->LineTo(TextRectangle.left - SPACE_BETWEEN_COLUMN / 2, TextRectangle.bottom);
  190. }
  191. }
  192. TextRectangle.right = TextRectangle.left + m_ColumnWidth[ColumnIndex];
  193. TextRectangle.left++;
  194. // if vertical scrool bar is visible
  195. if ((ColumnIndex == m_TotalColumn - 1 || (ColumnIndex == m_TotalColumn - 2 && m_ColumnWidth[m_TotalColumn - 1] == 0)) && (GetWindowLong(DropDownWindowPointer->m_hWnd, GWL_STYLE) & WS_VSCROLL))
  196. TextRectangle.right -= GetSystemMetrics(SM_CXVSCROLL);
  197. DeviceContextPointer->DrawText(m_ColumnItemList[ColumnIndex].GetAt(m_ColumnItemList[ColumnIndex].FindIndex(lpDrawItemStruct->itemID)), -1, TextRectangle,
  198. m_ColumnAlignStyle[ColumnIndex] | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
  199. }
  200. }
  201. if (!IsHighLightText)
  202. DeviceContextPointer->SelectObject(OldPenPointer);
  203. }
  204. else //Draw item in edit box control/static text control
  205. {
  206. TextRectangle.left += LEFTMARGIN_OF_CONTROL;
  207. if (m_ColumnWidth[m_BoundColumn] > 0)
  208. DeviceContextPointer->DrawText(m_ColumnItemList[m_BoundColumn].GetAt(m_ColumnItemList[m_BoundColumn].FindIndex(lpDrawItemStruct->itemID)), -1, TextRectangle,
  209. m_ColumnAlignStyle[m_BoundColumn] | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
  210. else //Bound column is hidden
  211. {
  212. //Seek a column that its width is not 0
  213. for (UINT ColumnIndex = 0; !m_ColumnWidth[ColumnIndex] && ColumnIndex < m_TotalColumn; ColumnIndex++);
  214. DeviceContextPointer->DrawText(m_ColumnItemList[ColumnIndex].GetAt(m_ColumnItemList[ColumnIndex].FindIndex(lpDrawItemStruct->itemID)), -1, TextRectangle,
  215. m_ColumnAlignStyle[ColumnIndex] | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
  216. }
  217. }
  218. }
  219. }
  220. void CMultiColumnComboBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) 
  221. {
  222. lpMeasureItemStruct->itemHeight = m_TextItemHeight;
  223. }