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