PushDlg: Allow to set upstream
[TortoiseGit.git] / ext / ResizableLib / ResizableComboBox.cpp
blob1a749e3cc969b9a039b14cffcb76301f8d089c1b
1 // ResizableComboBox.cpp : implementation file
2 //
3 /////////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2000-2004 by Paolo Messina
6 // (http://www.geocities.com/ppescher - ppescher@hotmail.com)
7 //
8 // The contents of this file are subject to the Artistic License (the "License").
9 // You may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at:
11 // http://www.opensource.org/licenses/artistic-license.html
13 // If you find this code useful, credits would be nice!
15 /////////////////////////////////////////////////////////////////////////////
17 #include "stdafx.h"
18 #include "ResizableComboBox.h"
20 #ifdef _DEBUG
21 #define new DEBUG_NEW
22 #undef THIS_FILE
23 static char THIS_FILE[] = __FILE__;
24 #endif
26 /////////////////////////////////////////////////////////////////////////////
27 // CResizableComboBox
29 CResizableComboBox::CResizableComboBox()
31 m_bClipMaxHeight = TRUE;
32 m_bIntegralHeight = TRUE;
35 CResizableComboBox::~CResizableComboBox()
37 if (m_ctrlListBox.GetSafeHwnd() != NULL)
38 m_ctrlListBox.UnsubclassWindow();
42 BEGIN_MESSAGE_MAP(CResizableComboBox, CComboBox)
43 //{{AFX_MSG_MAP(CResizableComboBox)
44 ON_WM_CTLCOLOR()
45 //}}AFX_MSG_MAP
46 END_MESSAGE_MAP()
48 /////////////////////////////////////////////////////////////////////////////
49 // CResizableComboBox message handlers
51 HBRUSH CResizableComboBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
53 HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor);
55 if (nCtlColor == CTLCOLOR_LISTBOX)
57 if (!(GetStyle() & CBS_SIMPLE)
58 && (m_ctrlListBox.m_hWnd == NULL))
60 TRACE("ComboLBox: 0x%08X\n", pWnd->m_hWnd);
62 // attach to the owned listbox
63 m_ctrlListBox.m_pOwnerCombo = this;
64 m_ctrlListBox.SubclassWindow(pWnd->m_hWnd);
68 return hbr;
71 LRESULT CResizableComboBox::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
73 switch (message)
75 case CB_GETDROPPEDCONTROLRECT:
76 *(LPRECT)lParam = m_rectDropDown;
77 MapWindowPoints(NULL, (LPRECT)lParam);
78 return TRUE;
81 LRESULT lResult = CComboBox::WindowProc(message, wParam, lParam);
83 // if listbox is attached, update horizontal extent
85 switch (message)
87 case CB_INSERTSTRING:
88 case CB_ADDSTRING:
89 if (lResult != CB_ERR && lResult != CB_ERRSPACE)
90 UpdateHorizontalExtent((LPCTSTR)lParam);
91 break;
93 case CB_DIR:
94 if (lResult != CB_ERR && lResult != CB_ERRSPACE)
95 InitHorizontalExtent();
96 break;
98 case CB_RESETCONTENT:
99 InitHorizontalExtent();
100 break;
103 return lResult;
106 void CResizableComboBox::InitHorizontalExtent()
108 CClientDC dc(this);
109 CFont* pOldFont = dc.SelectObject(GetFont());
111 CString str;
113 m_iExtent = 0;
114 int n = GetCount();
115 for (int i=0; i<n; i++)
117 GetLBText(i, str);
118 int cx = dc.GetTextExtent(str).cx;
119 if (cx > m_iExtent)
120 m_iExtent = cx;
123 SetHorizontalExtent(m_iExtent
124 + LOWORD(GetDialogBaseUnits()));
126 dc.SelectObject(pOldFont);
129 void CResizableComboBox::UpdateHorizontalExtent(LPCTSTR szText)
131 CClientDC dc(this);
132 CFont* pOldFont = dc.SelectObject(GetFont());
134 int cx = dc.GetTextExtent(szText, lstrlen(szText)).cx;
135 if (cx > m_iExtent)
137 m_iExtent = cx;
139 SetHorizontalExtent(m_iExtent
140 + LOWORD(GetDialogBaseUnits()));
143 dc.SelectObject(pOldFont);
146 void CResizableComboBox::PreSubclassWindow()
148 ASSERT(GetStyle() & CBS_NOINTEGRALHEIGHT);
150 InitHorizontalExtent();
152 GetDroppedControlRect(&m_rectDropDown);
153 ::MapWindowPoints(NULL, GetSafeHwnd(),
154 (LPPOINT)&m_rectDropDown, 2);
156 CComboBox::PreSubclassWindow();
159 int CResizableComboBox::MakeIntegralHeight(const int height)
161 int inth = height; // integral height (result)
162 int availh = height; // available height
163 int n = GetCount();
165 DWORD dwStyle = GetStyle();
167 if (!m_bIntegralHeight || n == 0)
168 return inth;
170 if (dwStyle & CBS_OWNERDRAWVARIABLE)
172 inth = 0; // try to reach availh by integral steps
173 int i = 0;
174 // use items below the first visible
175 for (i=GetTopIndex(); availh>0 && i<n; i++)
177 int h = GetItemHeight(i);
178 if (h == CB_ERR)
179 break;
181 inth += h;
182 availh -= h;
184 // to fill the remaining height, use items above
185 for (i=GetTopIndex()-1; availh>0 && i>=0; i--)
187 int h = GetItemHeight(i);
188 if (h == CB_ERR)
189 break;
191 inth += h;
192 availh -= h;
194 // scroll into view
195 SetTopIndex(i);
197 if (!m_bClipMaxHeight) // it can be higher than all the items
199 // to fill the remaining height, use last item
200 int h = GetItemHeight(n-1);
201 if (h != CB_ERR)
203 inth += availh - availh % h;
207 else
209 // every item has the same height (take the first)
210 int h = GetItemHeight(0);
211 if (h != CB_ERR && n != CB_ERR)
213 int rows = availh / h;
214 // can't be higher than all the items
215 if (m_bClipMaxHeight && rows > n)
216 rows = n;
217 inth = rows * h;
218 // scroll into view
219 if (n - rows < GetTopIndex())
220 SetTopIndex(n-rows);
224 return inth;