/** * @file XTPEditListBox.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/XTPResourceManager.h" #include "Common/XTPColorManager.h" #include "Common/XTPDrawHelpers.h" #include "Common/XTPWinThemeWrapper.h" #include "Common/XTPVC80Helpers.h" #include "Common/XTPMaskEditT.h" #include "Common/XTPResourceImage.h" #include "Common/ScrollBar/XTPScrollBase.h" #include "Common/ScrollBar/XTPScrollBarCtrl.h" #include "Common/ScrollBar/XTPScrollable.h" #include "Controls/Util/XTPControlTheme.h" #include "Controls/Resource.h" #include "Controls/Defines.h" #include "Controls/Util/XTPUtil.h" #include "Controls/Util/XTPGlobal.h" #include "Controls/Button/XTPButton.h" #include "Controls/Button/XTPButtonTheme.h" #include "Controls/Edit/XTPEdit.h" #include "Controls/Edit/XTPBrowseEdit.h" #include "Controls/ListBox/XTPListBox.h" #include "Controls/ListBox/XTPEditListBox.h" #include "Common/Base/Diagnostic/XTPDisableNoisyWarnings.h" #ifdef _DEBUG # define new DEBUG_NEW # undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define XTP_IDC_GROUP_EDIT 200 ///////////////////////////////////////////////////////////////////////////// // CXTPEditListBox ///////////////////////////////////////////////////////////////////////////// const int BTN_OFFSET = 22; CXTPEditListBox::CXTPEditListBox() : m_pParentWnd(NULL) , m_bEnableEdit(true) { m_pItemEdit = NULL; m_nIndex = -1; m_bNewItem = FALSE; m_strItemDefaultText.Empty(); SetListEditStyle(XTP_IDS_DIRECTORIES, LBS_XTP_CHOOSEDIR); } CXTPEditListBox::~CXTPEditListBox() { } IMPLEMENT_DYNAMIC(CXTPEditListBox, CXTPListBox) #include "Common/Base/Diagnostic/XTPBeginAfxMap.h" BEGIN_MESSAGE_MAP(CXTPEditListBox, CXTPListBox) //{{AFX_MSG_MAP(CXTPEditListBox) ON_LBN_XTP_LABELEDITEND(XTP_IDC_LBOX_EDIT, OnEndLabelEdit) ON_LBN_XTP_NEWITEM(XTP_IDC_GROUP_EDIT, OnNewItem) ON_LBN_XTP_DELETEITEM(XTP_IDC_GROUP_EDIT, OnDeleteItem) ON_LBN_XTP_MOVEITEMUP(XTP_IDC_GROUP_EDIT, OnMoveItemUp) ON_LBN_XTP_MOVEITEMDOWN(XTP_IDC_GROUP_EDIT, OnMoveItemDown) ON_WM_LBUTTONDBLCLK() ON_WM_LBUTTONDOWN() ON_WM_NCLBUTTONDOWN() ON_WM_NCMBUTTONDOWN() ON_WM_NCRBUTTONDOWN() ON_WM_WINDOWPOSCHANGED() ON_LBN_XTP_LABELEDITCANCEL(XTP_IDC_LBOX_EDIT, OnEndLabelEdit) ON_LBN_XTP_ONBROWSE(XTP_IDC_LBOX_EDIT, OnItemBrowse) ON_WM_ENABLE() ON_WM_SHOWWINDOW() ON_WM_MOUSEWHEEL() ON_WM_SIZE() //}}AFX_MSG_MAP END_MESSAGE_MAP() #include "Common/Base/Diagnostic/XTPEndAfxMap.h" COLORREF CXTPEditListBox::GetBackColor() { return IsWindowEnabled() ? GetXtremeColor(COLOR_WINDOW) : GetXtremeColor(COLOR_3DFACE); } void CXTPEditListBox::OnSize(UINT nType, int cx, int cy) { if (m_pItemEdit) { m_pItemEdit->EndLabelEdit(); Invalidate(FALSE); } CXTPListBox::OnSize(nType, cx, cy); } BOOL CXTPEditListBox::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) { if (m_pItemEdit) { m_pItemEdit->EndLabelEdit(); Invalidate(FALSE); } return CXTPListBox::OnMouseWheel(nFlags, zDelta, pt); } void CXTPEditListBox::OnEndLabelEdit() { // Get a pointer to the owner window. CWnd* pOwner = GetOwner(); _ASSERTE(pOwner); if (!pOwner) return; if (!m_pItemEdit) return; m_strItemText = m_pItemEdit->m_strWindowText; if (m_bNewItem) { // Delete the temp string. DeleteString(static_cast(m_nIndex)); // If the text string is empty, then send a cancel message. if (m_strItemText.IsEmpty()) { pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_XTP_LABELEDITCANCEL), XTPToLPARAM(m_hWnd)); m_nIndex = LB_ERR; } // The user has entered text, send the new item message // and insert the new string. else { m_nIndex = AddString(m_strItemText); // NB: SetTopIndex below causes some confusion if you have editing session, change // content and then double click on another item - the result looks like misplaced edit // control // SetTopIndex(m_nIndex); pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_XTP_NEWITEM), XTPToLPARAM(m_hWnd)); } } else { // set the index to the current selection. m_nIndex = GetCurSel(); // Get the text for the selected item. CString strItemText; GetText(m_nIndex, strItemText); // If the new string is the same as the old string, // then send a cancel message. if (strItemText == m_strItemText) { pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_XTP_LABELEDITCANCEL), XTPToLPARAM(m_hWnd)); } // The user has updated the text string, delete the // existing string and replace it with the new text. else { DWORD_PTR dwData = GetItemData(m_nIndex); DeleteString(static_cast(m_nIndex)); InsertString(m_nIndex, m_strItemText); SetItemData(m_nIndex, dwData); // NB: SetTopIndex below causes some confusion if you have editing session, change // content and then double click on another item - the result looks like misplaced edit // control // SetTopIndex(m_nIndex); pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_XTP_LABELEDITEND), XTPToLPARAM(m_hWnd)); } } // Set the focus back to the listbox. SetCurSel(m_nIndex); SetFocus(); m_pItemEdit = NULL; } // Basically, save any edited state, then pass the browse message to the parent window void CXTPEditListBox::OnItemBrowse() { m_nIndex = GetCurSel(); // Current index. // Set the focus back to the listbox. SetFocus(); CWnd* pOwner = GetOwner(); _ASSERTE(pOwner); // Send notification to owner. if (pOwner) pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_XTP_ONBROWSE), XTPToLPARAM(m_hWnd)); } // This member function will enable editing for the a list box item. void CXTPEditListBox::EditItem(int iItem) { SetFocus(); SetCurSel(iItem); m_nIndex = iItem; EditListItem(FALSE); } void CXTPEditListBox::GetEditItemText() { GetText(m_nIndex, m_strItemText); } void CXTPEditListBox::SetEditText(LPCTSTR pcszText) { if (m_pItemEdit == NULL) { return; } m_pItemEdit->SetWindowText(pcszText); } void CXTPEditListBox::EditListItem(BOOL bNewItem) { if (!m_bEnableEdit) return; CWnd* pOwner = GetOwner(); _ASSERTE(pOwner); if (!pOwner) return; // Turn off redraw until we are ready to // create the edit field. SetRedraw(FALSE); // flush the item text string. m_strItemText = m_strItemDefaultText; // if this is a new item, add a temporary string // to the list box and set the selection to it. This // is where the in place edit box will appear. if (bNewItem || GetCurSel() == LB_ERR) { pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_XTP_PRENEWITEM), XTPToLPARAM(m_hWnd)); m_nIndex = AddString(m_strItemText); SetCurSel(m_nIndex); m_bNewItem = TRUE; } // get the text for the currently selected // item and set the new flag to FALSE. else { m_bNewItem = FALSE; int iCount = GetCount(); m_nIndex = GetCurSel(); if (m_nIndex >= iCount || iCount <= 0) { m_nIndex = LB_ERR; SetCurSel(LB_ERR); // turn redraw back. SetRedraw(TRUE); Invalidate(); return; } GetEditItemText(); } // turn redraw back. SetRedraw(TRUE); Invalidate(); if (m_dwLStyle & LBS_XTP_BROWSE_ONLY) { // Send notification to owner. pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_XTP_ONBROWSE), XTPToLPARAM(m_hWnd)); return; } // Get the size of the currently selected item. CRect rcItem; GetItemRect(m_nIndex, rcItem); rcItem.InflateRect(-XTP_DPI_X(2), XTP_DPI_Y(2)); // create the edit box. m_pItemEdit = CreateEditControl(rcItem); // if defined, set the filter for the item edit control. if (!m_strFilter.IsEmpty()) { m_pItemEdit->SetDlgFilter(m_strFilter); } if (!m_strInitialDir.IsEmpty()) { m_pItemEdit->SetDlgInitialDir(m_strInitialDir); } } CXTPItemEdit* CXTPEditListBox::CreateEditControl(CRect rcItem) { CXTPItemEdit* pItemEdit = new CXTPItemEdit(); VERIFY(pItemEdit->Create(this, rcItem, m_strItemText, m_dwLStyle, true)); return pItemEdit; } void CXTPEditListBox::OnNewItem() { EditListItem(TRUE); } void CXTPEditListBox::OnLButtonDblClk(UINT nFlags, CPoint point) { CWnd::OnLButtonDblClk(nFlags, point); EditListItem(FALSE); } void CXTPEditListBox::OnDeleteItem() { DeleteItem(); } void CXTPEditListBox::DeleteItem() { CWnd* pOwner = GetOwner(); _ASSERTE(pOwner); if (!pOwner) return; // Send notification to owner that we are about to delete the item pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_XTP_PREDELETEITEM), XTPToLPARAM(m_hWnd)); int nCurIndex = GetCurSel(); // Current index. // If there is a valid selection made... if (nCurIndex != LB_ERR) { // Remove the new current item. int nCount = DeleteString(static_cast(nCurIndex)); if ((nCount != LB_ERR) && (nCurIndex < nCount)) { SetCurSel(nCurIndex); } else { SetCurSel(nCurIndex - 1); } } // Set the focus back to the listbox. SetFocus(); // Send notification to owner. pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_XTP_DELETEITEM), XTPToLPARAM(m_hWnd)); } void CXTPEditListBox::OnMoveItemUp() { int nIndex = GetCurSel(); if (nIndex != LB_ERR) MoveItemUp(nIndex); } void CXTPEditListBox::MoveItemUp(int nIndex) { m_nIndex = nIndex; // Current index. int nNewIndex = m_nIndex - 1; // New index. // If there is a valid selection made, and the // selection is not the first item and... if ((m_nIndex != LB_ERR) && (m_nIndex != 0)) { // Save the string for the item we are // going to swap position with. CString strItem; GetText(nNewIndex, strItem); // Save any item data. DWORD_PTR dwNewData = GetItemData(nNewIndex); // Remove both the new and current // index items... DeleteString(static_cast(nNewIndex)); // then swap and re-insert them into // the list box. InsertString(m_nIndex, strItem); // Restore any item data. SetItemData(m_nIndex, dwNewData); // Select the item at the new index. SetCurSel(nNewIndex); } // Set the focus back to the listbox. SetFocus(); CWnd* pOwner = GetOwner(); _ASSERTE(pOwner); if (!pOwner) return; // Send notification to owner. pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_XTP_MOVEITEMUP), XTPToLPARAM(m_hWnd)); } void CXTPEditListBox::OnMoveItemDown() { int nIndex = GetCurSel(); if (nIndex != LB_ERR) MoveItemDown(nIndex); } void CXTPEditListBox::MoveItemDown(int nIndex) { m_nIndex = nIndex; // Current index. int nNewIndex = m_nIndex + 1; // New index. // If there is a valid selection made, and the // selection is not the last item and... if ((m_nIndex != LB_ERR) && (nNewIndex < GetCount())) { // Save the string for the current // selection. CString strCurItem; GetText(m_nIndex, strCurItem); // Save any item data. DWORD_PTR dwCurData = GetItemData(m_nIndex); // Remove both the new and current // index items... DeleteString(static_cast(m_nIndex)); // then swap and re-insert them into // the list box. InsertString(nNewIndex, strCurItem); // Restore any item data. SetItemData(nNewIndex, dwCurData); // Select the item at the new index. SetCurSel(nNewIndex); } // Set the focus back to the listbox. SetFocus(); CWnd* pOwner = GetOwner(); _ASSERTE(pOwner); if (!pOwner) return; // Send notification to owner. pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_XTP_MOVEITEMDOWN), XTPToLPARAM(m_hWnd)); } void CXTPEditListBox::SetListEditStyle(UINT nTitle, DWORD dwLStyle /*= LBS_XTP_DEFAULT*/) { CString strTitle; XTPResourceManager()->LoadString(&strTitle, nTitle); SetListEditStyle(strTitle, dwLStyle); } void CXTPEditListBox::SetListEditStyle(LPCTSTR lpszTitle, DWORD dwLStyle /*= LBS_XTP_DEFAULT*/) { m_strTitle = lpszTitle; m_dwLStyle = dwLStyle; if (m_editGroup.GetSafeHwnd()) { m_editGroup.SetWindowText(m_strTitle); } } void CXTPEditListBox::Initialize(bool bAutoFont /*= true*/) { CXTPListBox::Initialize(bAutoFont); // get a pointer to the parent window. m_pParentWnd = GetParent(); _ASSERTE(m_pParentWnd); // must be valid. // Create the edit toolbar group. if (!HasToolbar()) return; // Create the toolbar. if (!CreateEditGroup(bAutoFont)) return; // Resize the edit list which will also cause WM_WINDOWPOSCHANGED // to be called to position the toolbar. CXTPWindowRect rcWindow(this); rcWindow.top += XTP_DPI_Y(BTN_OFFSET) + ::GetSystemMetrics(SM_CXEDGE); m_pParentWnd->ScreenToClient(&rcWindow); ::SetWindowPos(GetSafeHwnd(), NULL, rcWindow.left, rcWindow.top, rcWindow.Width(), rcWindow.Height(), SWP_FRAMECHANGED | SWP_NOZORDER); } BOOL CXTPEditListBox::CreateEditGroup(bool bAutoFont) { // Create the edit button group that appears at the top of the // list edit control. DWORD dwStyle = (GetStyle() & WS_VISIBLE) | WS_CHILD | SS_CENTERIMAGE | SS_LEFT | SS_NOTIFY; if (!m_editGroup.CreateEx(WS_EX_STATICEDGE, _T("Static"), m_strTitle, dwStyle, CRect(0, 0, 0, 0), GetParent(), XTP_IDC_GROUP_EDIT)) { TRACE0("Unable to create caption.\n"); return FALSE; } m_editGroup.m_bShowUpDownButtons = ((m_dwLStyle & LBS_XTP_HIDE_UP_DOWN) == 0); m_editGroup.m_bShowNewDeleteButtons = ((m_dwLStyle & LBS_XTP_ONLY_UP_DOWN) == 0); m_editGroup.SetOwner(this); m_editGroup.Initialize(bAutoFont); // enable the window depending on the list box enabled state. m_editGroup.EnableWindow(IsWindowEnabled()); return TRUE; } BOOL CXTPEditListBox::PreTranslateMessage(MSG* pMsg) { // Send message to edit window if active. if (m_pItemEdit && ::IsWindow(m_pItemEdit->m_hWnd)) { if (pMsg->wParam == VK_TAB) { SetFocus(); return CWnd::PreTranslateMessage(pMsg); } return m_pItemEdit->PreTranslateMessage(pMsg); } if (pMsg->message == WM_KEYUP) { if (pMsg->wParam == VK_DELETE && GetCurSel() != LB_ERR) { OnDeleteItem(); } if (pMsg->wParam == VK_INSERT) { OnNewItem(); } } if (pMsg->message == WM_SYSKEYUP) { if ((pMsg->wParam == VK_UP) && (::GetKeyState(VK_MENU) < 0) && GetCurSel() != LB_ERR) { OnMoveItemUp(); } if ((pMsg->wParam == VK_DOWN) && (::GetKeyState(VK_MENU) < 0) && GetCurSel() != LB_ERR) { OnMoveItemDown(); } } return CWnd::PreTranslateMessage(pMsg); } void CXTPEditListBox::OnLButtonDown(UINT nFlags, CPoint point) { CXTPListBox::OnLButtonDown(nFlags, point); m_nIndex = GetCurSel(); if (m_nIndex >= GetCount()) { SetCurSel(GetCount() - 1); GetOwner()->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_SELCHANGE), XTPToLPARAM(m_hWnd)); } CRect rcItem; if (GetItemRect(m_nIndex, rcItem) != LB_ERR) { if (!rcItem.PtInRect(point)) { CWnd* pOwner = GetOwner(); _ASSERTE(pOwner); if (!pOwner) return; SetCurSel(-1); pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_SELCHANGE), XTPToLPARAM(m_hWnd)); } } } void CXTPEditListBox::OnNcLButtonDown(UINT nHitTest, CPoint point) { if (m_pItemEdit) { m_pItemEdit->DestroyWindow(); m_pItemEdit = NULL; } CListBox::OnNcLButtonDown(nHitTest, point); } void CXTPEditListBox::OnNcMButtonDown(UINT nHitTest, CPoint point) { if (m_pItemEdit) { m_pItemEdit->DestroyWindow(); m_pItemEdit = NULL; } CListBox::OnNcMButtonDown(nHitTest, point); } void CXTPEditListBox::OnNcRButtonDown(UINT nHitTest, CPoint point) { if (m_pItemEdit) { m_pItemEdit->DestroyWindow(); m_pItemEdit = NULL; } CListBox::OnNcRButtonDown(nHitTest, point); } void CXTPEditListBox::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos) { CXTPListBox::OnWindowPosChanged(lpwndpos); // adjust the toolbar size and location. RecalcLayout(); } void CXTPEditListBox::RecalcLayout() { if (HasToolbar() && ::IsWindow(m_editGroup.m_hWnd)) { _ASSERTE(m_pParentWnd); // must be valid. CXTPWindowRect rcWindow(this); m_pParentWnd->ScreenToClient(&rcWindow); // move the group edit control. rcWindow.top -= XTP_DPI_Y(BTN_OFFSET); rcWindow.bottom = rcWindow.top + XTP_DPI_Y(BTN_OFFSET); ::SetWindowPos(m_editGroup.m_hWnd, NULL, rcWindow.left, rcWindow.top, rcWindow.Width(), rcWindow.Height(), SWP_FRAMECHANGED); } } void CXTPEditListBox::RefreshMetrics() { m_editGroup.RefreshMetrics(); CXTPListBox::RefreshMetrics(); } void CXTPEditListBox::OnEnable(BOOL bEnable) { CXTPListBox::OnEnable(bEnable); if (HasToolbar() && ::IsWindow(m_editGroup.m_hWnd)) m_editGroup.EnableWindow(bEnable); } void CXTPEditListBox::OnShowWindow(BOOL bShow, UINT nStatus) { CXTPListBox::OnShowWindow(bShow, nStatus); if (HasToolbar() && ::IsWindow(m_editGroup.m_hWnd)) m_editGroup.ShowWindow(bShow ? SW_SHOW : SW_HIDE); } ///////////////////////////////////////////////////////////////////////////// // CXTPEditListBoxToolBar ///////////////////////////////////////////////////////////////////////////// CXTPEditListBoxToolBar::CXTPEditListBoxToolBar() : m_bShowUpDownButtons(true) , m_bShowNewDeleteButtons(true) , m_bEnableEdit(true) { m_theme = xtpControlThemeDefault; } CXTPEditListBoxToolBar::~CXTPEditListBoxToolBar() { } IMPLEMENT_DYNAMIC(CXTPEditListBoxToolBar, CStatic) #include "Common/Base/Diagnostic/XTPBeginAfxMap.h" BEGIN_MESSAGE_MAP(CXTPEditListBoxToolBar, CStatic) //{{AFX_MSG_MAP(CXTPEditListBoxToolBar) ON_BN_CLICKED(XTP_IDC_BTN_NEW, OnButtonNew) ON_BN_CLICKED(XTP_IDC_BTN_DELETE, OnButtonDelete) ON_BN_CLICKED(XTP_IDC_BTN_UP, OnButtonUp) ON_BN_CLICKED(XTP_IDC_BTN_DOWN, OnButtonDown) ON_WM_WINDOWPOSCHANGED() ON_WM_ERASEBKGND() ON_WM_PAINT() ON_WM_ENABLE() ON_WM_SHOWWINDOW() ON_WM_NCPAINT() //}}AFX_MSG_MAP ON_MESSAGE(WM_XTP_SETCONTROLTHEME, OnSetTheme) END_MESSAGE_MAP() #include "Common/Base/Diagnostic/XTPEndAfxMap.h" BOOL CXTPEditListBoxToolBar::PreTranslateMessage(MSG* pMsg) { // Let the ToolTip process this message. m_tooltip.RelayEvent(pMsg); return CStatic::PreTranslateMessage(pMsg); } static UINT _arButtonID[] = { XTP_IDC_BTN_NEW, XTP_IDC_BTN_DELETE, XTP_IDC_BTN_UP, XTP_IDC_BTN_DOWN, }; void CXTPEditListBoxToolBar::MoveButtons() { if (!::IsWindow(m_hWnd)) return; // Set the initial size for the first button. CXTPClientRect rcClient(this); rcClient.left = rcClient.right - XTP_DPI_X(BTN_OFFSET); for (int i = _countof(m_arButton) - 1; i >= 0; --i) { if (::IsWindow(m_arButton[i].GetSafeHwnd())) { m_arClipRect[i] = rcClient; ::SetWindowPos(m_arButton[i].GetSafeHwnd(), NULL, rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), SWP_FRAMECHANGED); rcClient.OffsetRect(-XTP_DPI_X(BTN_OFFSET), 0); } else { m_arClipRect[i] = CRect(0, 0, 0, 0); } } Invalidate(); } void CXTPEditListBoxToolBar::SetButtonTheme(XTPControlTheme eTheme) { for (int i = 0; i < _countof(m_arButton); ++i) { if (::IsWindow(m_arButton[i].m_hWnd)) { if (m_arButton[i].SetTheme(eTheme)) { CXTPButtonTheme* pTheme = m_arButton[i].GetTheme(); if (pTheme) { pTheme->EnableToolbarStyle(TRUE); } } } } } void CXTPEditListBoxToolBar::Initialize(bool bAutoFont /*= true*/) { // Create the ToolTip control. m_tooltip.Create(this); m_tooltip.Activate(TRUE); for (int i = 0; i < _countof(m_arButton); ++i) { if ((!m_bShowNewDeleteButtons) && ((i == 0) || (i == 1))) continue; if ((!m_bShowUpDownButtons) && ((i == 2) || (i == 3))) continue; if (!m_arButton[i].Create(NULL, WS_CHILD | WS_VISIBLE | BS_ICON | BS_CENTER | BS_VCENTER, CRect(0, 0, 0, 0), this, _arButtonID[i])) { TRACE0("Unable to create edit button.\n"); continue; } CString strToolTip; CXTPResourceManager::AssertValid( XTPResourceManager()->LoadString(&strToolTip, _arButtonID[i])); // Add tooltips to group buttons. m_tooltip.AddTool(&m_arButton[i], strToolTip); // make sure the button is Windows XP theme compatible using // the toolbar button theme. if (m_arButton[i].SetTheme(xtpControlThemeFlat)) { CXTPButtonTheme* pTheme = m_arButton[i].GetTheme(); if (pTheme) { pTheme->EnableToolbarStyle(TRUE); } m_arButton[i].SetUseVisualStyle(TRUE); } m_arButton[i].EnableMarkup(); } if (m_bShowNewDeleteButtons) { CString xamlAdd, xamlDel; VERIFY(XTPResourceManager()->LoadXAML(xamlAdd, IDR_XAML_ICON_LIST_SYMBOL_ADD)); VERIFY(XTPResourceManager()->LoadXAML(xamlDel, IDR_XAML_ICON_LIST_SYMBOL_DELETE)); GetNewButton().SetWindowText(xamlAdd); GetDeleteButton().SetWindowText(xamlDel); } if (m_bShowUpDownButtons) { CString xamlUp, xamlDown; VERIFY(XTPResourceManager()->LoadXAML(xamlUp, IDR_XAML_ICON_LIST_SYMBOL_ARROW_UP)); VERIFY(XTPResourceManager()->LoadXAML(xamlDown, IDR_XAML_ICON_LIST_SYMBOL_ARROW_DOWN)); GetUpButton().SetWindowText(xamlUp); GetDownButton().SetWindowText(xamlDown); } // Move the buttons to their correct location. MoveButtons(); // Set the font for this window. if (bAutoFont) { SetFont(&XTPAuxData().xtpFont); } } void CXTPEditListBoxToolBar::SendCommand(UINT nCmdID) { if (m_bEnableEdit) { CWnd* pOwner = GetOwner(); _ASSERTE(pOwner); if (pOwner) pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), nCmdID), XTPToLPARAM(m_hWnd)); } } void CXTPEditListBoxToolBar::OnButtonNew() { SendCommand(LBN_XTP_NEWITEM); } void CXTPEditListBoxToolBar::OnButtonDelete() { SendCommand(LBN_XTP_DELETEITEM); } void CXTPEditListBoxToolBar::OnButtonUp() { SendCommand(LBN_XTP_MOVEITEMUP); } void CXTPEditListBoxToolBar::OnButtonDown() { SendCommand(LBN_XTP_MOVEITEMDOWN); } void CXTPEditListBoxToolBar::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos) { CStatic::OnWindowPosChanged(lpwndpos); // Move the buttons to their correct location. MoveButtons(); } BOOL CXTPEditListBoxToolBar::OnEraseBkgnd(CDC* /*pDC*/) { return TRUE; } #ifndef WM_QUERYUISTATE # define WM_QUERYUISTATE 0x0129 # define UISF_HIDEACCEL 0x2 #endif void CXTPEditListBoxToolBar::DrawText(CDC* pDC, CRect& rcClient) { // get the text for the control. CString strWindowText; GetWindowText(strWindowText); if (strWindowText.IsEmpty()) return; // select the font into the device context. CXTPFontDC font(pDC, GetFont()); CRect rcText(rcClient); rcText.left += XTP_DPI_X(1); // determine if the text is drawn disabled. pDC->SetTextColor(IsWindowEnabled() ? m_clrText.operator COLORREF() : GetXtremeColor(COLOR_GRAYTEXT)); pDC->SetBkMode(TRANSPARENT); DWORD dwFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE; if (SendMessage(WM_QUERYUISTATE) & UISF_HIDEACCEL) { dwFlags |= DT_HIDEPREFIX; } pDC->DrawText(strWindowText, rcText, dwFlags); } void CXTPEditListBoxToolBar::OnNcPaint() { CXTPWinThemeWrapper wrpTreeView; wrpTreeView.OpenThemeData(NULL, L"LISTBOX"); if (wrpTreeView.IsAppThemeActive() && (GetOwner()->GetExStyle() & WS_EX_CLIENTEDGE)) { CXTPWindowRect rc(this); CXTPClientRect rcClient(this); COLORREF clr = GetXtremeColor(COLOR_BTNSHADOW); if (rc.Width() == rcClient.Width() + XTP_DPI_X(2) && SUCCEEDED(wrpTreeView.GetThemeColor(0, 0, TMT_BORDERCOLOR, &clr))) { switch (m_theme) { case xtpControlThemeOffice2013: // case xtpControlThemeOffice2016: // case xtpControlThemeOffice2019: // case xtpControlThemeOffice2024: case xtpControlThemeVisualStudio2015: case xtpControlThemeVisualStudio2017: case xtpControlThemeVisualStudio2019: case xtpControlThemeVisualStudio2022: case xtpControlThemeNativeWindows10: case xtpControlThemeNativeWindows11: clr = m_clrBorder; break; default: break; } CWindowDC dc(this); dc.FillSolidRect(0, 0, rc.Width(), XTP_DPI_Y(1), clr); dc.FillSolidRect(0, 0, XTP_DPI_X(1), rc.Height(), clr); dc.FillSolidRect(rc.Width() - XTP_DPI_X(1), 0, XTP_DPI_X(1), rc.Height(), clr); dc.FillSolidRect(XTP_DPI_X(1), rc.Height() - XTP_DPI_Y(1), rc.Width() - XTP_DPI_X(2), XTP_DPI_Y(1), m_clrBackground); return; } } Default(); } void CXTPEditListBoxToolBar::OnPaint() { CPaintDC dc(this); // device context for painting // Exclude the buttons from getting repainted. int i; for (i = 0; i < _countof(m_arClipRect); ++i) dc.ExcludeClipRect(&m_arClipRect[i]); CRect r; GetClientRect(&r); CXTPBufferDC memDC(dc, r); memDC.FillSolidRect(r, m_clrBackground); DrawText(&memDC, r); } void CXTPEditListBoxToolBar::OnEnable(BOOL bEnable) { CStatic::OnEnable(bEnable); for (int i = 0; i < _countof(m_arButton); ++i) { if (::IsWindow(m_arButton[i].GetSafeHwnd())) { m_arButton[i].EnableWindow(bEnable); m_arButton[i].Invalidate(); } } Invalidate(); } void CXTPEditListBoxToolBar::OnShowWindow(BOOL bShow, UINT nStatus) { CStatic::OnShowWindow(bShow, nStatus); for (int i = 0; i < _countof(m_arButton); ++i) { if (::IsWindow(m_arButton[i].GetSafeHwnd())) m_arButton[i].ShowWindow(bShow ? SW_SHOW : SW_HIDE); } } LRESULT CXTPEditListBoxToolBar::OnSetTheme(WPARAM wParam, LPARAM /*lParam*/) { XTPControlTheme eTheme = (XTPControlTheme)wParam; m_theme = eTheme; SetTheme(eTheme); return 0; } void CXTPEditListBoxToolBar::SetTheme(XTPControlTheme theme) { UNREFERENCED_PARAMETER(theme); RefreshMetrics(); } void CXTPEditListBoxToolBar::RefreshMetrics() { m_clrBackground.SetStandardValue( XTPIniColor(_T("Controls.ListBox"), _T("Back"), GetXtremeColor(COLOR_3DFACE))); m_clrBorder.SetStandardValue( XTPIniColor(_T("Controls.ListBox"), _T("Border"), GetXtremeColor(COLOR_BTNSHADOW))); m_clrText.SetStandardValue( XTPIniColor(_T("Controls.ListBox"), _T("ItemText"), GetXtremeColor(COLOR_BTNTEXT))); }