fix 32-bit filenames
[TortoiseGit.git] / ext / ResizableLib / ResizableComboLBox.cpp
blobda3a2407bfcb0f7e900a9a0dab960c90cef0f448
1 // ResizableComboLBox.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 "ResizableComboLBox.h"
19 #include "ResizableComboBox.h"
21 #ifdef _DEBUG
22 #define new DEBUG_NEW
23 #undef THIS_FILE
24 static char THIS_FILE[] = __FILE__;
25 #endif
27 /////////////////////////////////////////////////////////////////////////////
28 // CResizableComboLBox
30 CResizableComboLBox::CResizableComboLBox()
32 m_dwAddToStyle = WS_THICKFRAME;
33 m_dwAddToStyleEx = 0;//WS_EX_CLIENTEDGE;
34 m_bSizing = FALSE;
37 CResizableComboLBox::~CResizableComboLBox()
43 BEGIN_MESSAGE_MAP(CResizableComboLBox, CWnd)
44 //{{AFX_MSG_MAP(CResizableComboLBox)
45 ON_WM_MOUSEMOVE()
46 ON_WM_LBUTTONDOWN()
47 ON_WM_LBUTTONUP()
48 ON_WM_NCHITTEST()
49 ON_WM_CAPTURECHANGED()
50 ON_WM_WINDOWPOSCHANGING()
51 ON_WM_WINDOWPOSCHANGED()
52 //}}AFX_MSG_MAP
53 END_MESSAGE_MAP()
55 /////////////////////////////////////////////////////////////////////////////
56 // CResizableComboLBox message handlers
58 void CResizableComboLBox::PreSubclassWindow()
60 CWnd::PreSubclassWindow();
62 InitializeControl();
65 BOOL CResizableComboLBox::IsRTL()
67 return (GetExStyle() & WS_EX_LAYOUTRTL);
70 void CResizableComboLBox::InitializeControl()
72 CRect rect;
73 m_pOwnerCombo->GetWindowRect(&rect);
74 m_sizeAfterSizing.cx = rect.Width();
75 m_sizeAfterSizing.cy = -rect.Height();
76 m_pOwnerCombo->GetDroppedControlRect(&rect);
77 m_sizeAfterSizing.cy += rect.Height();
78 m_sizeMin.cy = m_sizeAfterSizing.cy-2;
80 // change window's style
81 ModifyStyleEx(0, m_dwAddToStyleEx);
82 ModifyStyle(0, m_dwAddToStyle, SWP_FRAMECHANGED);
84 // count hscroll if present
85 if (GetStyle() & WS_HSCROLL)
86 m_sizeAfterSizing.cy += GetSystemMetrics(SM_CYHSCROLL);
88 SetWindowPos(NULL, 0, 0, m_sizeAfterSizing.cx, m_sizeAfterSizing.cy,
89 SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE);
92 void CResizableComboLBox::OnMouseMove(UINT nFlags, CPoint point)
94 CPoint pt = point;
95 MapWindowPoints(NULL, &pt, 1); // to screen coord
97 if (!m_bSizing)
99 // since mouse is captured we need to change the cursor manually
100 LRESULT ht = SendMessage(WM_NCHITTEST, 0, MAKELPARAM(pt.x, pt.y));
101 SendMessage(WM_SETCURSOR, (WPARAM)m_hWnd, MAKELPARAM(ht, WM_MOUSEMOVE));
103 CWnd::OnMouseMove(nFlags, point);
104 return;
107 // during resize
108 CRect rect = m_rcBeforeSizing;
109 CSize relMove = pt - m_ptBeforeSizing;
111 switch (m_nHitTest)
113 case HTBOTTOM:
114 rect.bottom += relMove.cy;
115 break;
116 case HTBOTTOMRIGHT:
117 rect.bottom += relMove.cy;
118 rect.right += relMove.cx;
119 break;
120 case HTRIGHT:
121 rect.right += relMove.cx;
122 break;
123 case HTBOTTOMLEFT:
124 rect.bottom += relMove.cy;
125 rect.left += relMove.cx;
126 break;
127 case HTLEFT:
128 rect.left += relMove.cx;
129 break;
132 // move window (if right-aligned it needs refresh)
133 UINT nCopyFlag = (GetExStyle() & WS_EX_RIGHT) ? SWP_NOCOPYBITS : 0;
134 SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(),
135 SWP_NOACTIVATE|SWP_NOZORDER|nCopyFlag);
138 void CResizableComboLBox::OnLButtonDown(UINT nFlags, CPoint point)
140 CPoint pt = point;
141 MapWindowPoints(NULL, &pt, 1); // to screen coord
143 LRESULT ht = SendMessage(WM_NCHITTEST, 0, MAKELPARAM(pt.x, pt.y));
145 if (ht == HTBOTTOM || ht == HTRIGHT || ht == HTBOTTOMRIGHT
146 || ht == HTLEFT || ht == HTBOTTOMLEFT)
148 // start resizing
149 m_bSizing = TRUE;
150 m_nHitTest = ht;
151 GetWindowRect(&m_rcBeforeSizing);
152 m_ptBeforeSizing = pt;
154 else
155 CWnd::OnLButtonDown(nFlags, point);
158 void CResizableComboLBox::OnLButtonUp(UINT nFlags, CPoint point)
160 CWnd::OnLButtonUp(nFlags, point);
162 EndSizing();
165 #if _MSC_VER < 1400
166 UINT CResizableComboLBox::OnNcHitTest(CPoint point)
167 #else
168 LRESULT CResizableComboLBox::OnNcHitTest(CPoint point)
169 #endif
171 CRect rcClient;
172 GetClientRect(&rcClient);
173 MapWindowPoints(NULL, &rcClient);
175 // ask for default hit-test value
176 UINT_PTR ht = CWnd::OnNcHitTest(point);
178 // disable improper resizing (based on layout setting)
179 switch (ht)
181 case HTTOPRIGHT:
182 if (!IsRTL() && point.y > rcClient.top)
183 ht = HTRIGHT;
184 else
185 ht = HTBORDER;
186 break;
187 case HTTOPLEFT:
188 if (IsRTL() && point.y > rcClient.top)
189 ht = HTLEFT;
190 else
191 ht = HTBORDER;
192 break;
194 case HTBOTTOMLEFT:
195 if (!IsRTL() && point.y > rcClient.bottom)
196 ht = HTBOTTOM;
197 else if (!IsRTL())
198 ht = HTBORDER;
199 break;
200 case HTBOTTOMRIGHT:
201 if (IsRTL() && point.y > rcClient.bottom)
202 ht = HTBOTTOM;
203 else if (IsRTL())
204 ht = HTBORDER;
205 break;
207 case HTLEFT:
208 if (!IsRTL())
209 ht = HTBORDER;
210 break;
211 case HTRIGHT:
212 if (IsRTL())
213 ht = HTBORDER;
214 break;
216 case HTTOP:
217 ht = HTBORDER;
220 return ht;
223 void CResizableComboLBox::OnCaptureChanged(CWnd *pWnd)
225 EndSizing();
227 CWnd::OnCaptureChanged(pWnd);
230 void CResizableComboLBox::EndSizing()
232 m_bSizing = FALSE;
233 CRect rect;
234 GetWindowRect(&rect);
235 m_sizeAfterSizing = rect.Size();
238 void CResizableComboLBox::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
240 if (!m_bSizing)
242 // restore the size when the drop-down list becomes visible
243 lpwndpos->cx = m_sizeAfterSizing.cx;
244 lpwndpos->cy = m_sizeAfterSizing.cy;
246 ApplyLimitsToPos(lpwndpos);
248 CWnd::OnWindowPosChanging(lpwndpos);
251 void CResizableComboLBox::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos)
253 // default implementation sends a WM_SIZE message
254 // that can change the size again to force integral height
256 // since we do that manually during resize, we should also
257 // update the horizontal scrollbar
258 SendMessage(WM_HSCROLL, SB_ENDSCROLL, 0);
260 GetWindowRect(&m_pOwnerCombo->m_rectDropDown);
261 ::MapWindowPoints(NULL, m_pOwnerCombo->GetSafeHwnd(),
262 (LPPOINT)&m_pOwnerCombo->m_rectDropDown, 2);
264 CWnd::OnWindowPosChanged(lpwndpos);
267 void CResizableComboLBox::ApplyLimitsToPos(WINDOWPOS* lpwndpos)
269 //TRACE(">H w(%d)\n", lpwndpos->cy);
270 // to adjust horizontally, use window rect
272 // min width can't be less than combo's
273 CRect rect;
274 m_pOwnerCombo->GetWindowRect(&rect);
275 m_sizeMin.cx = rect.Width();
277 // apply horizontal limits
278 if (lpwndpos->cx < m_sizeMin.cx)
279 lpwndpos->cx = m_sizeMin.cx;
281 // fix horizontal alignment
282 rect = CRect(0, 0, lpwndpos->cx, lpwndpos->cy);
283 m_pOwnerCombo->MapWindowPoints(NULL, &rect);
284 lpwndpos->x = rect.left;
286 // to adjust vertically, use client rect
288 // get client rect
289 rect = CRect(CPoint(lpwndpos->x, lpwndpos->y),
290 CSize(lpwndpos->cx, lpwndpos->cy));
291 SendMessage(WM_NCCALCSIZE, FALSE, (LPARAM)&rect);
292 CSize sizeClient = rect.Size();
294 // apply vertical limits
295 if (sizeClient.cy < m_sizeMin.cy)
296 sizeClient.cy = m_sizeMin.cy;
298 //TRACE(">H c(%d)\n", sizeClient.cy);
299 // adjust height, if needed
300 sizeClient.cy = m_pOwnerCombo->MakeIntegralHeight(sizeClient.cy);
301 //TRACE(">H c(%d)\n", sizeClient.cy);
303 // back to window rect
304 rect = CRect(0, 0, 1, sizeClient.cy);
305 DWORD dwStyle = GetStyle();
306 ::AdjustWindowRectEx(&rect, dwStyle, FALSE, GetExStyle());
307 lpwndpos->cy = rect.Height();
308 if (dwStyle & WS_HSCROLL)
309 lpwndpos->cy += GetSystemMetrics(SM_CYHSCROLL);
311 //TRACE("H c(%d) w(%d)\n", sizeClient.cy, lpwndpos->cy);