OSDN Git Service

Align key "puttykeyfile" with gitextension
[tortoisegit/TortoiseGitJp.git] / ext / ResizableLib / ResizableComboBox.cpp
1 // ResizableComboBox.cpp : implementation file\r
2 //\r
3 /////////////////////////////////////////////////////////////////////////////\r
4 //\r
5 // Copyright (C) 2000-2004 by Paolo Messina\r
6 // (http://www.geocities.com/ppescher - ppescher@hotmail.com)\r
7 //\r
8 // The contents of this file are subject to the Artistic License (the "License").\r
9 // You may not use this file except in compliance with the License. \r
10 // You may obtain a copy of the License at:\r
11 // http://www.opensource.org/licenses/artistic-license.html\r
12 //\r
13 // If you find this code useful, credits would be nice!\r
14 //\r
15 /////////////////////////////////////////////////////////////////////////////\r
16 \r
17 #include "stdafx.h"\r
18 #include "ResizableComboBox.h"\r
19 \r
20 #ifdef _DEBUG\r
21 #define new DEBUG_NEW\r
22 #undef THIS_FILE\r
23 static char THIS_FILE[] = __FILE__;\r
24 #endif\r
25 \r
26 /////////////////////////////////////////////////////////////////////////////\r
27 // CResizableComboBox\r
28 \r
29 CResizableComboBox::CResizableComboBox()\r
30 {\r
31         m_bClipMaxHeight = TRUE;\r
32         m_bIntegralHeight = TRUE;\r
33 }\r
34 \r
35 CResizableComboBox::~CResizableComboBox()\r
36 {\r
37         if (m_ctrlListBox.GetSafeHwnd() != NULL)\r
38                 m_ctrlListBox.UnsubclassWindow();\r
39 }\r
40 \r
41 \r
42 BEGIN_MESSAGE_MAP(CResizableComboBox, CComboBox)\r
43         //{{AFX_MSG_MAP(CResizableComboBox)\r
44         ON_WM_CTLCOLOR()\r
45         //}}AFX_MSG_MAP\r
46 END_MESSAGE_MAP()\r
47 \r
48 /////////////////////////////////////////////////////////////////////////////\r
49 // CResizableComboBox message handlers\r
50 \r
51 HBRUSH CResizableComboBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) \r
52 {\r
53         HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor);\r
54         \r
55         if (nCtlColor == CTLCOLOR_LISTBOX)\r
56         {\r
57                 if (!(GetStyle() & CBS_SIMPLE)\r
58                         && (m_ctrlListBox.m_hWnd == NULL))\r
59                 {\r
60                         TRACE("ComboLBox: 0x%08X\n", pWnd->m_hWnd);\r
61 \r
62                         // attach to the owned listbox\r
63                         m_ctrlListBox.m_pOwnerCombo = this;\r
64                         m_ctrlListBox.SubclassWindow(pWnd->m_hWnd);\r
65                 }\r
66         }\r
67 \r
68         return hbr;\r
69 }\r
70 \r
71 LRESULT CResizableComboBox::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) \r
72 {\r
73         switch (message)\r
74         {\r
75         case CB_GETDROPPEDCONTROLRECT:\r
76                 *(LPRECT)lParam = m_rectDropDown;\r
77                 MapWindowPoints(NULL, (LPRECT)lParam);\r
78                 return TRUE;\r
79         }\r
80 \r
81         LRESULT lResult = CComboBox::WindowProc(message, wParam, lParam);\r
82 \r
83         // if listbox is attached, update horizontal extent\r
84 \r
85         switch (message)\r
86         {\r
87         case CB_INSERTSTRING:\r
88         case CB_ADDSTRING:\r
89                 if (lResult != CB_ERR && lResult != CB_ERRSPACE)\r
90                         UpdateHorizontalExtent((LPCTSTR)lParam);\r
91                 break;\r
92 \r
93         case CB_DIR:\r
94                 if (lResult != CB_ERR && lResult != CB_ERRSPACE)\r
95                         InitHorizontalExtent();\r
96                 break;\r
97 \r
98         case CB_RESETCONTENT:\r
99                 InitHorizontalExtent();\r
100                 break;\r
101         }\r
102 \r
103         return lResult;\r
104 }\r
105 \r
106 void CResizableComboBox::InitHorizontalExtent()\r
107 {\r
108         CClientDC dc(this);\r
109         CFont* pOldFont = dc.SelectObject(GetFont());\r
110 \r
111         CString str;\r
112         \r
113         m_iExtent = 0;\r
114         int n = GetCount();\r
115         for (int i=0; i<n; i++)\r
116         {\r
117                 GetLBText(i, str);\r
118                 int cx = dc.GetTextExtent(str).cx;\r
119                 if (cx > m_iExtent)\r
120                         m_iExtent = cx;\r
121         }\r
122 \r
123         SetHorizontalExtent(m_iExtent\r
124                 + LOWORD(GetDialogBaseUnits()));\r
125 \r
126         dc.SelectObject(pOldFont);\r
127 }\r
128 \r
129 void CResizableComboBox::UpdateHorizontalExtent(LPCTSTR szText)\r
130 {\r
131         CClientDC dc(this);\r
132         CFont* pOldFont = dc.SelectObject(GetFont());\r
133 \r
134         int cx = dc.GetTextExtent(szText, lstrlen(szText)).cx;\r
135         if (cx > m_iExtent)\r
136         {\r
137                 m_iExtent = cx;\r
138 \r
139                 SetHorizontalExtent(m_iExtent\r
140                         + LOWORD(GetDialogBaseUnits()));\r
141         }\r
142 \r
143         dc.SelectObject(pOldFont);\r
144 }\r
145 \r
146 void CResizableComboBox::PreSubclassWindow() \r
147 {\r
148         ASSERT(GetStyle() & CBS_NOINTEGRALHEIGHT);\r
149 \r
150         InitHorizontalExtent();\r
151         \r
152         GetDroppedControlRect(&m_rectDropDown);\r
153         ::MapWindowPoints(NULL, GetSafeHwnd(),\r
154                 (LPPOINT)&m_rectDropDown, 2);\r
155         \r
156         CComboBox::PreSubclassWindow();\r
157 }\r
158 \r
159 int CResizableComboBox::MakeIntegralHeight(const int height)\r
160 {\r
161         int inth = height;      // integral height (result)\r
162         int availh = height;    // available height\r
163         int n = GetCount();\r
164 \r
165         DWORD dwStyle = GetStyle();\r
166 \r
167         if (!m_bIntegralHeight || n == 0)\r
168                 return inth;\r
169         \r
170         if (dwStyle & CBS_OWNERDRAWVARIABLE)\r
171         {\r
172                 inth = 0;       // try to reach availh by integral steps\r
173                 int i = 0;\r
174                 // use items below the first visible\r
175                 for (i=GetTopIndex(); availh>0 && i<n; i++)\r
176                 {\r
177                         int h = GetItemHeight(i);\r
178                         if (h == CB_ERR)\r
179                                 break;\r
180 \r
181                         inth += h;\r
182                         availh -= h;\r
183                 }\r
184                 // to fill the remaining height, use items above\r
185                 for (i=GetTopIndex()-1; availh>0 && i>=0; i--)\r
186                 {\r
187                         int h = GetItemHeight(i);\r
188                         if (h == CB_ERR)\r
189                                 break;\r
190 \r
191                         inth += h;\r
192                         availh -= h;\r
193                 }\r
194                 // scroll into view\r
195                 SetTopIndex(i);\r
196 \r
197                 if (!m_bClipMaxHeight) // it can be higher than all the items\r
198                 {\r
199                         // to fill the remaining height, use last item\r
200                         int h = GetItemHeight(n-1);\r
201                         if (h != CB_ERR)\r
202                         {\r
203                                 inth += availh - availh % h;\r
204                         }\r
205                 }\r
206         }\r
207         else\r
208         {\r
209                 // every item has the same height (take the first)\r
210                 int h = GetItemHeight(0);\r
211                 if (h != CB_ERR && n != CB_ERR)\r
212                 {\r
213                         int rows = availh / h;\r
214                         // can't be higher than all the items\r
215                         if (m_bClipMaxHeight && rows > n)\r
216                                 rows = n;\r
217                         inth = rows * h;\r
218                         // scroll into view\r
219                         if (n - rows < GetTopIndex())\r
220                                 SetTopIndex(n-rows);\r
221                 }\r
222         }\r
223 \r
224         return inth;\r
225 }\r