975 lines
21 KiB
C++
975 lines
21 KiB
C++
// XTPReportInplaceControls.cpp
|
|
//
|
|
// This file is a part of the XTREME REPORTCONTROL MFC class library.
|
|
// (c)1998-2008 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 "XTPReportControl.h"
|
|
#include "XTPReportDefines.h"
|
|
#include "XTPReportInplaceControls.h"
|
|
#include "XTPReportColumn.h"
|
|
#include "XTPReportRecordItemText.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
CXTPReportInplaceControl::CXTPReportInplaceControl()
|
|
{
|
|
}
|
|
|
|
CXTPReportInplaceControl::~CXTPReportInplaceControl()
|
|
{
|
|
SetItemArgs(0);
|
|
}
|
|
|
|
void CXTPReportInplaceControl::SetItemArgs(XTP_REPORTRECORDITEM_ARGS* pItemArgs)
|
|
{
|
|
if (pItemArgs)
|
|
{
|
|
pItemArgs->AddRef();
|
|
Release();
|
|
|
|
pItem = pItemArgs->pItem;
|
|
pControl = pItemArgs->pControl;
|
|
pRow = pItemArgs->pRow;
|
|
pColumn = pItemArgs->pColumn;
|
|
rcItem = pItemArgs->rcItem;
|
|
}
|
|
else
|
|
{
|
|
Release();
|
|
|
|
pItem = 0;
|
|
pControl = 0;
|
|
pRow = 0;
|
|
pColumn = 0;
|
|
}
|
|
}
|
|
|
|
IMPLEMENT_DYNAMIC(CXTPReportInplaceEdit, CEdit)
|
|
|
|
CXTPReportInplaceEdit::CXTPReportInplaceEdit()
|
|
{
|
|
m_pSelectedConstraint = NULL;
|
|
m_clrText = 0;
|
|
m_bSetWindowText = FALSE;
|
|
}
|
|
|
|
CXTPReportInplaceEdit::~CXTPReportInplaceEdit()
|
|
{
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CXTPReportInplaceEdit, CEdit)
|
|
//{{AFX_MSG_MAP(CXTPReportInplaceEdit)
|
|
ON_WM_MOUSEACTIVATE()
|
|
ON_WM_CTLCOLOR_REFLECT()
|
|
ON_CONTROL_REFLECT(EN_KILLFOCUS, OnEnKillfocus)
|
|
ON_CONTROL_REFLECT(EN_CHANGE, OnEnChange)
|
|
ON_WM_LBUTTONDBLCLK()
|
|
ON_WM_KEYDOWN()
|
|
ON_WM_SYSKEYDOWN()
|
|
ON_WM_GETDLGCODE()
|
|
ON_WM_CHAR()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
void CXTPReportInplaceEdit::HideWindow()
|
|
{
|
|
if (m_hWnd)
|
|
{
|
|
ShowWindow(SW_HIDE);
|
|
SetItemArgs(0);
|
|
}
|
|
}
|
|
|
|
void CXTPReportInplaceEdit::Create(XTP_REPORTRECORDITEM_ARGS* pItemArgs)
|
|
{
|
|
SetItemArgs(pItemArgs);
|
|
m_pSelectedConstraint = NULL;
|
|
|
|
XTP_REPORTRECORDITEM_METRICS* pMetrics = new XTP_REPORTRECORDITEM_METRICS;
|
|
|
|
//pMetrics->strText = pItem->GetCaption(pColumn);
|
|
CXTPReportRecordItemText* pTextItem = DYNAMIC_DOWNCAST(CXTPReportRecordItemText, pItem);
|
|
|
|
if(pTextItem != NULL)
|
|
pMetrics->strText = pTextItem->GetValue();
|
|
else
|
|
pMetrics->strText = pItem->GetCaption(pColumn);
|
|
|
|
pItemArgs->pRow->FillMetrics(pColumn, pItem, pMetrics);
|
|
|
|
CRect rect = pItemArgs->rcItem;
|
|
pItem->GetCaptionRect(pItemArgs, rect);
|
|
rect.DeflateRect(2, 1, 2, 2);
|
|
|
|
CXTPReportRecordItemEditOptions* pEditOptions = pItem->GetEditOptions(pColumn);
|
|
ASSERT(pEditOptions);
|
|
if (!pEditOptions)
|
|
return;
|
|
|
|
m_clrText = pMetrics->clrForeground;
|
|
m_strValue = pMetrics->strText;
|
|
m_strText_prev = pMetrics->strText;
|
|
|
|
DWORD dwEditStyle = WS_CHILD | pEditOptions->m_dwEditStyle;
|
|
|
|
dwEditStyle &= ~(ES_LEFT | ES_RIGHT | ES_CENTER);
|
|
|
|
if (pControl->GetPaintManager()->m_bUseEditTextAlignment)
|
|
{
|
|
if (pMetrics->nColumnAlignment & DT_RIGHT)
|
|
{
|
|
dwEditStyle |= ES_RIGHT;
|
|
}
|
|
else if (pMetrics->nColumnAlignment & DT_CENTER)
|
|
{
|
|
dwEditStyle |= ES_CENTER;
|
|
}
|
|
}
|
|
|
|
if (m_hWnd)
|
|
{
|
|
DWORD dwStyle = WS_CHILD | WS_VISIBLE | ES_READONLY;
|
|
|
|
if ((GetStyle() & dwStyle) != (dwEditStyle & dwStyle))
|
|
DestroyWindow();
|
|
}
|
|
|
|
if (!m_hWnd)
|
|
{
|
|
CEdit::Create(dwEditStyle, rect, pControl, 0);
|
|
}
|
|
|
|
if (pControl->GetExStyle() & WS_EX_RTLREADING)
|
|
{
|
|
ModifyStyleEx(0, WS_EX_RTLREADING);
|
|
}
|
|
|
|
|
|
SetLimitText(pEditOptions->m_nMaxLength);
|
|
|
|
SetFocus();
|
|
SetFont(pMetrics->pFont);
|
|
SetWindowText(m_strValue);
|
|
|
|
pMetrics->InternalRelease();
|
|
|
|
|
|
if (rect.right > rect.left)
|
|
{
|
|
SetWindowPos(0, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOZORDER | SWP_SHOWWINDOW);
|
|
}
|
|
else
|
|
{
|
|
HideWindow();
|
|
}
|
|
|
|
SetMargins(0, 0);
|
|
}
|
|
|
|
void CXTPReportInplaceEdit::SetWindowText(LPCTSTR lpszString)
|
|
{
|
|
m_bSetWindowText = TRUE;
|
|
|
|
CWnd::SetWindowText(lpszString);
|
|
m_strText_prev = lpszString;
|
|
|
|
m_bSetWindowText = FALSE;
|
|
}
|
|
|
|
void CXTPReportInplaceEdit::SetFont(CFont* pFont)
|
|
{
|
|
m_fntEdit.DeleteObject();
|
|
LOGFONT lf;
|
|
pFont->GetLogFont(&lf);
|
|
m_fntEdit.CreateFontIndirect(&lf);
|
|
|
|
CEdit::SetFont(&m_fntEdit);
|
|
}
|
|
|
|
void CXTPReportInplaceEdit::OnEnKillfocus()
|
|
{
|
|
if (pControl && pItem)
|
|
{
|
|
//pItem->OnValidateEdit((XTP_REPORTRECORDITEM_ARGS*)this);
|
|
pItem->OnCancelEdit(pControl, TRUE);
|
|
HideWindow();
|
|
}
|
|
}
|
|
|
|
void CXTPReportInplaceEdit::OnEnChange()
|
|
{
|
|
if(m_bSetWindowText || !pControl || !pItem)
|
|
return;
|
|
|
|
CString strValue, strValNew;
|
|
GetWindowText(strValue);
|
|
strValNew = strValue;
|
|
|
|
BOOL bCommit = pItem->OnEditChanging((XTP_REPORTRECORDITEM_ARGS*)this, strValNew);
|
|
if (!bCommit || strValNew != strValue)
|
|
{
|
|
int nSelStart = 0, nSelEnd = 0;
|
|
GetSel(nSelStart, nSelEnd);
|
|
|
|
SetWindowText(bCommit ? strValNew : m_strText_prev);
|
|
|
|
SetSel(nSelStart, nSelEnd);
|
|
}
|
|
else
|
|
{
|
|
m_strText_prev = strValue;
|
|
}
|
|
}
|
|
|
|
int CXTPReportInplaceEdit::OnMouseActivate(CWnd* , UINT , UINT ) //(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
|
|
{
|
|
return MA_NOACTIVATE;
|
|
}
|
|
|
|
UINT CXTPReportInplaceEdit::OnGetDlgCode()
|
|
{
|
|
return DLGC_WANTALLKEYS;
|
|
}
|
|
|
|
void CXTPReportInplaceEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
// TRACE(_T("ReportControl, OnChar('%d') \n"), nChar);
|
|
|
|
if (!pControl)
|
|
return;
|
|
|
|
// Moved to PreTranslateMessage
|
|
// if (!pControl->OnPreviewKeyDown(nChar, nRepCnt, nFlags))
|
|
// {
|
|
// return;
|
|
// }
|
|
|
|
if (nChar == VK_TAB) return;
|
|
if (nChar == VK_ESCAPE || nChar == VK_RETURN)
|
|
{
|
|
pControl->EditItem(NULL);
|
|
return;
|
|
}
|
|
if (pItem && pColumn && pItem->GetEditOptions(pColumn)->m_bConstraintEdit)
|
|
{
|
|
CXTPReportRecordItemEditOptions* pEditOptions = pItem->GetEditOptions(pColumn);
|
|
|
|
CXTPReportRecordItemConstraints* pConstraints = pEditOptions->GetConstraints();
|
|
int nCount = pConstraints->GetCount();
|
|
if (nCount > 0)
|
|
{
|
|
|
|
CString str, strActual;
|
|
GetWindowText(str);
|
|
strActual = str;
|
|
|
|
CXTPReportRecordItemConstraint* pConstraint = (m_pSelectedConstraint == NULL) ?
|
|
pEditOptions->FindConstraint(str): m_pSelectedConstraint;
|
|
|
|
int nIndexStart, nIndex;
|
|
nIndexStart = nIndex = (pConstraint == NULL ? nCount - 1 : pConstraint->GetIndex());
|
|
|
|
CString strSeach ((TCHAR)nChar);
|
|
|
|
do
|
|
{
|
|
|
|
nIndex = nIndex < nCount - 1 ? nIndex + 1 : 0;
|
|
|
|
pConstraint = pConstraints->GetAt(nIndex);
|
|
str = pConstraint->m_strConstraint;
|
|
|
|
if (strSeach.CompareNoCase(str.Left(1)) == 0)
|
|
{
|
|
m_pSelectedConstraint = pConstraint;
|
|
SetWindowText(str);
|
|
SetSel(0, -1);
|
|
|
|
if(strActual.CompareNoCase(str) != 0)
|
|
((CXTPReportControl*)pControl)->OnConstraintSelecting(pRow, pItem, pColumn, pConstraint);
|
|
|
|
return;
|
|
}
|
|
|
|
} while (nIndex != nIndexStart);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
CEdit::OnChar(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
void CXTPReportInplaceEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
CXTPReportControl* _pControl = pControl;
|
|
ASSERT(_pControl);
|
|
|
|
if (!_pControl)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
if (nChar == VK_TAB && _pControl)
|
|
{
|
|
_pControl->SetFocus();
|
|
_pControl->SendMessage(WM_CHAR, nChar);
|
|
return;
|
|
|
|
}
|
|
if (nChar == VK_ESCAPE)
|
|
{
|
|
SetWindowText(m_strValue);
|
|
return;
|
|
}
|
|
else if (nChar == VK_RETURN)
|
|
{
|
|
return;
|
|
}
|
|
else if (nChar == VK_UP || nChar == VK_DOWN || nChar == VK_PRIOR || nChar == VK_NEXT)
|
|
{
|
|
if (pItem && pColumn && pItem->GetEditOptions(pColumn)->m_bConstraintEdit)
|
|
{
|
|
CXTPReportRecordItemConstraint* pConstraint;
|
|
CXTPReportRecordItemEditOptions* pEditOptions = pItem->GetEditOptions(pColumn);
|
|
CXTPReportRecordItemConstraints* pConstraints = pEditOptions->GetConstraints();
|
|
|
|
int nCount = pConstraints->GetCount();
|
|
if (nCount > 1)
|
|
{
|
|
CString strActual, str;
|
|
GetWindowText(strActual);
|
|
|
|
int nIndex = 0; // the first item
|
|
|
|
if(nChar == VK_NEXT)
|
|
{
|
|
nIndex = nCount - 1; // the last item
|
|
}
|
|
else if (nChar != VK_PRIOR)
|
|
{
|
|
// look for the actually selected item
|
|
for(int i = 0; i < nCount; i++)
|
|
{
|
|
pConstraint = pConstraints->GetAt(i);
|
|
|
|
if (strActual.CompareNoCase(pConstraint->m_strConstraint) == 0)
|
|
{
|
|
if(nChar == VK_UP)
|
|
nIndex = max(0, i - 1);
|
|
else if(nChar == VK_DOWN)
|
|
nIndex = min(nCount-1, i + 1);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
pConstraint = pConstraints->GetAt(max(0, min(nIndex, nCount-1)));
|
|
str = pConstraint->m_strConstraint;
|
|
m_pSelectedConstraint = pConstraint;
|
|
|
|
// set the default font, because user could change the font (for ex. to striked one)
|
|
SetFont(pControl->GetPaintManager()->GetTextFont());
|
|
SetWindowText(str);
|
|
SetSel(0, -1);
|
|
|
|
if(strActual.CompareNoCase(str) != 0)
|
|
((CXTPReportControl*)pControl)->OnConstraintSelecting(pRow, pItem, pColumn, pConstraint);
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
void CXTPReportInplaceEdit::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
if ((nChar == VK_UP || nChar == VK_DOWN) && pControl)
|
|
{
|
|
if (pControl->GetInplaceButtons()->GetSize() > 0)
|
|
{
|
|
CXTPReportInplaceButton* pButton = pControl->GetInplaceButtons()->GetAt(0);
|
|
|
|
if (pButton->GetItem() == pItem)
|
|
{
|
|
pItem->OnInplaceButtonDown(pButton);
|
|
}
|
|
}
|
|
}
|
|
|
|
CEdit::OnSysKeyDown(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
BOOL CXTPReportInplaceEdit::PreTranslateMessage(MSG* pMsg)
|
|
{
|
|
if (pMsg->message == WM_KEYDOWN && pControl)
|
|
{
|
|
if (!pControl->OnPreviewKeyDown((UINT&)pMsg->wParam, LOWORD(pMsg->lParam), HIWORD(pMsg->lParam)) )
|
|
{
|
|
// TRACE(_T("InplaceEdit, PreTranslateMessagem-OnPreviewKeyDown('%d') = CANCEL \n"), pMsg->wParam);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
if (pMsg->message == WM_KEYDOWN && IsDialogMessage(pMsg))
|
|
return TRUE;
|
|
|
|
return CEdit::PreTranslateMessage(pMsg);
|
|
}
|
|
|
|
void CXTPReportInplaceEdit::OnLButtonDblClk(UINT nFlags, CPoint point)
|
|
{
|
|
if (pRow && pItem)
|
|
{
|
|
MapWindowPoints(pControl, &point, 1);
|
|
pRow->OnDblClick(point);
|
|
}
|
|
|
|
if (pItem)
|
|
{
|
|
CEdit::OnLButtonDblClk(nFlags, point);
|
|
}
|
|
}
|
|
|
|
HBRUSH CXTPReportInplaceEdit::CtlColor(CDC* pDC, UINT /*nCtlColor*/)
|
|
{
|
|
pDC->SetTextColor(m_clrText);
|
|
|
|
return GetSysColorBrush(COLOR_WINDOW);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CXTPReportInplaceButton
|
|
|
|
CXTPReportInplaceButton::CXTPReportInplaceButton(UINT nID)
|
|
{
|
|
m_nID = nID;
|
|
m_nWidth = 17;
|
|
m_nFixedHeight = 19;
|
|
m_bInsideCell = FALSE;
|
|
m_nIconIndex = XTP_REPORT_NOICON;
|
|
|
|
m_bPressed = m_bOver = FALSE;
|
|
m_nState = 0;
|
|
m_nSpinIncrement = 0;
|
|
m_unSpinTimerCnt = 0;
|
|
m_unSpinTimerId = 0;
|
|
|
|
m_nSpinMin = INT_MIN;
|
|
m_nSpinMax = INT_MAX;
|
|
m_nSpinStep = 1;
|
|
|
|
|
|
}
|
|
|
|
void CXTPReportInplaceButton::Create(XTP_REPORTRECORDITEM_ARGS* pItemArgs, CRect& rcButtons)
|
|
{
|
|
m_bPressed = m_bOver = FALSE;
|
|
m_nState = 0;
|
|
m_nSpinIncrement = 0;
|
|
m_unSpinTimerCnt = 0;
|
|
m_unSpinTimerId = 0;
|
|
SetItemArgs(pItemArgs);
|
|
|
|
CRect rect(rcButtons);
|
|
if (pControl->GetPaintManager()->IsFixedInplaceButtonHeight())
|
|
rect.bottom = rect.top + m_nFixedHeight;
|
|
|
|
if (m_bInsideCell)
|
|
{
|
|
rect.right = rcButtons.left;
|
|
rect.left = rect.right - m_nWidth;
|
|
|
|
rcButtons.left = rect.left;
|
|
}
|
|
else
|
|
{
|
|
rect.left = rcButtons.right;
|
|
rect.right = rect.left + m_nWidth;
|
|
|
|
rcButtons.right = rect.right;
|
|
}
|
|
|
|
if (!m_hWnd)
|
|
{
|
|
CStatic::Create(NULL, SS_NOTIFY | WS_CHILD, rect, pItemArgs->pControl);
|
|
}
|
|
|
|
SetWindowPos(0, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOZORDER | SWP_SHOWWINDOW);
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CXTPReportInplaceButton, CStatic)
|
|
//{{AFX_MSG_MAP(CXTPReportInplaceButton)
|
|
ON_WM_PAINT()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_LBUTTONDBLCLK()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_CAPTURECHANGED()
|
|
ON_WM_TIMER()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
void CXTPReportInplaceButton::OnPaint()
|
|
{
|
|
CPaintDC dc(this);
|
|
|
|
if (pControl)
|
|
{
|
|
pControl->GetPaintManager()->DrawInplaceButton(&dc, this);
|
|
}
|
|
}
|
|
|
|
void CXTPReportInplaceButton::OnFinalRelease()
|
|
{
|
|
if (m_hWnd != NULL)
|
|
DestroyWindow();
|
|
|
|
CCmdTarget::OnFinalRelease();
|
|
}
|
|
|
|
void CXTPReportInplaceButton::OnLButtonDown(UINT, CPoint point)
|
|
{
|
|
switch(m_nID)
|
|
{
|
|
case XTP_ID_REPORT_COMBOBUTTON :
|
|
case XTP_ID_REPORT_EXPANDBUTTON :
|
|
m_bOver = m_bPressed = TRUE;
|
|
break;
|
|
case XTP_ID_REPORT_SPINBUTTON :
|
|
{
|
|
CXTPClientRect rect(this);
|
|
m_bOver = TRUE;
|
|
rect.bottom -= rect.Height() / 2;
|
|
m_nState = rect.PtInRect(point) ? SPNP_UP : SPNP_DOWN;
|
|
|
|
m_nSpinIncrement = m_nState == SPNP_UP ? m_nSpinStep : -m_nSpinStep;
|
|
|
|
pItem->OnInplaceButtonDown(this);
|
|
|
|
// start timer
|
|
m_unSpinTimerCnt = 0;
|
|
m_unSpinTimerId = SetTimer(1, 500, NULL);
|
|
break;
|
|
}
|
|
}
|
|
Invalidate(FALSE);
|
|
SetCapture();
|
|
}
|
|
|
|
void CXTPReportInplaceButton::OnLButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
if ((m_bPressed || m_nState) && pItem)
|
|
{
|
|
if(m_unSpinTimerId)
|
|
{
|
|
KillTimer(1);
|
|
m_unSpinTimerId = 0;
|
|
}
|
|
m_nSpinIncrement = 0;
|
|
m_unSpinTimerCnt = 0;
|
|
m_bPressed = FALSE;
|
|
m_nState = 0;
|
|
Invalidate(FALSE);
|
|
ReleaseCapture();
|
|
if (m_bOver && m_nID != XTP_ID_REPORT_SPINBUTTON)
|
|
{
|
|
pItem->OnInplaceButtonDown(this);
|
|
}
|
|
}
|
|
CStatic::OnLButtonUp(nFlags, point);
|
|
}
|
|
|
|
void CXTPReportInplaceButton::OnLButtonDblClk(UINT nFlags, CPoint point)
|
|
{
|
|
UNREFERENCED_PARAMETER(nFlags);
|
|
|
|
if(m_nID == XTP_ID_REPORT_SPINBUTTON)
|
|
{
|
|
CXTPClientRect rect(this);
|
|
if (rect.PtInRect(point))
|
|
{
|
|
rect.bottom -= rect.Height() / 2;
|
|
m_nState = rect.PtInRect(point) ? SPNP_UP : SPNP_DOWN;
|
|
m_nSpinIncrement = m_nState == SPNP_UP ? 1 : -1;
|
|
pItem->OnInplaceButtonDown(this);
|
|
// start timer
|
|
m_unSpinTimerCnt = 0;
|
|
m_unSpinTimerId = SetTimer(1, 500, NULL);
|
|
}
|
|
Invalidate(FALSE);
|
|
SetCapture();
|
|
}
|
|
}
|
|
|
|
void CXTPReportInplaceButton::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
if (m_bPressed || m_nState)
|
|
{
|
|
CXTPClientRect rect(this);
|
|
BOOL bOver;
|
|
if(m_nID != XTP_ID_REPORT_SPINBUTTON)
|
|
bOver = rect.PtInRect(point);
|
|
else
|
|
{
|
|
bOver = rect.PtInRect(point) &&
|
|
(point.y < (rect.bottom - rect.Height() / 2) && m_nState == SPNP_UP ||
|
|
point.y >= (rect.bottom - rect.Height() / 2) && m_nState == SPNP_DOWN);
|
|
}
|
|
if ((bOver && !m_bOver) || (!bOver && m_bOver))
|
|
{
|
|
m_bOver = bOver;
|
|
if(m_nID == XTP_ID_REPORT_SPINBUTTON)
|
|
{
|
|
if(m_bOver)
|
|
{
|
|
m_nSpinIncrement = m_nState == SPNP_UP ? 1 : -1;
|
|
m_unSpinTimerCnt = 0;
|
|
m_unSpinTimerId = SetTimer(1, 500, NULL); // start timer
|
|
}
|
|
else if(m_unSpinTimerId)
|
|
{
|
|
// stop timer
|
|
KillTimer(1);
|
|
m_nSpinIncrement = 0;
|
|
m_unSpinTimerCnt = 0;
|
|
m_unSpinTimerId = 0;
|
|
}
|
|
}
|
|
Invalidate(FALSE);
|
|
}
|
|
}
|
|
|
|
CStatic::OnMouseMove(nFlags, point);
|
|
}
|
|
|
|
void CXTPReportInplaceButton::OnCaptureChanged(CWnd* pWnd)
|
|
{
|
|
m_bPressed = FALSE;
|
|
m_nState = 0;
|
|
Invalidate(FALSE);
|
|
|
|
CStatic::OnCaptureChanged(pWnd);
|
|
}
|
|
|
|
void CXTPReportInplaceButton::OnTimer(UINT_PTR nIDEvent)
|
|
{
|
|
if(m_unSpinTimerCnt == 0 && abs(m_nSpinIncrement) < 10)
|
|
{
|
|
// first timer event, reset timer
|
|
KillTimer(1);
|
|
m_unSpinTimerId = SetTimer(1, 100, NULL);
|
|
}
|
|
m_unSpinTimerCnt++;
|
|
if(m_unSpinTimerCnt >= 20 && abs(m_nSpinIncrement < 100000))
|
|
{
|
|
m_nSpinIncrement *= 10;
|
|
m_unSpinTimerCnt = 0;
|
|
}
|
|
pItem->OnInplaceButtonDown(this);
|
|
|
|
CStatic::OnTimer(nIDEvent);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CXTPReportInplaceList
|
|
|
|
CXTPReportInplaceList::CXTPReportInplaceList()
|
|
{
|
|
m_bApply = FALSE;
|
|
m_dwLastKeyDownTime = 0;
|
|
}
|
|
|
|
|
|
void CXTPReportInplaceList::Create(XTP_REPORTRECORDITEM_ARGS* pItemArgs, CXTPReportRecordItemConstraints* pConstaints)
|
|
{
|
|
SetItemArgs(pItemArgs);
|
|
|
|
CRect rect(pItemArgs->rcItem);
|
|
|
|
if (!m_hWnd)
|
|
{
|
|
CListBox::CreateEx(WS_EX_TOOLWINDOW | (pControl->GetExStyle() & WS_EX_LAYOUTRTL), _T("LISTBOX"), _T(""), LBS_NOTIFY | WS_CHILD | WS_BORDER | WS_VSCROLL, CRect(0, 0, 0, 0), pControl, 0);
|
|
SetOwner(pControl);
|
|
}
|
|
|
|
SetFont(pControl->GetPaintManager()->GetTextFont());
|
|
ResetContent();
|
|
|
|
int dx = rect.right - rect.left + 1;
|
|
|
|
CWindowDC dc(pControl);
|
|
CXTPFontDC font(&dc, GetFont());
|
|
int nThumbLength = GetSystemMetrics(SM_CXHTHUMB);
|
|
|
|
CString strCaption = pItem->GetCaption(pColumn);
|
|
DWORD dwData = pItem->GetSelectedConstraintData(pItemArgs);
|
|
|
|
for (int i = 0; i < pConstaints->GetCount(); i++)
|
|
{
|
|
CXTPReportRecordItemConstraint* pConstaint = pConstaints->GetAt(i);
|
|
CString str = pConstaint->m_strConstraint;
|
|
int nIndex = AddString(str);
|
|
SetItemDataPtr(nIndex, pConstaint);
|
|
|
|
dx = max(dx, dc.GetTextExtent(str).cx + nThumbLength);
|
|
|
|
if ((dwData == (DWORD)-1 && strCaption == str) || (dwData == pConstaint->m_dwData))
|
|
SetCurSel(nIndex);
|
|
}
|
|
|
|
int nHeight = GetItemHeight(0);
|
|
rect.top = rect.bottom;
|
|
rect.bottom += nHeight * min(10, GetCount()) + 2;
|
|
rect.left = rect.right - dx;
|
|
|
|
pControl->ClientToScreen(&rect);
|
|
|
|
CRect rcWork = XTPMultiMonitor()->GetWorkArea(rect);
|
|
if (rect.bottom > rcWork.bottom && rect.top > rcWork.CenterPoint().y)
|
|
{
|
|
rect.OffsetRect(0, - rect.Height() - pItemArgs->rcItem.Height());
|
|
}
|
|
|
|
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();
|
|
|
|
if (!m_hWnd) // Can be destroyed after focus set
|
|
return;
|
|
|
|
SetWindowLongPtr(m_hWnd, GWLP_HWNDPARENT, 0);
|
|
ModifyStyle(WS_CHILD, WS_POPUP);
|
|
SetWindowLongPtr(m_hWnd, GWLP_HWNDPARENT, (LONG_PTR)pControl->m_hWnd);
|
|
|
|
SetWindowPos(&CWnd::wndTopMost, rect.left, rect.top, rect.Width(), rect.Height(), SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
|
|
|
|
CXTPMouseMonitor::SetupHook(this);
|
|
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CXTPReportInplaceList, CListBox)
|
|
//{{AFX_MSG_MAP(CXTPReportInplaceList)
|
|
ON_WM_MOUSEACTIVATE()
|
|
ON_WM_KILLFOCUS()
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_CHAR()
|
|
ON_WM_KEYDOWN()
|
|
ON_WM_SYSKEYDOWN()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
int CXTPReportInplaceList::OnMouseActivate(CWnd* /*pDesktopWnd*/, UINT /*nHitTest*/, UINT /*message*/)
|
|
{
|
|
return MA_NOACTIVATE;
|
|
}
|
|
|
|
void CXTPReportInplaceList::SetItemArgs(XTP_REPORTRECORDITEM_ARGS* pItemArgs)
|
|
{
|
|
m_bApply = FALSE;
|
|
CXTPReportInplaceControl::SetItemArgs(pItemArgs);
|
|
|
|
m_dwLastKeyDownTime = 0;
|
|
m_strHotSearchContext.Empty();
|
|
}
|
|
|
|
void CXTPReportInplaceList::PostNcDestroy()
|
|
{
|
|
CXTPMouseMonitor::SetupHook(NULL);
|
|
SetItemArgs(NULL);
|
|
|
|
CListBox::PostNcDestroy();
|
|
}
|
|
|
|
|
|
void CXTPReportInplaceList::OnKillFocus(CWnd* pNewWnd)
|
|
{
|
|
//ASSERT(pItem || m_bApply);
|
|
|
|
if (pItem && !m_bApply)
|
|
pItem->OnEditCanceled(this);
|
|
|
|
CListBox::OnKillFocus(pNewWnd);
|
|
DestroyWindow();
|
|
}
|
|
|
|
void CXTPReportInplaceList::OnLButtonUp(UINT, CPoint point)
|
|
{
|
|
CXTPClientRect rc(this);
|
|
|
|
if (rc.PtInRect(point))
|
|
Apply();
|
|
else
|
|
Cancel();
|
|
}
|
|
|
|
|
|
void CXTPReportInplaceList::Cancel()
|
|
{
|
|
m_bApply = FALSE;
|
|
|
|
GetOwner()->SetFocus();
|
|
}
|
|
|
|
void CXTPReportInplaceList::Apply()
|
|
{
|
|
if (!pControl)
|
|
return;
|
|
|
|
CXTPReportControl* pReportControl = pControl;
|
|
|
|
int nIndex = GetCurSel();
|
|
if (nIndex != LB_ERR)
|
|
{
|
|
m_bApply = TRUE;
|
|
|
|
CXTPReportRecordItemConstraint* pConstraint = (CXTPReportRecordItemConstraint*)GetItemDataPtr(nIndex);
|
|
|
|
XTP_REPORTRECORDITEM_ARGS itemArgs = *((XTP_REPORTRECORDITEM_ARGS*)this);
|
|
itemArgs.AddRef();
|
|
|
|
pItem->OnConstraintChanged(&itemArgs, pConstraint);
|
|
pReportControl->RedrawControl();
|
|
|
|
pReportControl->SendMessageToParent(itemArgs.pRow, itemArgs.pItem, itemArgs.pColumn, XTP_NM_REPORT_VALUECHANGED, 0);
|
|
|
|
itemArgs.Release();
|
|
}
|
|
|
|
pReportControl->SetFocus();
|
|
}
|
|
|
|
void CXTPReportInplaceList::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
UNREFERENCED_PARAMETER(nRepCnt); UNREFERENCED_PARAMETER(nFlags);
|
|
|
|
const DWORD cwdHotSearchTomeOut_ms = 1300;
|
|
|
|
DWORD dwTime = GetTickCount();
|
|
|
|
if (dwTime - m_dwLastKeyDownTime > cwdHotSearchTomeOut_ms)
|
|
m_strHotSearchContext.Empty();
|
|
|
|
m_dwLastKeyDownTime = dwTime;
|
|
|
|
//----------------------------------------------
|
|
m_strHotSearchContext += (TCHAR)nChar;
|
|
|
|
int nIndex = GetCurSel();
|
|
if (nIndex == LB_ERR)
|
|
nIndex = 0;
|
|
|
|
int nFindIdx = FindString(nIndex, m_strHotSearchContext);
|
|
|
|
if(nFindIdx == LB_ERR && nIndex > 0)
|
|
nFindIdx = FindString(0, m_strHotSearchContext);
|
|
|
|
if(nFindIdx != LB_ERR)
|
|
{
|
|
SetCurSel(nFindIdx);
|
|
|
|
if(nIndex != nFindIdx)
|
|
OnSelectionChanged(nFindIdx);
|
|
}
|
|
}
|
|
|
|
void CXTPReportInplaceList::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
switch(nChar)
|
|
{
|
|
case VK_UP:
|
|
case VK_DOWN:
|
|
case VK_PRIOR:
|
|
case VK_NEXT:
|
|
case VK_HOME:
|
|
case VK_END:
|
|
m_strHotSearchContext.Empty();
|
|
}
|
|
|
|
//----------------------------------------------
|
|
if (nChar == VK_ESCAPE)
|
|
{
|
|
Cancel();
|
|
}
|
|
else if (nChar == VK_RETURN || nChar == VK_F4)
|
|
{
|
|
Apply();
|
|
}
|
|
else
|
|
{
|
|
int nPrevSel = CListBox::GetCurSel();
|
|
CListBox::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
int nActualSel = CListBox::GetCurSel();
|
|
|
|
if(nPrevSel != nActualSel)
|
|
OnSelectionChanged(nActualSel);
|
|
}
|
|
}
|
|
|
|
void CXTPReportInplaceList::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
if (nChar == VK_DOWN || nChar == VK_UP)
|
|
{
|
|
Apply();
|
|
return;
|
|
}
|
|
|
|
CListBox::OnSysKeyDown(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
void CXTPReportInplaceList::OnSelectionChanged(int nLBIndex)
|
|
{
|
|
CString strActual, str;
|
|
CListBox::GetText(nLBIndex,strActual);
|
|
|
|
CXTPReportRecordItemEditOptions* pEditOptions = pItem->GetEditOptions(pColumn);
|
|
CXTPReportRecordItemConstraints* pConstraints = pEditOptions->GetConstraints();
|
|
|
|
int nCount = pConstraints->GetCount();
|
|
for(int nIndex = 0; nIndex < nCount; nIndex++)
|
|
{
|
|
CXTPReportRecordItemConstraint* pConstraint = pConstraints->GetAt(nIndex);
|
|
str = pConstraint->m_strConstraint;
|
|
|
|
if(strActual.CompareNoCase(str) == 0)
|
|
{
|
|
((CXTPReportControl*)pControl)->OnConstraintSelecting(pRow, pItem, pColumn, pConstraint);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|