You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1024 lines
23 KiB
C++
1024 lines
23 KiB
C++
// XTPEditListBox.cpp : implementation of the CXTPEditListBox class.
|
|
//
|
|
// This file is a part of the XTREME CONTROLS MFC class library.
|
|
// (c)1998-2012 Codejock Software, All Rights Reserved.
|
|
//
|
|
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
|
|
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
|
|
// CONSENT OF CODEJOCK SOFTWARE.
|
|
//
|
|
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
|
|
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
|
|
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
|
|
// SINGLE COMPUTER.
|
|
//
|
|
// CONTACT INFORMATION:
|
|
// support@codejock.com
|
|
// http://www.codejock.com
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "Common/XTPResourceManager.h"
|
|
#include "Common/XTPColorManager.h"
|
|
#include "Common/XTPDrawHelpers.h"
|
|
#include "Common/XTPWinThemeWrapper.h"
|
|
#include "Common/XTPMaskEditT.h"
|
|
#include "../Util/XTPControlTheme.h"
|
|
|
|
#include "../Resource.h"
|
|
#include "../Defines.h"
|
|
#include "../Util/XTPUtil.h"
|
|
#include "../Util/XTPGlobal.h"
|
|
#include "../Button/XTPButton.h"
|
|
#include "../Button/XTPButtonTheme.h"
|
|
#include "../Edit/XTPEdit.h"
|
|
#include "../Edit/XTPBrowseEdit.h"
|
|
#include "XTPListBox.h"
|
|
#include "XTPEditListBox.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_bEnableEdit(true)
|
|
, m_pParentWnd(NULL)
|
|
{
|
|
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)
|
|
|
|
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()
|
|
|
|
|
|
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();
|
|
ASSERT(pOwner);
|
|
if (!pOwner)
|
|
return;
|
|
|
|
if (!m_pItemEdit)
|
|
return;
|
|
|
|
m_strItemText = m_pItemEdit->m_strWindowText;
|
|
|
|
if (m_bNewItem)
|
|
{
|
|
// Delete the temp string.
|
|
DeleteString(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), (LPARAM)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), (LPARAM)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), (LPARAM)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(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), (LPARAM)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();
|
|
ASSERT(pOwner);
|
|
|
|
// Send notification to owner.
|
|
if (pOwner) pOwner->SendMessage( WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(),
|
|
LBN_XTP_ONBROWSE), (LPARAM)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();
|
|
ASSERT(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), (LPARAM)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), (LPARAM)m_hWnd );
|
|
|
|
return;
|
|
}
|
|
|
|
// Get the size of the currently selected item.
|
|
CRect rcItem;
|
|
GetItemRect(m_nIndex, rcItem);
|
|
rcItem.InflateRect(-2, 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();
|
|
ASSERT(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), (LPARAM)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(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), (LPARAM)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(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();
|
|
ASSERT(pOwner);
|
|
if (!pOwner)
|
|
return;
|
|
|
|
// Send notification to owner.
|
|
pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(),
|
|
LBN_XTP_MOVEITEMUP), (LPARAM)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(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();
|
|
ASSERT(pOwner);
|
|
if (!pOwner)
|
|
return;
|
|
|
|
// Send notification to owner.
|
|
pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(),
|
|
LBN_XTP_MOVEITEMDOWN), (LPARAM)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();
|
|
ASSERT_VALID(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 += 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), (LPARAM)m_hWnd);
|
|
}
|
|
|
|
CRect rcItem;
|
|
if (GetItemRect(m_nIndex, rcItem) != LB_ERR)
|
|
{
|
|
if (!rcItem.PtInRect(point))
|
|
{
|
|
CWnd* pOwner = GetOwner();
|
|
ASSERT(pOwner);
|
|
if (!pOwner)
|
|
return;
|
|
|
|
SetCurSel(-1);
|
|
pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_SELCHANGE), (LPARAM)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))
|
|
{
|
|
ASSERT_VALID(m_pParentWnd); // must be valid.
|
|
|
|
CXTPWindowRect rcWindow(this);
|
|
m_pParentWnd->ScreenToClient(&rcWindow);
|
|
|
|
// move the group edit control.
|
|
rcWindow.top -= BTN_OFFSET;
|
|
rcWindow.bottom = rcWindow.top + BTN_OFFSET;
|
|
|
|
::SetWindowPos(m_editGroup.m_hWnd, NULL, rcWindow.left, rcWindow.top,
|
|
rcWindow.Width(), rcWindow.Height(), SWP_FRAMECHANGED);
|
|
}
|
|
}
|
|
|
|
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_bEnableEdit(true)
|
|
, m_bShowNewDeleteButtons(true)
|
|
{
|
|
|
|
}
|
|
|
|
CXTPEditListBoxToolBar::~CXTPEditListBoxToolBar()
|
|
{
|
|
}
|
|
|
|
IMPLEMENT_DYNAMIC(CXTPEditListBoxToolBar, CStatic)
|
|
|
|
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
|
|
END_MESSAGE_MAP()
|
|
|
|
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-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(-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);
|
|
|
|
CImageList imageList;
|
|
imageList.Create(14, 12, ILC_COLOR8 | ILC_MASK, 0, 1);
|
|
|
|
CBitmap bmp;
|
|
CXTPResourceManager::AssertValid(XTPResourceManager()->LoadBitmap(&bmp, XTP_IDB_LISTEDIT));
|
|
imageList.Add(&bmp, RGB(255, 0, 255));
|
|
|
|
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;
|
|
}
|
|
|
|
m_arIcon[i] = imageList.ExtractIcon(i);
|
|
m_arButton[i].SetIcon(CSize(0), m_arIcon[i]);
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
// Move the buttons to their correct location.
|
|
MoveButtons();
|
|
|
|
// Set the font for this window.
|
|
if (bAutoFont)
|
|
{
|
|
SetFont(&XTPAuxData().font);
|
|
}
|
|
}
|
|
|
|
void CXTPEditListBoxToolBar::SendCommand(UINT nCmdID)
|
|
{
|
|
if (m_bEnableEdit)
|
|
{
|
|
CWnd* pOwner = GetOwner();
|
|
ASSERT(pOwner);
|
|
|
|
if (pOwner) pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(),
|
|
nCmdID), (LPARAM)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
|
|
|
|
#ifndef DT_HIDEPREFIX
|
|
#define DT_HIDEPREFIX 0x00100000
|
|
#endif //!DT_HIDEPREFIX
|
|
|
|
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 += 1;
|
|
|
|
// determine if the text is drawn disabled.
|
|
pDC->SetTextColor(GetXtremeColor(IsWindowEnabled() ? COLOR_BTNTEXT : 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.OpenTheme(0, L"LISTBOX");
|
|
if (wrpTreeView.IsAppThemed() && wrpTreeView.IsAppThemeReady() && (GetOwner()->GetExStyle() & WS_EX_CLIENTEDGE))
|
|
{
|
|
CXTPWindowRect rc(this);
|
|
CXTPClientRect rcClient(this);
|
|
|
|
COLORREF clr = GetXtremeColor(COLOR_BTNSHADOW);
|
|
if (rc.Width() == rcClient.Width() + 2 &&
|
|
SUCCEEDED(wrpTreeView.GetThemeColor(0, 0, TMT_BORDERCOLOR, &clr)))
|
|
{
|
|
CWindowDC dc(this);
|
|
|
|
dc.FillSolidRect(0, 0, rc.Width(), 1, clr);
|
|
dc.FillSolidRect(0, 0, 1, rc.Height(), clr);
|
|
dc.FillSolidRect(rc.Width() - 1, 0, 1, rc.Height(), clr);
|
|
dc.FillSolidRect(1, rc.Height() - 1, rc.Width() - 2, 1, GetXtremeColor(COLOR_3DFACE));
|
|
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, GetXtremeColor(COLOR_3DFACE));
|
|
|
|
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);
|
|
}
|
|
}
|