void CResizableComboBox::PreSubclassWindow() { ASSERT(GetStyle() & CBS_NOINTEGRALHEIGHT); InitHorizontalExtent(); GetDroppedControlRect(&m_rectDropDown); ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT)&m_rectDropDown, 2); CComboBox::PreSubclassWindow(); }
//------------------------------------------------------------------------ //! CBN_DROPDOWN message handler called when the CComboBox control //! is expanded into a dropdown list. Used to restrict the width of //! the dropdown list to the max width. //------------------------------------------------------------------------ void CGridEditorComboBox::OnDropDown() { int itemHeight = GetItemHeight(-1); int nNumEntries = GetCount(); // Resize combobox according to actual element count int visibleItemCount = m_MaxHeightItems < nNumEntries ? m_MaxHeightItems : nNumEntries; // min(m_MaxHeightItems, nNumEntries); CRect rectExpanded; GetClientRect(rectExpanded); rectExpanded.bottom += visibleItemCount * GetItemHeight(0); rectExpanded.bottom += GetSystemMetrics(SM_CYEDGE) * 2; // top & bottom edges SetWindowPos(NULL, // not relative to any other windows 0, 0, // TopLeft corner doesn't change rectExpanded.Width(), rectExpanded.Height(), // existing width, new height SWP_NOMOVE | SWP_NOZORDER // don't move box or change z-ordering. ); // Resize combo-box width to fit contents int nMaxItemWidth = 0; CString str; // Find max-width of the elements CDC* pDC = GetDC(); CFont* pFont = GetFont(); CFont* pOldFont = pDC->SelectObject(pFont); for (int i = 0; i < nNumEntries; i++) { GetLBText(i, str); int nLength = pDC->GetTextExtent(str).cx; nMaxItemWidth = nMaxItemWidth > nLength ? nMaxItemWidth : nLength; // max(nMaxItemWidth, nLength); if (nMaxItemWidth > m_MaxWidthPixels) { nMaxItemWidth = m_MaxWidthPixels; break; } } // Check if there are so many elements that we need space for a vertical scrollbar CRect rect; GetDroppedControlRect(&rect); if (rect.Height() <= nNumEntries*GetItemHeight(0)) nMaxItemWidth +=::GetSystemMetrics(SM_CXVSCROLL); // Add margin space to the calculations nMaxItemWidth += pDC->GetTextExtent(_T("0")).cx; pDC->SelectObject(pOldFont); ReleaseDC(pDC); SetDroppedWidth(nMaxItemWidth); SetItemHeight(-1, itemHeight); }
int COXMultiComboBox::AdjustToFitSize() { int nResult; if(m_bFitToSize) { int nTotalWidth=GetTotalWidth()+2*GetSystemMetrics(SM_CXBORDER); int nTotalHeight=GetTotalHeight(); int nBorderHeight=GetSystemMetrics(SM_CYBORDER); int nScrollbarHeight=GetSystemMetrics(SM_CYHSCROLL); CRect rcDrop; GetDroppedControlRect(&rcDrop); if((nTotalHeight > rcDrop.Height()-2*nBorderHeight) || ((nTotalWidth > rcDrop.Width()) && (nTotalHeight > rcDrop.Height()-nScrollbarHeight-2*nBorderHeight))) { nTotalWidth+=::GetSystemMetrics(SM_CXVSCROLL); } int nScreenWidth=::GetSystemMetrics(SM_CXSCREEN); nTotalWidth=nTotalWidth>nScreenWidth ? nScreenWidth : nTotalWidth; nResult=SetDroppedWidth(nTotalWidth); } else nResult=SetDroppedWidth(1); if(nResult!=CB_ERR) { // ... To indicate that the scrollbars has to be re-adjusted m_fSizeChanged = TRUE; // Redraws the listbox if(::IsWindow(m_ComboLBox.m_hWnd)) { m_ComboLBox.RedrawWindow(NULL,NULL, RDW_ERASE|RDW_INVALIDATE|RDW_ERASENOW|RDW_UPDATENOW|RDW_FRAME); } } return nResult; }
// This message is handle to get the HWND of the listbox of the combobox // as there is no otherway to get it(refer to Q65881, Q131845 in Knowledge Base) // The listbox handle is needed to set the scrollbar to it if needed, and to // handle its WM_HSCROLL message. HBRUSH COXMultiComboBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) // --- In : pDC : device context (See standard help for detaled info) // pWnd : Pointer Cwnd obejct of the window whose background // has to be painted. // nCtlColor : Type of the control // --- Out : // --- Returns : Brush to supply to paint the background // --- Effect : The listbox's HWND is got and sunclassed to COXComboLBox // window object. The listbox style is modified to // have WS_HSCROLL. The horizontal extent of the listbox is // set and scrollbars are shown are hided depending on the // width and height. Scroll range for horizantal scrollbar // is set and also m_NumCharsPerPage is set. { HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor); // Handle only if the type of control is Listbox only if ((nCtlColor == CTLCOLOR_LISTBOX) && m_fSizeChanged) { // ... To stop this code run unneccessorily m_fSizeChanged = FALSE; if(m_ComboLBox.GetSafeHwnd()==NULL) { m_ComboLBox.SubclassWindow(pWnd->GetSafeHwnd()); m_ComboLBox.ModifyStyle(0,WS_HSCROLL); TEXTMETRIC tm; GetTextMetrics(pDC->m_hDC,&tm); m_nLineWidth = tm.tmAveCharWidth; } int nTotalWidth = GetTotalWidth(); // ... Sets horizontal extent to total width m_ComboLBox.SetHorizontalExtent(nTotalWidth); CRect rcDrop; GetDroppedControlRect(&rcDrop); int iTotalItemHeight = 0; for (int i = 0; i < m_ComboLBox.GetCount(); i++) iTotalItemHeight += m_ComboLBox.GetItemHeight(i); if (rcDrop.Height() < iTotalItemHeight || m_bFitToSize) m_ComboLBox.AdjustHScroll(); if(GetStyle()&CBS_DROPDOWN) { CRect rcWnd; m_ComboLBox.GetWindowRect(&rcWnd); m_ComboLBox.MoveWindow(&rcWnd,TRUE); } if(m_ComboLBox.m_fHorzScrollVisible) { CRect rcClient; m_ComboLBox.GetClientRect(&rcClient); m_nPageWidth = rcClient.Width(); // setting sroll info SCROLLINFO si; si.cbSize = sizeof(si); si.nPos = 0; si.nMin = 0; si.nMax = nTotalWidth; si.nPage = m_nPageWidth; si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS ; m_ComboLBox.SetScrollInfo(SB_HORZ,&si,TRUE); m_ComboLBox.SendMessage(WM_HSCROLL,SB_TOP,0L); } m_ComboLBox.RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_FRAME); } return hbr; }