/** * @file XTPControlListBox.cpp * * @copyright * (c) 1998-2025 Codejock Software, All Rights Reserved. * * This source file is the property of Codejock Software and must not be * redistributed by any means without the explicit written permission of * Codejock Software. * * The use of this source code is governed by the terms and conditions specified * in the Toolkit Pro license agreement. Codejock Software grants you, as a * single software developer, the limited right to use this software on one * computer only. * * Contact Information: * support@codejock.com * http://www.codejock.com * */ #include "stdafx.h" #include "Common/XTPTypeId.h" #include "Common/XTPCasting.h" #include "Common/XTPFramework.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPSynchro.h" #include "Common/XTPApplication.h" #include "Common/XTPSingleton.h" #include "Common/XTPGdiObjects.h" #include "Common/XTPDrawHelpers.h" #include "Common/PropExchange/XTPPropExchangeSection.h" #include "Common/XTPPropExchange.h" #include "Common/XTPHookManager.h" #include "Common/XTPColorManager.h" #include "CommandBars/XTPCommandBarsDefines.h" #include "CommandBars/XTPPaintManager.h" #include "CommandBars/XTPControl.h" #include "CommandBars/XTPCommandBar.h" #include "CommandBars/XTPMouseManager.h" #include "CommandBars/XTPControlListBox.h" #include "Common/Base/Diagnostic/XTPDisableNoisyWarnings.h" #ifdef _DEBUG # undef THIS_FILE static char THIS_FILE[] = __FILE__; # define new DEBUG_NEW #endif class CXTPControlListBoxCtrl : public CListBox { friend class CXTPControlListBox; protected: void OnSelChanged(); protected: //{{AFX_CODEJOCK_PRIVATE DECLARE_MESSAGE_MAP() //{{AFX_MSG(CXTPControlListBoxCtrl) afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnPaint(); afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); //}}AFX_MSG //}}AFX_CODEJOCK_PRIVATE public: CXTPControlListBox* m_pControl; }; IMPLEMENT_XTP_CONTROL(CXTPControlListBox, CXTPControl) ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CXTPControlListBox::CXTPControlListBox() { m_pListBox = new CXTPControlListBoxCtrl; m_pListBox->m_pControl = this; m_pListBox->CreateEx(0, _T("LISTBOX"), NULL, WS_POPUP | WS_VSCROLL | WS_CLIPCHILDREN | LBS_NOTIFY, CRect(0, 0, 0, 0), 0, 0); m_nListBoxLinesMin = 1; m_nListBoxLinesMax = 12; m_nWidth = XTP_DPI_X(100); m_bMultiplSel = FALSE; m_bMouseLocked = FALSE; } CXTPControlListBox::~CXTPControlListBox() { if (m_pListBox) { delete m_pListBox; } } CListBox* CXTPControlListBox::GetListCtrl() const { _ASSERTE(this); return m_pListBox; } void CXTPControlListBox::SetWidth(int nWidth) { m_nWidth = nWidth; } void CXTPControlListBox::SetMultiplSel(BOOL bMultiplSel) { m_bMultiplSel = bMultiplSel; m_pListBox->DestroyWindow(); m_pListBox->CreateEx(0, _T("LISTBOX"), NULL, WS_POPUP | WS_VSCROLL | WS_CLIPCHILDREN | LBS_NOTIFY | (m_bMultiplSel ? LBS_MULTIPLESEL : 0), CRect(0, 0, 0, 0), 0, 0); } void CXTPControlListBox::SetLinesMinMax(int nMin, int nMax) { m_nListBoxLinesMin = nMin; m_nListBoxLinesMax = nMax; } void CXTPControlListBox::SetRect(CRect rcControl) { _ASSERTE(this); if (m_rcControl == rcControl && m_pListBox->GetParent() == m_pParent) { return; } m_rcControl = rcControl; m_pListBox->EnableWindow(GetEnabled()); m_pListBox->ModifyStyle(WS_POPUP, WS_CHILD); m_pListBox->SetParent(m_pParent); m_pListBox->MoveWindow(rcControl); m_pListBox->SetWindowPos(0, 0, 0, 0, 0, UINT(SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | (!IsVisible() ? SWP_HIDEWINDOW : SWP_SHOWWINDOW))); } void CXTPControlListBox::SetParent(CXTPCommandBar* pParent) { if (pParent != m_pParent && (pParent && pParent->GetSafeHwnd())) { m_pListBox->ModifyStyle(WS_POPUP, WS_CHILD); m_pListBox->SetParent(pParent); } CXTPControl::SetParent(pParent); } void CXTPControlListBox::OnEnabledChanged() { _ASSERTE(this); if (m_pListBox->GetSafeHwnd()) m_pListBox->EnableWindow(GetEnabled()); } CSize CXTPControlListBox::GetSize(CDC* /*pDC*/) { _ASSERTE(this); m_pListBox->SetFont(GetPaintManager()->GetIconFont(), FALSE); int nItemHeight = m_pListBox->GetItemHeight(0); int nHeight = min(m_nListBoxLinesMax, max(m_nListBoxLinesMin, m_pListBox->GetCount())) * nItemHeight; int nWidth = m_nWidth; return CSize(nWidth, nHeight); } void CXTPControlListBox::Draw(CDC* /*pDC*/) { } BOOL CXTPControlListBox::IsFocused() const { return m_bSelected; } BOOL CXTPControlListBox::OnSetSelected(int bSelected) { if (!CXTPControl::OnSetSelected(bSelected)) return FALSE; if (bSelected && !m_bMouseLocked) { XTPMouseManager()->LockMouseMove(); m_bMouseLocked = TRUE; } else if (!bSelected && m_bMouseLocked) { XTPMouseManager()->UnlockMouseMove(); m_bMouseLocked = FALSE; } return TRUE; } BOOL CXTPControlListBox::OnHookKeyDown(UINT nChar, LPARAM lParam) { _ASSERTE(this); if (nChar == VK_RETURN || nChar == VK_TAB) return FALSE; if (nChar == VK_ESCAPE) return FALSE; int nSel = m_pListBox->GetCurSel(); m_pListBox->SendMessage(WM_KEYDOWN, nChar, lParam); if (nSel != m_pListBox->GetCurSel()) { m_pListBox->OnSelChanged(); } return TRUE; } void CXTPControlListBox::OnClick(BOOL bKeyboard, CPoint pt) { if (bKeyboard) { OnExecute(); } else CXTPControl::OnClick(bKeyboard, pt); } void CXTPControlListBox::OnCalcDynamicSize(DWORD dwMode) { CXTPControl::OnCalcDynamicSize(dwMode); if (m_bMultiplSel) { m_pListBox->SelItemRange(FALSE, 0, m_pListBox->GetCount() - 1); } else { m_pListBox->SetCurSel(-1); } NotifySite(XTP_LBN_POPUP); } void CXTPControlListBox::Copy(CXTPControl* pControl, BOOL bRecursive) { if (this != pControl) { ASSERT_KINDOF(CXTPControlListBox, pControl); CXTPControl::Copy(pControl, bRecursive); m_nWidth = ((CXTPControlListBox*)pControl)->m_nWidth; SetMultiplSel(((CXTPControlListBox*)pControl)->m_bMultiplSel); m_nListBoxLinesMax = ((CXTPControlListBox*)pControl)->m_nListBoxLinesMax; m_nListBoxLinesMin = ((CXTPControlListBox*)pControl)->m_nListBoxLinesMin; CListBox* pListBox = ((CXTPControlListBox*)pControl)->GetListCtrl(); int nCount = pListBox->m_hWnd ? pListBox->GetCount() : 0; m_pListBox->ResetContent(); for (int i = 0; i < nCount; i++) { CString str; pListBox->GetText(i, str); m_pListBox->AddString(str); } } } void CXTPControlListBox::DoPropExchange(CXTPPropExchange* pPX) { CXTPControl::DoPropExchange(pPX); CString str; PX_DPI_X_Int(pPX, _T("Width"), m_nWidth, 100); PX_Bool(pPX, _T("MultiplSel"), m_bMultiplSel, FALSE); PX_Int(pPX, _T("ListBoxLinesMax"), m_nListBoxLinesMax, 12); PX_Int(pPX, _T("ListBoxLinesMin"), m_nListBoxLinesMin, 1); CXTPPropExchangeSection secItems(pPX->GetSection(_T("Items"))); if (pPX->IsStoring()) { int nCount = m_pListBox->m_hWnd ? m_pListBox->GetCount() : 0; secItems->WriteCount(XTPToDWORDChecked(nCount)); for (int i = 0; i < nCount; i++) { m_pListBox->GetText(i, str); CString strSection; strSection.Format(_T("Item%i"), i); PX_String(&secItems, strSection, str, _T("")); } } else { SetMultiplSel(m_bMultiplSel); DWORD nNewCount = secItems->ReadCount(); for (DWORD i = 0; i < nNewCount; i++) { CString strSection; strSection.Format(_T("Item%i"), XTPToInt(i)); PX_String(&secItems, strSection, str, _T("")); m_pListBox->AddString(str); } } } #include "Common/Base/Diagnostic/XTPBeginAfxMap.h" BEGIN_MESSAGE_MAP(CXTPControlListBoxCtrl, CListBox) ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_LBUTTONDBLCLK() ON_WM_MOUSEMOVE() ON_WM_ERASEBKGND() ON_WM_PAINT() ON_WM_VSCROLL() END_MESSAGE_MAP() #include "Common/Base/Diagnostic/XTPEndAfxMap.h" void CXTPControlListBoxCtrl::OnLButtonDown(UINT /*nFlags*/, CPoint /*point*/) { } void CXTPControlListBoxCtrl::OnLButtonUp(UINT /*nFlags*/, CPoint /*point*/) { m_pControl->OnExecute(); } void CXTPControlListBoxCtrl::OnLButtonDblClk(UINT /*nFlags*/, CPoint /*point*/) { } void CXTPControlListBoxCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { SetRedraw(FALSE); CListBox::OnVScroll(nSBCode, nPos, pScrollBar); SetRedraw(TRUE); Invalidate(); UpdateWindow(); // repaint the scroll bar. ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); } void CXTPControlListBoxCtrl::OnPaint() { CPaintDC dcPaint(this); CXTPClientRect rc(this); CXTPBufferDC dc(dcPaint, rc); dc.FillSolidRect(rc, GetXtremeColor(COLOR_WINDOW)); CWnd::DefWindowProc(WM_PAINT, (WPARAM)dc.m_hDC, 0); } BOOL CXTPControlListBoxCtrl::OnEraseBkgnd(CDC* /*pDC*/) { return TRUE; } void CXTPControlListBoxCtrl::OnMouseMove(UINT nFlags, CPoint point) { BOOL bOutside; UINT nItem = ItemFromPoint(point, bOutside); if (!bOutside) { SetCurSel(XTPToIntChecked(nItem)); SetSel(XTPToIntChecked(nItem), TRUE); OnSelChanged(); } MapWindowPoints(m_pControl->GetParent(), &point, 1); m_pControl->GetParent()->OnMouseMove(nFlags, point); } void CXTPControlListBoxCtrl::OnSelChanged() { if (m_pControl->m_bMultiplSel) { int nSel = GetCurSel(); if (nSel != LB_ERR) { SelItemRange(FALSE, nSel + 1, GetCount() - 1); if (nSel != 0) SelItemRange(TRUE, 0, nSel); else SetSel(0, TRUE); } else { SelItemRange(FALSE, 0, GetCount() - 1); } } m_pControl->NotifySite(XTP_LBN_SELCHANGE); } /////////////////////////////////////////////////////////////////// // CXTPControlListBoxInfo IMPLEMENT_XTP_CONTROL(CXTPControlStatic, CXTPControl) CXTPControlStatic::CXTPControlStatic() { m_nWidth = 0; } void CXTPControlStatic::SetWidth(int nWidth) { m_nWidth = nWidth; } CSize CXTPControlStatic::GetSize(CDC* pDC) { CXTPPaintManager* pPaintManager = GetPaintManager(); BOOL bVert = pPaintManager->GetControlTextOrientation(this) == xtpBarTextVertical; CXTPEmptyRect rcText; CSize sz = pPaintManager->DrawControlText(pDC, this, &rcText, FALSE, bVert, FALSE, FALSE); if (bVert) return CSize(max(XTP_DPI_X(22), sz.cx), max(m_nWidth, sz.cy)); return CSize(max(m_nWidth, sz.cx), max(XTP_DPI_Y(22), sz.cy)); } void CXTPControlStatic::Draw(CDC* pDC) { CXTPPaintManager* pPaintManager = GetPaintManager(); BOOL bVert = pPaintManager->GetControlTextOrientation(this) == xtpBarTextVertical; CRect rcText = GetRect(); pDC->SetTextColor(pPaintManager->GetControlTextColor(this)); pPaintManager->DrawControlText(pDC, this, &rcText, TRUE, bVert, TRUE, FALSE); } void CXTPControlStatic::Copy(CXTPControl* pControl, BOOL bRecursive) { if (this != pControl) { ASSERT_KINDOF(CXTPControlStatic, pControl); CXTPControl::Copy(pControl, bRecursive); m_nWidth = ((CXTPControlStatic*)pControl)->m_nWidth; } } void CXTPControlStatic::DoPropExchange(CXTPPropExchange* pPX) { CXTPControl::DoPropExchange(pPX); PX_DPI_X_Int(pPX, _T("Width"), m_nWidth, 0); }