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.
489 lines
11 KiB
C++
489 lines
11 KiB
C++
// XTPPropertyGridInplaceList.cpp : implementation of the CXTPPropertyGridInplaceList class.
|
|
//
|
|
// This file is a part of the XTREME PROPERTYGRID 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/XTPDrawHelpers.h"
|
|
#include "Common/XTPSystemHelpers.h"
|
|
|
|
#include "XTPPropertyGridDefines.h"
|
|
#include "XTPPropertyGridItem.h"
|
|
#include "XTPPropertyGridInplaceList.h"
|
|
#include "XTPPropertyGridView.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
BOOL CXTPPropertyGridInplaceList::m_bShowShadow = FALSE;
|
|
BOOL CXTPPropertyGridInplaceList::m_bTrackSelection = FALSE;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CXTPPropertyGridInplaceList
|
|
|
|
CXTPPropertyGridInplaceList::CXTPPropertyGridInplaceList()
|
|
: m_pItem(0)
|
|
{
|
|
}
|
|
|
|
CXTPPropertyGridInplaceList::~CXTPPropertyGridInplaceList()
|
|
{
|
|
}
|
|
|
|
IMPLEMENT_DYNAMIC(CXTPPropertyGridInplaceList, CListBox)
|
|
|
|
BEGIN_MESSAGE_MAP(CXTPPropertyGridInplaceList, CListBox)
|
|
//{{AFX_MSG_MAP(CXTPPropertyGridInplaceList)
|
|
ON_WM_KILLFOCUS()
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_KEYDOWN()
|
|
ON_WM_SYSKEYDOWN()
|
|
ON_WM_MOUSEACTIVATE()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_GETDLGCODE()
|
|
ON_WM_NCPAINT()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
void CXTPPropertyGridInplaceList::OnNcPaint()
|
|
{
|
|
Default();
|
|
|
|
CWindowDC dc(this);
|
|
|
|
CXTPWindowRect rc(this);
|
|
rc.OffsetRect(-rc.TopLeft());
|
|
|
|
dc.Draw3dRect(rc, GetSysColor(COLOR_WINDOWFRAME), GetSysColor(COLOR_WINDOWFRAME));
|
|
}
|
|
|
|
|
|
UINT CXTPPropertyGridInplaceList::OnGetDlgCode()
|
|
{
|
|
return DLGC_WANTALLKEYS;
|
|
}
|
|
|
|
void CXTPPropertyGridInplaceList::MeasureItem(LPMEASUREITEMSTRUCT)
|
|
{
|
|
|
|
}
|
|
|
|
void CXTPPropertyGridInplaceList::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
|
|
{
|
|
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
|
|
CRect rc(lpDrawItemStruct->rcItem);
|
|
CXTPPropertyGridItemConstraint* pConstraint = (CXTPPropertyGridItemConstraint*)GetItemDataPtr(lpDrawItemStruct->itemID);
|
|
|
|
BOOL bSelected = (lpDrawItemStruct->itemState & ODS_SELECTED);
|
|
|
|
if (m_pItem)
|
|
{
|
|
m_pItem->OnDrawItemConstraint(pDC, pConstraint, rc, bSelected);
|
|
}
|
|
}
|
|
|
|
void CXTPPropertyGridInplaceList::Create(CXTPPropertyGridItem* pItem, CRect rect)
|
|
{
|
|
ASSERT(pItem && pItem->GetGrid());
|
|
if (!pItem)
|
|
return;
|
|
|
|
CRect rcValue(rect);
|
|
rcValue.left = pItem->GetGrid()->GetDividerPos() + 1;
|
|
|
|
CWnd* pParent = (CWnd*)pItem->GetGrid();
|
|
m_pItem = pItem;
|
|
|
|
DestroyWindow();
|
|
|
|
if (!m_hWnd)
|
|
{
|
|
CListBox::CreateEx(WS_EX_TOOLWINDOW | (pParent->GetExStyle() & WS_EX_LAYOUTRTL), _T("LISTBOX"), _T(""),
|
|
LBS_NOTIFY | WS_CHILD | WS_VSCROLL | WS_BORDER | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS, CRect(0, 0, 0, 0), pParent, 0);
|
|
SetOwner(pParent);
|
|
|
|
|
|
if (m_bShowShadow && XTPSystemVersion()->IsWinXPOrGreater())
|
|
SetClassLongPtr(m_hWnd, GCL_STYLE, GetClassLongPtr(m_hWnd, GCL_STYLE) | 0x00020000);
|
|
}
|
|
SetFont(pParent->GetFont());
|
|
|
|
ResetContent();
|
|
|
|
CXTPPropertyGridItemConstraints* pList = pItem->GetConstraints();
|
|
|
|
|
|
int dx = rect.right - rcValue.left;
|
|
|
|
CWindowDC dc(pParent);
|
|
CXTPFontDC font(&dc, pParent->GetFont());
|
|
int nHeight = dc.GetTextExtent(_T(" "), 1).cy + 3;
|
|
|
|
for (int i = 0; i < pList->GetCount(); i++)
|
|
{
|
|
CXTPPropertyGridItemConstraint* pConstraint = pList->GetConstraintAt(i);
|
|
|
|
CString str = pConstraint->m_strConstraint;
|
|
int nIndex = AddString(str);
|
|
SetItemDataPtr(nIndex, pConstraint);
|
|
|
|
CSize sz = pItem->OnMergeItemConstraint(&dc, pConstraint);
|
|
|
|
dx = max(dx, sz.cx);
|
|
nHeight = max(nHeight, sz.cy);
|
|
|
|
if (pItem->GetValue() == str)
|
|
SetCurSel(nIndex);
|
|
}
|
|
|
|
SetItemHeight(0, nHeight);
|
|
|
|
rect.top = rect.bottom;
|
|
rect.bottom += nHeight * __min(pItem->GetDropDownItemCount(), GetCount()) + 2;
|
|
rect.left = rect.right - __min(dx, rect.Width() - XTP_PGI_EXPAND_BORDER);
|
|
|
|
pParent->ClientToScreen(&rect);
|
|
|
|
CRect rcWork = XTPMultiMonitor()->GetWorkArea(rect);
|
|
if (rect.bottom > rcWork.bottom && rect.top > rcWork.CenterPoint().y)
|
|
{
|
|
rect.OffsetRect(0, - rect.Height() - rcValue.Height() - 1);
|
|
}
|
|
if (rect.left < rcWork.left) rect.OffsetRect(rcWork.left - rect.left, 0);
|
|
if (rect.right > rcWork.right) rect.OffsetRect(rcWork.right - rect.right, 0);
|
|
|
|
|
|
SetFocus();
|
|
|
|
|
|
SetWindowLongPtr(m_hWnd, GWLP_HWNDPARENT, 0);
|
|
ModifyStyle(WS_CHILD, WS_POPUP);
|
|
SetWindowLongPtr(m_hWnd, GWLP_HWNDPARENT, (LONG_PTR)pParent->m_hWnd);
|
|
|
|
SetWindowPos(&CWnd::wndTopMost, rect.left, rect.top, rect.Width(), rect.Height(), SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
|
|
|
|
CXTPMouseMonitor::SetupHook(this);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CXTPPropertyGridInplaceList message handlers
|
|
|
|
void CXTPPropertyGridInplaceList::OnKillFocus(CWnd* pNewWnd)
|
|
{
|
|
CListBox::OnKillFocus(pNewWnd);
|
|
|
|
CXTPMouseMonitor::SetupHook(NULL);
|
|
|
|
|
|
Cancel();
|
|
DestroyWindow();
|
|
}
|
|
|
|
int CXTPPropertyGridInplaceList::OnMouseActivate(CWnd* /*pDesktopWnd*/, UINT /*nHitTest*/, UINT /*message*/)
|
|
{
|
|
return MA_NOACTIVATE;
|
|
}
|
|
|
|
void CXTPPropertyGridInplaceList::PostNcDestroy()
|
|
{
|
|
CXTPMouseMonitor::SetupHook(NULL);
|
|
|
|
CListBox::PostNcDestroy();
|
|
}
|
|
|
|
void CXTPPropertyGridInplaceList::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
CListBox::OnMouseMove(nFlags, point);
|
|
|
|
if (m_bTrackSelection)
|
|
{
|
|
BOOL bOutsize = FALSE;
|
|
int nItem = ItemFromPoint(point, bOutsize);
|
|
if (nItem != -1 && !bOutsize && nItem != GetCurSel())
|
|
{
|
|
SetCurSel(nItem);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CXTPPropertyGridInplaceList::OnLButtonUp(UINT, CPoint point)
|
|
{
|
|
CXTPClientRect rc(this);
|
|
|
|
if (rc.PtInRect(point))
|
|
Apply();
|
|
else
|
|
Cancel();
|
|
}
|
|
|
|
|
|
void CXTPPropertyGridInplaceList::Cancel()
|
|
{
|
|
if (m_pItem)
|
|
{
|
|
m_pItem->OnCancelEdit();
|
|
m_pItem = NULL;
|
|
}
|
|
|
|
if (m_hWnd && ::GetFocus() == m_hWnd)
|
|
{
|
|
GetOwner()->SetFocus();
|
|
}
|
|
}
|
|
|
|
void CXTPPropertyGridInplaceList::Apply()
|
|
{
|
|
int nIndex = GetCurSel();
|
|
if (nIndex != LB_ERR && m_pItem)
|
|
{
|
|
CXTPPropertyGridItemConstraint* pConstraint = (CXTPPropertyGridItemConstraint*)GetItemDataPtr(nIndex);
|
|
if (pConstraint && !pConstraint->m_bEnabled)
|
|
return;
|
|
|
|
|
|
CXTPPropertyGridItem* pItem = m_pItem;
|
|
m_pItem = NULL;
|
|
|
|
CXTPPropertyGridItemConstraints* pList = pItem->GetConstraints();
|
|
pList->SetCurrent(nIndex);
|
|
|
|
CString str;
|
|
GetText(nIndex, str);
|
|
|
|
if (pItem->OnAfterEdit(str) && str != pItem->GetValue())
|
|
pItem->OnValueChanged(str);
|
|
}
|
|
|
|
if (m_hWnd && ::GetFocus() == m_hWnd)
|
|
{
|
|
GetOwner()->SetFocus();
|
|
}
|
|
}
|
|
|
|
void CXTPPropertyGridInplaceList::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
if (nChar == VK_ESCAPE) Cancel();
|
|
else if (nChar == VK_RETURN || nChar == VK_F4) Apply();
|
|
else CListBox::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
void CXTPPropertyGridInplaceList::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
if (nChar == VK_DOWN || nChar == VK_UP)
|
|
{
|
|
Apply();
|
|
return;
|
|
}
|
|
|
|
CListBox::OnSysKeyDown(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
|
|
void CXTPPropertyGridInplaceList::DestroyItem()
|
|
{
|
|
// reset variables to defaults.
|
|
m_pItem = NULL;
|
|
|
|
CXTPMouseMonitor::SetupHook(NULL);
|
|
|
|
// destroy the window.
|
|
DestroyWindow();
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CXTPPropertyGridInplaceMultilineEdit
|
|
|
|
CXTPPropertyGridInplaceMultilineEdit::CXTPPropertyGridInplaceMultilineEdit()
|
|
: m_pItem(0)
|
|
{
|
|
}
|
|
|
|
CXTPPropertyGridInplaceMultilineEdit::~CXTPPropertyGridInplaceMultilineEdit()
|
|
{
|
|
}
|
|
|
|
IMPLEMENT_DYNAMIC(CXTPPropertyGridInplaceMultilineEdit, CEdit)
|
|
|
|
BEGIN_MESSAGE_MAP(CXTPPropertyGridInplaceMultilineEdit, CEdit)
|
|
//{{AFX_MSG_MAP(CXTPPropertyGridInplaceMultilineEdit)
|
|
ON_WM_KILLFOCUS()
|
|
ON_WM_KEYDOWN()
|
|
ON_WM_SYSKEYDOWN()
|
|
ON_WM_MOUSEACTIVATE()
|
|
ON_WM_GETDLGCODE()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
void CXTPPropertyGridInplaceMultilineEdit::Create(CXTPPropertyGridItem* pItem, CRect rect)
|
|
{
|
|
ASSERT(pItem && pItem->GetGrid());
|
|
if (!pItem)
|
|
return;
|
|
|
|
CRect rcValue(rect);
|
|
rcValue.left = pItem->GetGrid()->GetDividerPos() + 1;
|
|
|
|
CWnd* pParent = (CWnd*)pItem->GetGrid();
|
|
m_pItem = pItem;
|
|
|
|
if (!m_hWnd)
|
|
{
|
|
CEdit::CreateEx(WS_EX_TOOLWINDOW, _T("EDIT"), m_pItem->GetValue(), ES_MULTILINE | WS_CHILD | WS_BORDER | WS_VSCROLL | ES_AUTOVSCROLL, CRect(0, 0, 0, 0), pParent, 0);
|
|
SetOwner(pParent);
|
|
}
|
|
SetFont(pParent->GetFont());
|
|
|
|
|
|
int dx = rect.right - rcValue.left;
|
|
|
|
CWindowDC dc(pParent);
|
|
CXTPFontDC font(&dc, pParent->GetFont());
|
|
int nHeight = dc.GetTextExtent(_T(" "), 1).cy;
|
|
|
|
rect.top = rect.bottom;
|
|
rect.bottom += nHeight * pItem->GetDropDownItemCount() + 4;
|
|
rect.left = rect.right - __min(dx, rect.Width() - XTP_PGI_EXPAND_BORDER);
|
|
|
|
pParent->ClientToScreen(&rect);
|
|
|
|
CRect rcWork = XTPMultiMonitor()->GetWorkArea(rect);
|
|
if (rect.bottom > rcWork.bottom && rect.top > rcWork.CenterPoint().y)
|
|
{
|
|
rect.OffsetRect(0, - rect.Height() - rcValue.Height() - 1);
|
|
}
|
|
if (rect.left < rcWork.left) rect.OffsetRect(rcWork.left - rect.left, 0);
|
|
if (rect.right > rcWork.right) rect.OffsetRect(rcWork.right - rect.right, 0);
|
|
|
|
|
|
SetFocus();
|
|
|
|
|
|
SetWindowLongPtr(m_hWnd, GWLP_HWNDPARENT, 0);
|
|
ModifyStyle(WS_CHILD, WS_POPUP);
|
|
SetWindowLongPtr(m_hWnd, GWLP_HWNDPARENT, (LONG_PTR)pParent->m_hWnd);
|
|
|
|
SetWindowPos(&CWnd::wndTopMost, rect.left, rect.top, rect.Width(), rect.Height(), SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
|
|
|
|
CXTPMouseMonitor::SetupHook(this);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CXTPPropertyGridInplaceMultilineEdit message handlers
|
|
|
|
void CXTPPropertyGridInplaceMultilineEdit::OnKillFocus(CWnd* pNewWnd)
|
|
{
|
|
CEdit::OnKillFocus(pNewWnd);
|
|
|
|
CXTPMouseMonitor::SetupHook(NULL);
|
|
|
|
|
|
Apply();
|
|
DestroyWindow();
|
|
}
|
|
|
|
int CXTPPropertyGridInplaceMultilineEdit::OnMouseActivate(CWnd* /*pDesktopWnd*/, UINT /*nHitTest*/, UINT /*message*/)
|
|
{
|
|
return MA_NOACTIVATE;
|
|
}
|
|
|
|
void CXTPPropertyGridInplaceMultilineEdit::PostNcDestroy()
|
|
{
|
|
CXTPMouseMonitor::SetupHook(NULL);
|
|
|
|
delete this;
|
|
}
|
|
|
|
|
|
void CXTPPropertyGridInplaceMultilineEdit::Cancel()
|
|
{
|
|
if (m_pItem)
|
|
{
|
|
m_pItem->OnCancelEdit();
|
|
m_pItem = NULL;
|
|
}
|
|
|
|
if (m_hWnd && ::GetFocus() == m_hWnd)
|
|
{
|
|
GetOwner()->SetFocus();
|
|
}
|
|
}
|
|
|
|
void CXTPPropertyGridInplaceMultilineEdit::Apply()
|
|
{
|
|
if (m_pItem)
|
|
{
|
|
CXTPPropertyGridItem* pItem = m_pItem;
|
|
m_pItem = NULL;
|
|
|
|
CString str;
|
|
GetWindowText(str);
|
|
|
|
if (pItem->OnAfterEdit(str) && str != pItem->GetValue())
|
|
pItem->OnValueChanged(str);
|
|
}
|
|
|
|
if (m_hWnd && ::GetFocus() == m_hWnd)
|
|
{
|
|
GetOwner()->SetFocus();
|
|
}
|
|
}
|
|
|
|
void CXTPPropertyGridInplaceMultilineEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
if (nChar == VK_ESCAPE)
|
|
Cancel();
|
|
else if (nChar == VK_F4)
|
|
Apply();
|
|
else if (nChar == VK_RETURN && (GetKeyState(VK_CONTROL) >= 0))
|
|
Apply();
|
|
else CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
void CXTPPropertyGridInplaceMultilineEdit::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
if (nChar == VK_DOWN || nChar == VK_UP)
|
|
{
|
|
Apply();
|
|
return;
|
|
}
|
|
|
|
CEdit::OnSysKeyDown(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
UINT CXTPPropertyGridInplaceMultilineEdit::OnGetDlgCode()
|
|
{
|
|
return DLGC_WANTALLKEYS;
|
|
}
|
|
|
|
BOOL CXTPPropertyGridInplaceMultilineEdit::PreTranslateMessage(MSG* pMsg)
|
|
{
|
|
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE)
|
|
{
|
|
Cancel();
|
|
return TRUE;
|
|
}
|
|
|
|
return CEdit::PreTranslateMessage(pMsg);
|
|
}
|