--- /dev/null
+// ResizableComboLBox.cpp : implementation file\r
+//\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Copyright (C) 2000-2004 by Paolo Messina\r
+// (http://www.geocities.com/ppescher - ppescher@hotmail.com)\r
+//\r
+// The contents of this file are subject to the Artistic License (the "License").\r
+// You may not use this file except in compliance with the License. \r
+// You may obtain a copy of the License at:\r
+// http://www.opensource.org/licenses/artistic-license.html\r
+//\r
+// If you find this code useful, credits would be nice!\r
+//\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+#include "stdafx.h"\r
+#include "ResizableComboLBox.h"\r
+#include "ResizableComboBox.h"\r
+\r
+#ifdef _DEBUG\r
+#define new DEBUG_NEW\r
+#undef THIS_FILE\r
+static char THIS_FILE[] = __FILE__;\r
+#endif\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// CResizableComboLBox\r
+\r
+CResizableComboLBox::CResizableComboLBox()\r
+{\r
+ m_dwAddToStyle = WS_THICKFRAME;\r
+ m_dwAddToStyleEx = 0;//WS_EX_CLIENTEDGE;\r
+ m_bSizing = FALSE;\r
+}\r
+\r
+CResizableComboLBox::~CResizableComboLBox()\r
+{\r
+\r
+}\r
+\r
+\r
+BEGIN_MESSAGE_MAP(CResizableComboLBox, CWnd)\r
+ //{{AFX_MSG_MAP(CResizableComboLBox)\r
+ ON_WM_MOUSEMOVE()\r
+ ON_WM_LBUTTONDOWN()\r
+ ON_WM_LBUTTONUP()\r
+ ON_WM_NCHITTEST()\r
+ ON_WM_CAPTURECHANGED()\r
+ ON_WM_WINDOWPOSCHANGING()\r
+ ON_WM_WINDOWPOSCHANGED()\r
+ //}}AFX_MSG_MAP\r
+END_MESSAGE_MAP()\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// CResizableComboLBox message handlers\r
+\r
+void CResizableComboLBox::PreSubclassWindow() \r
+{\r
+ CWnd::PreSubclassWindow();\r
+\r
+ InitializeControl();\r
+}\r
+\r
+BOOL CResizableComboLBox::IsRTL()\r
+{\r
+ return (GetExStyle() & WS_EX_LAYOUTRTL);\r
+}\r
+\r
+void CResizableComboLBox::InitializeControl()\r
+{\r
+ CRect rect;\r
+ m_pOwnerCombo->GetWindowRect(&rect);\r
+ m_sizeAfterSizing.cx = rect.Width();\r
+ m_sizeAfterSizing.cy = -rect.Height();\r
+ m_pOwnerCombo->GetDroppedControlRect(&rect);\r
+ m_sizeAfterSizing.cy += rect.Height();\r
+ m_sizeMin.cy = m_sizeAfterSizing.cy-2;\r
+\r
+ // change window's style\r
+ ModifyStyleEx(0, m_dwAddToStyleEx);\r
+ ModifyStyle(0, m_dwAddToStyle, SWP_FRAMECHANGED);\r
+\r
+ // count hscroll if present\r
+ if (GetStyle() & WS_HSCROLL)\r
+ m_sizeAfterSizing.cy += GetSystemMetrics(SM_CYHSCROLL);\r
+\r
+ SetWindowPos(NULL, 0, 0, m_sizeAfterSizing.cx, m_sizeAfterSizing.cy,\r
+ SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE);\r
+}\r
+\r
+void CResizableComboLBox::OnMouseMove(UINT nFlags, CPoint point) \r
+{\r
+ CPoint pt = point;\r
+ MapWindowPoints(NULL, &pt, 1); // to screen coord\r
+\r
+ if (!m_bSizing)\r
+ {\r
+ // since mouse is captured we need to change the cursor manually\r
+ LRESULT ht = SendMessage(WM_NCHITTEST, 0, MAKELPARAM(pt.x, pt.y));\r
+ SendMessage(WM_SETCURSOR, (WPARAM)m_hWnd, MAKELPARAM(ht, WM_MOUSEMOVE));\r
+\r
+ CWnd::OnMouseMove(nFlags, point);\r
+ return;\r
+ }\r
+\r
+ // during resize\r
+ CRect rect = m_rcBeforeSizing;\r
+ CSize relMove = pt - m_ptBeforeSizing;\r
+\r
+ switch (m_nHitTest)\r
+ {\r
+ case HTBOTTOM:\r
+ rect.bottom += relMove.cy;\r
+ break;\r
+ case HTBOTTOMRIGHT:\r
+ rect.bottom += relMove.cy;\r
+ rect.right += relMove.cx;\r
+ break;\r
+ case HTRIGHT:\r
+ rect.right += relMove.cx;\r
+ break;\r
+ case HTBOTTOMLEFT:\r
+ rect.bottom += relMove.cy;\r
+ rect.left += relMove.cx;\r
+ break;\r
+ case HTLEFT:\r
+ rect.left += relMove.cx;\r
+ break;\r
+ }\r
+\r
+ // move window (if right-aligned it needs refresh)\r
+ UINT nCopyFlag = (GetExStyle() & WS_EX_RIGHT) ? SWP_NOCOPYBITS : 0;\r
+ SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(),\r
+ SWP_NOACTIVATE|SWP_NOZORDER|nCopyFlag);\r
+}\r
+\r
+void CResizableComboLBox::OnLButtonDown(UINT nFlags, CPoint point) \r
+{\r
+ CPoint pt = point;\r
+ MapWindowPoints(NULL, &pt, 1); // to screen coord\r
+\r
+ LRESULT ht = SendMessage(WM_NCHITTEST, 0, MAKELPARAM(pt.x, pt.y));\r
+\r
+ if (ht == HTBOTTOM || ht == HTRIGHT || ht == HTBOTTOMRIGHT\r
+ || ht == HTLEFT || ht == HTBOTTOMLEFT)\r
+ {\r
+ // start resizing\r
+ m_bSizing = TRUE;\r
+ m_nHitTest = ht;\r
+ GetWindowRect(&m_rcBeforeSizing);\r
+ m_ptBeforeSizing = pt;\r
+ }\r
+ else\r
+ CWnd::OnLButtonDown(nFlags, point);\r
+}\r
+\r
+void CResizableComboLBox::OnLButtonUp(UINT nFlags, CPoint point) \r
+{\r
+ CWnd::OnLButtonUp(nFlags, point);\r
+\r
+ EndSizing();\r
+}\r
+\r
+#if _MSC_VER < 1400\r
+UINT CResizableComboLBox::OnNcHitTest(CPoint point) \r
+#else\r
+LRESULT CResizableComboLBox::OnNcHitTest(CPoint point) \r
+#endif\r
+{\r
+ CRect rcClient;\r
+ GetClientRect(&rcClient);\r
+ MapWindowPoints(NULL, &rcClient);\r
+\r
+ // ask for default hit-test value\r
+ UINT_PTR ht = CWnd::OnNcHitTest(point);\r
+\r
+ // disable improper resizing (based on layout setting)\r
+ switch (ht)\r
+ {\r
+ case HTTOPRIGHT:\r
+ if (!IsRTL() && point.y > rcClient.top)\r
+ ht = HTRIGHT;\r
+ else\r
+ ht = HTBORDER;\r
+ break;\r
+ case HTTOPLEFT:\r
+ if (IsRTL() && point.y > rcClient.top)\r
+ ht = HTLEFT;\r
+ else\r
+ ht = HTBORDER;\r
+ break;\r
+\r
+ case HTBOTTOMLEFT:\r
+ if (!IsRTL() && point.y > rcClient.bottom)\r
+ ht = HTBOTTOM;\r
+ else if (!IsRTL())\r
+ ht = HTBORDER;\r
+ break;\r
+ case HTBOTTOMRIGHT:\r
+ if (IsRTL() && point.y > rcClient.bottom)\r
+ ht = HTBOTTOM;\r
+ else if (IsRTL())\r
+ ht = HTBORDER;\r
+ break;\r
+\r
+ case HTLEFT:\r
+ if (!IsRTL())\r
+ ht = HTBORDER;\r
+ break;\r
+ case HTRIGHT:\r
+ if (IsRTL())\r
+ ht = HTBORDER;\r
+ break;\r
+\r
+ case HTTOP:\r
+ ht = HTBORDER;\r
+ }\r
+\r
+ return ht;\r
+}\r
+\r
+void CResizableComboLBox::OnCaptureChanged(CWnd *pWnd) \r
+{\r
+ EndSizing();\r
+\r
+ CWnd::OnCaptureChanged(pWnd);\r
+}\r
+\r
+void CResizableComboLBox::EndSizing()\r
+{\r
+ m_bSizing = FALSE;\r
+ CRect rect;\r
+ GetWindowRect(&rect);\r
+ m_sizeAfterSizing = rect.Size();\r
+}\r
+\r
+void CResizableComboLBox::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos) \r
+{\r
+ if (!m_bSizing)\r
+ {\r
+ // restore the size when the drop-down list becomes visible\r
+ lpwndpos->cx = m_sizeAfterSizing.cx;\r
+ lpwndpos->cy = m_sizeAfterSizing.cy;\r
+ }\r
+ ApplyLimitsToPos(lpwndpos);\r
+\r
+ CWnd::OnWindowPosChanging(lpwndpos);\r
+}\r
+\r
+void CResizableComboLBox::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos) \r
+{\r
+ // default implementation sends a WM_SIZE message\r
+ // that can change the size again to force integral height\r
+\r
+ // since we do that manually during resize, we should also\r
+ // update the horizontal scrollbar \r
+ SendMessage(WM_HSCROLL, SB_ENDSCROLL, 0);\r
+\r
+ GetWindowRect(&m_pOwnerCombo->m_rectDropDown);\r
+ ::MapWindowPoints(NULL, m_pOwnerCombo->GetSafeHwnd(),\r
+ (LPPOINT)&m_pOwnerCombo->m_rectDropDown, 2);\r
+\r
+ CWnd::OnWindowPosChanged(lpwndpos);\r
+}\r
+\r
+void CResizableComboLBox::ApplyLimitsToPos(WINDOWPOS* lpwndpos)\r
+{\r
+ //TRACE(">H w(%d)\n", lpwndpos->cy);\r
+ // to adjust horizontally, use window rect\r
+\r
+ // min width can't be less than combo's\r
+ CRect rect;\r
+ m_pOwnerCombo->GetWindowRect(&rect);\r
+ m_sizeMin.cx = rect.Width();\r
+\r
+ // apply horizontal limits\r
+ if (lpwndpos->cx < m_sizeMin.cx)\r
+ lpwndpos->cx = m_sizeMin.cx;\r
+\r
+ // fix horizontal alignment\r
+ rect = CRect(0, 0, lpwndpos->cx, lpwndpos->cy);\r
+ m_pOwnerCombo->MapWindowPoints(NULL, &rect);\r
+ lpwndpos->x = rect.left;\r
+\r
+ // to adjust vertically, use client rect\r
+\r
+ // get client rect\r
+ rect = CRect(CPoint(lpwndpos->x, lpwndpos->y),\r
+ CSize(lpwndpos->cx, lpwndpos->cy));\r
+ SendMessage(WM_NCCALCSIZE, FALSE, (LPARAM)&rect);\r
+ CSize sizeClient = rect.Size();\r
+\r
+ // apply vertical limits\r
+ if (sizeClient.cy < m_sizeMin.cy)\r
+ sizeClient.cy = m_sizeMin.cy;\r
+\r
+ //TRACE(">H c(%d)\n", sizeClient.cy);\r
+ // adjust height, if needed\r
+ sizeClient.cy = m_pOwnerCombo->MakeIntegralHeight(sizeClient.cy);\r
+ //TRACE(">H c(%d)\n", sizeClient.cy);\r
+\r
+ // back to window rect\r
+ rect = CRect(0, 0, 1, sizeClient.cy);\r
+ DWORD dwStyle = GetStyle();\r
+ ::AdjustWindowRectEx(&rect, dwStyle, FALSE, GetExStyle());\r
+ lpwndpos->cy = rect.Height();\r
+ if (dwStyle & WS_HSCROLL)\r
+ lpwndpos->cy += GetSystemMetrics(SM_CYHSCROLL);\r
+\r
+ //TRACE("H c(%d) w(%d)\n", sizeClient.cy, lpwndpos->cy);\r
+}\r
+\r